solvingTransformations.frink


// These transformations try to solve simple equations and teach Frink to
// solve basic algebraic equations for the specified variable.
//
//  For example, enter:
//    solve[3(x+y) == 10, x]
//
// (Right now this requires the double-equals sign because Frink currently
//  requires that the left-hand-side of an assignment operator
//  ( = ) can actually be meaningfully assigned to, which may be
// a constraint that needs to get loosened for temporary values.

// This creates a named list of transformations called "solving" that we
// can apply by name later.
transformations solving
{
   // Move the variable we're solving for to the left side of the equation
   // if it's only on the right side of the equation.
   solve[_left == _right, _x] :: (freeOf[_left, _x] AND expressionContains[_right, _x])  <-> solve[_right == _left, _x]

   // Bailout condition
   solve[_x == _z, _x] :: freeOf[_z, _x]  <-> _x = _z

   // Quadratic equations 
   solve[(_a:1) _x^2 + (_b:1) _x == _c, _x] :: freeOf[_c, _x] <-> [ solve[_x == (-_b + (_b^2 - 4 _a (-_c))^(1/2)) / (2 _a), _x], solve[_x == (-_b - (_b^2 - 4 _a (-_c))^(1/2)) / (2 _a), _x] ]


   // If both sides have an x, divide out x terms from right.
//   solve[_a == (_c:1) _x^(_b:1), _x] :: expressionContains[_a, _x] <-> solve[_a / _x^_b == _c, _x]

   // First move additive terms
   // Move all x-containing terms to left
   solve[_a == _c, _x] :: (expressionContains[_a, _x] && expressionContains[_c, _x]) <-> solve[_a - _c == 0, _x]

   // Move all non-x-containing terms to right.
    solve[_a + _b == _c, _x] :: (freeOf[_a,_x] AND expressionContains[_b, _x]) <-> solve[_b == _c - _a, _x]

   // Then move multiplicative terms.
   solve[_a * _b == _c, _x] :: (freeOf[_a,_x] AND expressionContains[_b, _x]) <-> solve[_b == _c / _a, _x]


   // Flip inverse exponents.
   solve[_a^_k == _b, _c] :: expressionContains[_a, _c] AND (_k < 0) <-> solve[1/(_a^_k) == 1/_b, _c]

   // Solve for squared terms.
   // Results are a list of two different solutions.
   solve[_a^_k == _b, _c] :: expressionContains[_a, _c] AND (_k > 0) AND (_k mod 2 == 0) <-> [ solve[_a^(_k/2) == _b^(1/2),_c] , solve[_a^(_k/2) == -_b^(1/2), _c ] ]

   // Some simplifying rules that actually aren't appropriate if you're
   // tracking units.  These are not really valid because 0 feet != 0 days
   // and 0 feet + 0 is not units-correct.
   0 _x <-> 0
   
   _x + 0 <-> _x

   // Exponentiate out parts
   (_a _b)^_c <-> _a^_c _b^_c
    
   // Distribute (to often clarify and simplify)
   _a (_c + _d) <-> _a _c + _a _d

//   (_a + _b)^_k :: isInteger[_k] AND _k >= 2  <->  (_a^2 + 2 _a _b + _b^2)(_a + _b)^(_k-2)
}


"solvingTransformations.frink included ok!"


View or download solvingTransformations.frink in plain text format


This is a program written in the programming language Frink.
For more information, view the Frink Documentation or see More Sample Frink Programs.

Alan Eliasen was born 14705 days, 19 hours, 59 minutes ago.