powerTransformations.frink

Download or view powerTransformations.frink in plain text format


// The dependency on LambertW.frink brings in dependencies on
// ArbitraryPrecision.frink and pi.frink.  You can comment
// out the "use" statement below without problems; you just won't be able
// to get a numerical result for the LambertW function; it will just give
// a symbolic result.
use LambertW.frink

/** This contains solvers for equations containing exponents.  It is generally
    only intended for real-valued arguments and will not always find all
    solutions.
*/

transformations power
{
   // Turn exp[x] into e^x
   exp[_x] <-> e^_x

   // Solve x^y === z for y
   //   or, more generally, this solves
   // (a x)^((k y)^n) === z for y
   solve[((_a:1) _x) ^ (((_k:1) _y)^(_n:1)) === _z, _y] :: freeOf[_k, _y] && freeOf[_a, _y] && freeOf[_n, _y] && freeOf[_z, _y] <-> solve[_y === (ln[_z] / (ln[_a _x])^(1/_n)) / _k, _y]

   // Solve c a^y b^y === z for y
   solve[(_c:1) _a^_y _b^_y === _z, _y] :: freeOf[_a, _y] && freeOf[_b, _y] && freeOf[_c, _y] && freeOf[_z, _y] <-> solve[_y === ln[_z / _c] / (ln[_a] + ln[_b]), _y]

   // Solve x^y === z for x  for irrational exponents.  (Rational exponents
   // are solved better in solvingTransformations.frink )
   solve[_x ^ _y === _z, _x] :: freeOf[_z, _x] && ! isInteger[_y] && ! isRational[_y] <-> solve[_x === _z^(1/_y), _x]

   // Solve ln[a] === b  when a contains the variable y we're solving for.
   // This is only valid for the reals or complex
   // numbers where  -pi < Im[y] <= pi
   // Basically, we take the exp() of both sides.
   solve[ln[_a] === _b, _y] :: freeOf[_b, _y] and expressionContains[_a, _y] <-> solve[_a === e^_b, _y]

   // Solve log[a] === b  when a contains the variable y we're solving for.
   // Basically, we take the 10^ of both sides.
   solve[log[_a] === _b, _y] :: freeOf[_b, _y] and expressionContains[_a, _y] <-> solve[_a === 10^_b, _y]
   
   // Solve _b^_a = x  when a contains the variable y we're solving for.
   // This does not find all solutions.
   // Basically, take log of both sides to base _b.
   // The exclusions for integer and rational arguments are because these
   // are better solved (finding more solutions) by the routines in
   // solvingTransformations.frink
   solve[_b^_a === _x, _y] :: freeOf[_x, _y] and freeOf[_b, _y] and expressionContains[_a, _y] && ! isInteger[_a] && ! isRational[_a] <-> solve[_a === ln[_x] / ln[_b], _y]

   // Solve _b^_a = x  when b contains the variable y we're solving for.
   // This does not find all solutions.
   // Basically, take log of both sides to base _b.
   // The exclusions for integer and rational arguments are because these
   // are better solved (finding more solutions) by the routines in
   // solvingTransformations.frink
   solve[_b^_a === _x, _y] :: freeOf[_x, _y] and freeOf[_a, _y] and expressionContains[_b, _y] && ! isInteger[_a] && ! isRational[_a] <-> solve[ln[_b] === ln[_x] / _a, _y]

   
   // Solve generalizations of a = n / ln[n] for n which include
   // a = n / ln[c n]
   // a = n / ln[c n^x]
   // a = n^y / ln[c n^x]
   // The exponents y and x can be negative, which indicates division by n.
   // This requires the Lambert W function which is not yet part of core
   // Frink but is defined in LambertW.frink which has dependencies on
   // ArbitraryPrecision.frink and sqrtWayne.frink.
   solve[_n^(_y:1) / ln[(_c:1) _n^(_x:1)] === _a, _n] :: freeOf[_c, _n] and freeOf[_y, _n] and freeOf[_x, _n] <-> [ solve[_n === (-((_a*_x*LambertW[-(((_c^(-1))^(_y/_x)*_y)/(_a*_x))])/_y))^_y^(-1), _n], solve[_n === (-((_a*_x*LambertW1[-(((_c^(-1))^(_y/_x)*_y)/(_a*_x))])/_y))^_y^(-1), _n]]


   // Solve generalizations of a = n ln[n] for n which include
   // a = n ln[c n]
   // a = n ln[c n^x]
   // a = n^y ln[c n^x]
   // The exponents y and x can be negative, which indicates division by n.
   // This requires the Lambert W function which is not yet part of core
   // Frink but is defined in LambertW.frink which has dependencies on
   // ArbitraryPrecision.frink and sqrtWayne.frink.
   solve[_n^(_y:1) ln[(_c:1) _n^(_x:1)] === _a, _n] :: freeOf[_c, _n] and freeOf[_x, _n] and freeOf[_y, _n] <-> [ solve[_n === ((_a _y)/(_x LambertW[(_a _y)/((_c^(-_x^(-1)))^_y * _x)]))^_y^(-1), _n], solve[_n === ((_a _y)/(_x LambertW1[(_a _y)/((_c^(-_x^(-1)))^_y * _x)]))^_y^(-1), _n]]

   // Solve generalizations of z = w e^w  for w which include
   // z = w e^(d w)
   // and even
   // w^x e^(d w^y)
   // This requires the Lambert W function which is not yet part of core
   // Frink but is defined in LambertW.frink which has dependencies on
   // ArbitraryPrecision.frink and sqrtWayne.frink.
   // This is currently commented out because it is solved by the more general
   // rule below.
//   solve[_w^(_x:1) e^((_d:1) _w^(_y:1)) === _z, _w] :: freeOf[_d, _w] and freeOf[_y,_w] and freeOf[_x, _w] <-> solve[_w === (_x LambertW[_d _y _z^(_y / _x) / _x] / (_d _y))^(1/_y), _w]

   // Solve generalizations of z = w b^w  for w which include
   // z = w b^(d w)
   // and even
   // w^x b^(d w^y)
   // This requires the Lambert W function which is not yet part of core
   // Frink but is defined in LambertW.frink which has dependencies on
   // ArbitraryPrecision.frink and sqrtWayne.frink.
   solve[_w^(_x:1) _b^((_d:1) _w^(_y:1)) === _z, _w] :: freeOf[_d, _w] and freeOf[_y,_w] and freeOf[_z, _w] and freeOf[_x, _w] and freeOf[_b, _w] <-> solve[_w === ((_x LambertW[(_d _y _z^(_y/_x) ln[_b])/_x])/(_d _y ln[_b]))^_y^(-1), _w]

   // Solve generalizations of a^(b x) = x
   // Which includes:
   // c a^(b x) + d x = 0
   solve[(_c:1) _a^((_b:1) _x) + (_d:1) _x === 0 , _x] :: freeOf[[_a, _b, _c, _d], _x] <-> [solve[_x === -LambertW[_b _c ln[_a] / _d] / (_b ln[_a]), _x], solve[_x === -LambertW1[_b _c ln[_a] / _d] / (_b ln[_a]), _x]]
}


Download or view powerTransformations.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 20162 days, 22 hours, 22 minutes ago.