在Mathematica中为线性方程创建随机系数

5

以下方程中,是否有一种方法可以为p1、p2、p3和p4指定随机值?

p1 y1 + p2 y2 + p3 y3 = p4

已知y1、y2和y3是要解决的变量。


系数需要具有特定的分布吗?正态分布?均匀分布? - Andrew Walker
不,只是随机的实数或整数。 - penny
@penny:这可能意味着你想要一个均匀分布... - Simon
5个回答

9
最简单的方法是通过在替换规则上Thread一个随机值列表:
例如:
p1 y1 + p2 y2 + p3 y3 == p4 /. Thread[{p1, p2, p3, p4} -> RandomReal[{0, 1}, 4]]

(* 0.345963 y1 + 0.333069 y2 + 0.565556 y3 == 0.643419 *)

或者,受Leonid的启发,您可以使用Alternatives和模式匹配:
p1 y1 + p2 y2 + p3 y3 == p4 /. p1 | p2 | p3 | p4 :> RandomReal[]

仅供娱乐,这里有另一种类似的解决方案:

p1 y1 + p2 y2 + p3 y3 == p4 /. s_Symbol :> 
     RandomReal[]/;StringMatchQ[SymbolName[s], "p"~~DigitCharacter]

如果您想匹配不仅仅是 p0, p1, ..., p9,可以将 DigitCharacter 替换为 NumberString。当然,对于大型表达式,上述方法并不特别高效...


+1. 如果您按照我建议使用Alternatives,则应该使用延迟规则,否则所有数字都将相同。 - Leonid Shifrin
@Leonid:哎呀……我以为我做了! - Simon

7

其他答案都不错,但是如果你经常进行这种操作,我建议你以更系统化的方式命名变量和系数。这不仅可以让你编写更简单的规则,还可以在从3个方程式转换为4个方程式时使更改变得更加简单。例如:

In[1]:= vars   = Array[y, 3] 
Out[1]= {y[1], y[2], y[3]}

In[2]:= coeffs = Array[p, 4]
Out[2]= {p[1], p[2], p[3], p[4]}

当你制作方程式时,可以稍微花点心思:

In[3]:= vars . Most[coeffs] == Last[coeffs]
Out[3]= p[1] y[1] + p[2] y[2] + p[3] y[3] == p[4]

用随机数替换系数现在是一个非常基本的规则之一:
In[4]:= sub = eqn /. p[_] :> RandomReal[] 
Out[4]= 0.281517 y[1] + 0.089162 y[2] + 0.0860836 y[3] == 0.915208

规则也可以写成 _p :> RandomReal[],如果你喜欢的话。解决这个问题也不需要输入太多内容。
In[5]:= Reduce[sub]
Out[5]= y[1] == 3.25099 - 0.31672 y[2] - 0.305785 y[3]

Andrew Walker所说,您可以使用Reduce来查找所有解,而不仅仅是一些解。您可以将其包装在一个函数中,该函数参数化变量的数量,如下所示:
In[6]:= reduceRandomEquation[n_Integer] := 
          With[{vars = Array[y, n], coeffs = Array[p, n+1]},
            Reduce[vars . Most[coeffs]]

In[7]:= reduceRandomEquation[4]
Out[7]= y[1] == 2.13547 - 0.532422 y[2] - 0.124029 y[3] - 2.48944 y[4]

4

如果您需要替换值的解决方案,一种可能的方法是:

f[y1_, y2_, y3_] := p1 y1 + p2 y2 + p3 y3 - p4
g = f[y1, y2, y3] /. p1 -> RandomReal[] /. p2 -> RandomReal[] /. 
   p3 -> RandomReal[] /. p4 -> RandomReal[]
Reduce[g == 0, {y1}]
Reduce[g == 0, {y2}]
Reduce[g == 0, {y3}]

如果您只需要解方程的解决方案:

f[y1_, y2_, y3_] := p1 y1 + p2 y2 + p3 y3 - p4
g = f[y1, y2, y3]
Solve[g == 0, {y1}]
Solve[g == 0, {y2}]
Solve[g == 0, {y3}]

reduce函数是用来做什么的?它是否必要? - penny
1
Reduce与Solve类似,但会找到所有的解。在这种情况下,使用Solve就足够了。 - Andrew Walker
3
你的解决方案可以稍微简化一下:f[y1, y2, y3] /. p1 | p2 | p3 | p4 :> RandomReal[] - Leonid Shifrin
哦,事实上,我现在不想解决这个问题。我只需要把方程式拿出来。 - penny
@Leonid - 谢谢你的简化,有新的尝试! :) - Andrew Walker

3
如果您可以不使用符号系数名称p1等,那么您可以按照以下方式生成。我们需要一个变量列表、方程的数量以及系数和右手边向量的范围。
In[80]:= randomLinearEquations[vars_, n_, crange_] := 
 Thread[RandomReal[crange, {n, Length[vars]}].vars == 
   RandomReal[crange, n]]

In[81]:= randomLinearEquations[{x, y, z}, 2, {-10, 10}]

Out[81]= {7.72377 x - 4.18397 y - 4.58168 z == -7.78991, -1.13697 x + 
   5.67126 y + 7.47534 z == -6.11561}

获取整数系数、矩阵和右手边的不同范围等变体非常简单。

Daniel Lichtblau


2
另一种方法:
dim = 3;
eq = Array[p, dim].Array[y, dim] == p[dim + 1];
Evaluate@Array[p, dim + 1] = RandomInteger[10, dim + 1]

Solve[eq, Array[y, dim]]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接