Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I understand Mathematica can't assign the results of a Solve to the unknowns because there may be more than 1 solution. How can I assign the 4 values of following result to variables?

enter image description here

share|improve this question
    
Could you elaborate on what you are trying to achieve? In principle you can use Replace (or Part) to assign the values to variables. –  sebhofer Jun 11 '12 at 13:36
    
@sebhofer - I want to assign the first x value to a variable X1, then the y value to Y1, the other two to X2 and Y2. I just don't seem to get the hang of references yet. –  stevenvh Jun 11 '12 at 13:40

5 Answers 5

up vote 14 down vote accepted

You can do this :

s = Solve[y^2 == 13 x + 17 && y == 193 x + 29, {x, y}];
xx = s[[All, 1, 2]];
yy = s[[All, 2, 2]];

Now you can access solutions, this way xx[[1]], yy[[2]].

If you prefer to collect solutions in Array, there is another way :

X = Array[ x, {Length@s}];
Y = Array[ y, {Length@s}];
x[k_] /; MemberQ[ Range[ Length @ s], k] := s[[k, 1, 2]]
y[k_] /; MemberQ[ Range[ Length @ s], k] := s[[k, 2, 2]]

now X is equivalent to s[[All, 1, 2]], while Y to s[[All, 2, 2]], e.g. :

X[[1]] == x[1]
Y == s[[All, 2, 2]]
True
True

You do not have to use or even to define X and Y arrays, e.g.

{x[1], y[1]}
{(-11181 - Sqrt[2242057])/74498, 1/386 (13 - Sqrt[2242057])}

We've used Condition i.e. /; to assure definitions of x[i], y[i] only for i in an appropriate range determined by Length @ s, i.e. number of solutions.

share|improve this answer
2  
I think the OP is a complete beginner, and all he's looking for is ReplaceAll. This might be a bit too advanced for someone new to Mma. –  Szabolcs Jun 11 '12 at 13:57
    
@Szabolcs Literally there is the assignment tag, so he is rather looking for Set or SetDelayed applications. –  Artes Jun 11 '12 at 16:07
    
I think I'll use your first solution for now, until I get the hang of ReplaceAll. @Szabolcs: Yes, Mma virgin. Thanks, all. –  stevenvh Jun 12 '12 at 7:09
    
@stevenvh I think this answer can be also interesting for you : mathematica.stackexchange.com/questions/1819/… –  Artes Jul 12 '12 at 11:17

