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.

Suppose I have an equation relating a number of variables and I know the values of all but one of them. Using the equation and known values as input, is there a simple command (built-in or otherwise) to determine the missing value?

Original example:

Consider the formula for the area of a rectangle. I can write the formula as area[length_, width_] := length*width and plug in numbers for the dimensions and get the area. Also, I could write a formula for finding each specific dimension in terms of the remaining two. My question is this: Is there a way to write a single expression which will do the whole job, that is I can plug in any two of the components of the area formula and have Mathematica return the third?

So for instance, if

equation = area == area[length, width]

and let's say the area is 5 and the length is 2. The output should be

{area -> 5, length -> 2, width -> 5/2}

or simply

width -> 5/2

Response to comment: I'm not sure what the syntax should look like. Preferably it would be expressive and natural (obviously). Maybe area -> 5 or area == 5 is a natural way to code a given value; or maybe even as an argument. [Edit note, Michael E2: I don't know what the OP had mind. I don't want to restrict the question too much here, esp. if someone has a really nice way of doing it. I hope it is sufficient that the equation and all but one value of the variables are known and can be used as input.]

share|improve this question
    
Yes, what you ask for can be done with Manipulate. –  m_goldberg Mar 28 '14 at 13:07
1  
maybe it would help if you showed examples of what you expect the syntax to look like. The question title doesn't reflect at all what you are asking by the way. –  george2079 Mar 28 '14 at 13:26
    
@george2079. The title is my edit, not the OP's original title. It's my best shot at describing what the OP is asking. Since you think it's way off target, please edit it to get it on target. –  m_goldberg Mar 28 '14 at 21:25

2 Answers 2

up vote 3 down vote accepted
rectangle[{r1_Rule, r2_Rule}] :=
     (#~Join~First@Solve[ (e1 e2 == area) /. # , 
      First@Complement[ {area, e1, e2}, First /@ #] ]) &@{r1, r2}

rectangle[{e2 -> 3, e1 -> 2}]

{e2 -> 3, e1 -> 2, area -> 6}

rectangle[{area -> 12, e1 -> 2}]

{area -> 12, e1 -> 2, e2 -> 6}

share|improve this answer

Update

Another variation. This one shows that basically, with the right input, the solution the OP is after is simply Solve.

ClearAll[solveMissing];
solveMissing[eqns_, knowns : {_[_Symbol, _] ...}] := 
 Solve@Flatten[{eqns, Equal @@@ knowns}]

The original examples (below) may be written without specifying all variables, as follows:

solveMissing[area == length*width, {{length, 2}, {width, 4}}]
solveMissing[area == length*width, {{area, 8}, {width, 4}}]
solveMissing[area == length*width, {{width, 4}}]
solveMissing[volume == Pi*radius^2*height, {{volume, 12 Pi}, {height, 3}}]

(*
  {{area -> 8, length -> 2, width -> 4}}
  {{area -> 8, length -> 2, width -> 4}}
  {{area -> 4 length, width -> 4}}
  { {height -> 3, radius -> -2, volume -> 12 π},
    {height -> 3, radius -> 2, volume -> 12 π}}
*)

These variations are also allowed, if not preferred:

solveMissing[area == length*width, {length -> 2, width -> 4}]
solveMissing[area == length*width, {length == 2, width == 4}]
(* {{area -> 8, length -> 2, width -> 4}} *)

Or use Solve directly:

Solve[{area == length*width, length == 2, width == 4}]
(* {{area -> 8, length -> 2, width -> 4}} *)

Note: The pattern _[_Symbol, _] allows any head (that does not evaluate to something else), even ones that don't make sense. Stricter checking might be desired in some cases. For instance, (List | Rule | Equal)[_Symbol, _].

Original answer

A variation:

solveMissing[eqn_, vars_] := Solve[
  Append[Equal @@@ Cases[vars, {_Symbol, _}], eqn],
  Replace[vars, {x_Symbol, _} :> x, 1]]

Examples:

solveMissing[area == length*width, {area, {length, 2}, {width, 4}}]
solveMissing[area == length*width, {{area, 8}, length, {width, 4}}]
(*
  {{area -> 8, length -> 2, width -> 4}}
  {{area -> 8, length -> 2, width -> 4}}
*)

solveMissing[area == length*width, {area, length, {width, 4}}]
(*
  Solve::svars: Equations may not give solutions for all "solve" variables. >>
  {{area -> 4 length, width -> 4}}
*)

solveMissing[volume == Pi * radius^2 * height, {{volume, 12 Pi}, radius, {height, 3}}]
(*
  {{volume -> 12 π, radius -> -2, height -> 3},
   {volume -> 12 π, radius -> 2, height -> 3}}
*)
share|improve this answer
    
I like this abstraction. Would you consider editing the question to fit this such that it might be reopened? –  Mr.Wizard Jun 26 at 16:56
    
@Mr.Wizard Done (or attempted to do so). I have an improvement in mind, but I'll hold off until it is reopened out of some sense of fairness. Or I might completely lose track and forget about it. –  Michael E2 Jun 27 at 16:03

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.