Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating random coefficients for linear equations in mathematica

Is there a way to assign a random value to p1, p2, p3 and p4 for the following equation?

p1 y1 + p2 y2 + p3 y3 = p4

given that y1, y2 and y3 are variables to be solved.

like image 446
penny Avatar asked Sep 16 '11 09:09

penny


4 Answers

The easiest(?) way is to Thread a list of random values over a replacement rule:

For example:

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 *)

Or, inspired by Leonid, you can use Alternatives and pattern matching:

p1 y1 + p2 y2 + p3 y3 == p4 /. p1 | p2 | p3 | p4 :> RandomReal[]

Just for fun, here's one more, similar solution:

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

Where you could replace DigitCharacter with NumberString if you want it to match more than just p0, p1, ..., p9. Of course, for large expressions, the above won't be particularly efficient...

like image 188
Simon Avatar answered Oct 04 '22 21:10

Simon


The other answers are good, but if you do a lot of this sort of thing, I recommend naming your variables and coefficients in a more systematic way. This will not only allow you to write a much simpler rule, it will also make for much simpler changes when it's time to go from 3 equations to 4. For example:

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]}

You can be a little fancy when you make your equation:

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

Substituting random numbers for the coefficients is now one one very basic rule:

In[4]:= sub = eqn /. p[_] :> RandomReal[] 
Out[4]= 0.281517 y[1] + 0.089162 y[2] + 0.0860836 y[3] == 0.915208

The rule at the end could also be written _p :> RandomReal[], if you prefer. You don't have to type much to solve it, either.

In[5]:= Reduce[sub]
Out[5]= y[1] == 3.25099 - 0.31672 y[2] - 0.305785 y[3]

As Andrew Walker said, you use Reduce to find all the solutions, instead of just some of them. You can wrap this up in a function which paramerizes the number of variables like so:

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]
like image 24
Pillsy Avatar answered Oct 04 '22 21:10

Pillsy


If you need solutions with values substituted in, one possible way to do this is:

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}]

If all you need is the solution to the equations:

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}]
like image 43
Andrew Walker Avatar answered Oct 04 '22 22:10

Andrew Walker


If you can live without the symbolic coefficient names p1 et al, then you might generate as below. We take a variable list, and number of equations, and a range for the coefficients and rhs vector.

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}

It is straightforward to obtain variants such as integer coefficients, different ranges for matrix and rhs, etc.

Daniel Lichtblau

like image 30
Daniel Lichtblau Avatar answered Oct 04 '22 21:10

Daniel Lichtblau