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.

Solve gives me an expression which I want to use as the body of a function. Rather than run Solve every time inside my function body, I just want to take the rule output Solve already gave me, and repurpose it into something that accepts arguments.

For example, this works, but is slow because Solve runs in every invocation:

(* returns the two points where the line through pt {x1, y1} 
with slope m intersects the circle x^2 + y^2 = 100 *)
intersections[m_, x1_, y1_] :=
 Solve[y - y1 == m (x - x1) && 
    x^2 + y^2 == 100, {x, y}] /. Rule[_, val_] -> val

intersections[1, 0, 0]
(* result: *) {{-5 Sqrt[2], -5 Sqrt[2]}, {5 Sqrt[2], 5 Sqrt[2]}}

I've tried variations on below, but they don't work:

solution = Solve[y - y1 == m (x - x1) && 
     x^2 + y^2 == 100, {x, y}] /. Rule[_, val_] -> val /. {m -> #1, 
   x1 -> #2, y1 -> #3}

intersections[m_, x1_, y1_] := solution[m, x1, y1]

Below is almost what I want, but the rule replacements don't perform as well as real function arguments, and this is also dependent on copying around replacement symbol names:

solution = Solve[y - y1 == m (x - x1) && 
     x^2 + y^2 == 100, {x, y}] /. Rule[_, val_] -> val ;
intersections := solution /. { m -> #1, x1 -> #2, y1 -> #3} &;

How can I take the the expression Solve gave me, and "function-ify" it? Copy-pasting the expressions into a function works, but obviously I don't want to do that.

share|improve this question
    
Strongly related; arguably a duplicate: mathematica.stackexchange.com/q/6664/121 –  Mr.Wizard Dec 7 '12 at 19:23
add comment

2 Answers

up vote 1 down vote accepted

Use Block or Formal Symbols to guard against unwanted evaluation, then define your function using Set (=) rather than SetDelayed (:=). Might as well throw in a FullSimplify to clean it up a bit.

Block[{x, y, x1, y1, m},
  intersections[m_, x1_, y1_] = FullSimplify[
    {x, y} /. Solve[y - y1 == m (x - x1) && x^2 + y^2 == 100, {x, y}]
  ]
];

intersections[1, 0, 0]
{{-5 Sqrt[2], -5 Sqrt[2]}, {5 Sqrt[2], 5 Sqrt[2]}}

A look at the definition we created:

?intersections

Mathematica graphics

share|improve this answer
add comment

If you want to solve the equation once, and use the solution again, then you can try

sol = Solve[y - y1 == m (x - x1) && 4 x^2 + y^2 == 100, {x, y}];
intersections[mm_, xx1_, yy1_] :=
 {x /. sol /. {x1 -> xx1, m -> mm, y1 -> yy1},
  y /. sol /. {x1 -> xx1, m -> mm, y1 -> yy1}
 }

Now you can call it as

intersections[1, 2, 3]

which gives

{{(1/5)*(-1 - 4*Sqrt[31]), (1/5)*(-1 + 4*Sqrt[31])}, {4/5 - (4*Sqrt[31])/5, 4/5 + (4*Sqrt[31])/5}}

Solve is only called once as you asked for. The solution is used again and again

share|improve this answer
    
This is pretty much the same as my last example. –  latkin Dec 7 '12 at 19:30
add comment

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.