Ah, they finally implemented it in version 10, then! Here's a procedure I've been using since version 5, it might provide similar features in versions prior to the introduction of Value. (I'm not sure, but maybe I posted it on the MathGroup... so forgive me if this is not news)

I had called it "ToValues". I gave it two options:

Options[ToValues] = {
      Flattening -> Automatic, IndexedFunction -> False};

The help message is hopefully self-explicating:

ToValues::usage =
    "ToValues[li] 
    suppresses the Rule wrapper in every part of list li.\n ToValues[li,F] \
applies the function F to every rhs of Rule, turning var->value into \
F[value]. If the function F has a parametrized head, then it is possible to \
pass the lhs of Rule to it by setting the option IndexedFunction->True. It will \
turn var->value into F[var][value].\n When the option Flattening is set to \
Automatic, ToValues flattens li to yield a simplified structure (the \
flattening is tuned to get the simplest list of values for the solution of a \
system of several equation in several variables). With Flattening set to None \
the original structure is left intact.";

The code is really short.

ToValues[li_, opts___Rule] := Module[
    {newli, vars, sols, fl},
    fl = Flattening /. {opts} /. Options[ToValues];
    sols = First[Dimensions[li]]; vars = Last[Dimensions[li]];
    newli = li /. Rule[_, v_] -> v;
    If[fl == Automatic && vars == 1, newli = Flatten[newli]];
    If[fl == Automatic && sols == 1, First[newli], newli]
    ]

ToValues[li_, fun_, opts___Rule] := 
  Module[
    {newli, vars, sols, foo, fl, mi},
    mi = IndexedFunction /. {opts} /. Options[ToValues];
    fl = Flattening /. {opts} /. Options[ToValues];
    If[mi == True,
          newli = li /. (x_ -> v_) -> foo[x][v],
          newli = li /. (_ -> v_) -> foo[v]
      ];
    sols = First[Dimensions[li]]; vars = Last[Dimensions[li]];
    If[fl == Automatic && vars == 1, newli = Flatten[newli]];
    If[fl == Automatic && sols == 1, First[newli], newli] //. foo -> fun
]

Example data:

sols = {{x -> 1}, {y -> 2}, {z -> 3}};

Application of ToValues to lists of rules

ToValues[sols] // InputForm

{1, 2, 3}

Of course assignment is immediate, here

{x1,x2,x3} = ToValues[sols]

This is what the Flattening option does:

ToValues[sols, Flattening -> None] // InputForm

{{1}, {2}, {3}}

Application of ToValues with parametric function

F[var_][value_] := {var, value}

ToValues[sols, F] // InputForm

{F[1], F[2], F[3]}

ToValues[sols, F, IndexedFunction -> True] // InputForm

{{x, 1}, {y, 2}, {z, 3}}

ToValues[sols, F, IndexedFunction -> True, Flattening -> None] // InputForm

{{{x, 1}}, {{y, 2}}, {{z, 3}}}

Real world applications:

Solve[{x + y == 1, x - y == 2}] // ToValues

{3/2, 1/2}

This gives a list of the complex solutions

Solve[x^5 == 1] // ToValues

This uses the optional function to compute the real and imaginary part of each solution

pts = ToValues[Solve[x^5 == 1, x], {Re[#], Im[#]} &] // N;
ListPlot[pts, AspectRatio -> Automatic, Frame -> 
      True, PlotStyle -> PointSize[.018]];

And this pushes the function to create graphics objects based on those values

pts = ToValues[Solve[x^9 == 1, x], Point[{Re[#], Im[#]}] &];
Show[Graphics[{PointSize[.018], pts}],
    AspectRatio -> 1, Frame -> True, Axes -> True];

Someone who has patience enough might want to add the plots.

share|improve this answer

Update: Version 10 built-in function Values does value extraction conveniently for rules appearing in lists of arbitrary lengths and depths:

{{x1, y1}, {x2, y2}} = Values[Solve[y^2 == 13 x + 17 && y == 193 x + 29, {x, y}]]
(* {{(-11181-Sqrt[2242057])/74498,1/386 (13-Sqrt[2242057])}, 
    {(-11181+Sqrt[2242057])/74498,1/386 (13+Sqrt[2242057])}} *)

Another example:

lst={{a->1,b->2},{c->3},{{d->4}},{e->5,{f->6,{g->7}}}};
Values[lst]
(* {{1,2},{3},{{4}},{5,{6,{7}}}} *)

Original post:

{{x1, y1}, {x2, y2}} = Solve[y^2 == 13 x + 17 && y == 193 x + 29, {x, y}][[All, All, -1]]
(* {{(-11181 - Sqrt[2242057])/74498, 1/386 (13 - Sqrt[2242057])}, 
    {(-11181 + Sqrt[2242057])/74498, 1/386 (13 + Sqrt[2242057])}} *)

{x1, y2}
(* {(-11181- Sqrt[2242057]) / 74498, 1 / 386 (13 + Sqrt[2242057])} *)
share|improve this answer
    
I'm sorry you've deleted your previous answer nevertheless suppresing duplicates we reduce increasing overall entropy of this site, +1. –  Artes Sep 19 '14 at 21:07
    
@artes, thank you for the upvote. I agree with your concern over excessive duplicates. The other Q/A is indeed a special case of this one. However, because of its special structure, some tricks that work there do not work here, e.g Last@@@Solve[...]. –  kglr Sep 19 '14 at 21:16

Usually you don't want to actually assign values to x and y, and you would use replacement rules instead:

sols = Solve[y^2 == 13 x + 17 && y == 193 x + 29, {x, y}];

{x, y} /. sols[[1]]

or for the second solution:

{x, y} /. sols[[2]]

If you really want to assign values to x and y globally, you could use:

Set @@@ sols[[1]]

but you must clear x and y before using another set:

Clear[x, y]
Set @@@ sols[[2]]

If you want to assign values to x and y within a Block you could do something like this:

Hold @@ {sols[[2]]} /. Rule -> Set /. _[vars_] :>
  Block[vars,
   Sin[x] + Sqrt[y] // N
  ]

This uses what I am calling the injector pattern to get the values into Block in the right syntax without it prematurely evaluating.


Related questions:

Getting rid of the “x ->” in FindInstance results

Using the output of Solve

share|improve this answer
1  
+1.Something related to your last comment and the injector pattern. –  Leonid Shifrin Jun 11 '12 at 14:05

If you really wish to assign solutions to variables, you can do something like this:

In[1]:= ClearAll[Subscript]
sols=Solve[y^2==13x+17&&y==193x+29,{x,y}];
i=0;
sols/.{r__Rule}:>Set@@@({r}/.var:x|y->Subscript[var,++i]);
Subscript//Definition

Out[5]=

Subscript[x,1]=(-11181-Sqrt[2242057])/74498
Subscript[x,2]=(-11181+Sqrt[2242057])/74498
Subscript[y,1]=1/386(13-Sqrt[2242057])
Subscript[y,2]=1/386 (13+Sqrt[2242057])

Then you can use the solutions for demonstration purposes:

enter image description here

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.