Just to increase awareness we *do* have a sexy search mechanism in
SymPy
living in sympy.strategies.tree (by my definition of sexiness).
In [1]: from sympy.strategies.tree import greedy, brute
In [2]: funcs = [simplify, expand, fu, powsimp, sqrtdenest]
In [3]: objective = lambda x: len(str(x)) # minimize string length
In [4]: megasimp = greedy((funcs, funcs), objective)
megasimp tries each of simplify, expand, fu, powsimp, and sqrtdenest,
then
selects the result that minimizes the object (string length). It then
tries each of those functions again on the result (this is the result
of
including funcs twice in a tuple.) We could swap out greedy for
brute and
it would try all 5 squared combinations.
In [5]: foo = -sqrt(-2*sqrt(2)+3)+sqrt(2*sqrt(2)+3)
In [6]: megasimp(foo)
Out[6]: 2
Of course, this is a fairly dumb example, because just using
sqrtdenest
once is the right answer. In principle though we could have defined
much
more sophisticated function evaluation trees. For anyone still
reading,
here is the docstring to greedy
Execute a strategic tree. Select alternatives greedily
Trees
-----
Nodes in a tree can be either
function - a leaf
list - a selection among operations
tuple - a sequence of chained operations
Textual examples
----------------
Text: Run f, then run g, e.g. ``lambda x: g(f(x))``
Code: ``(f, g)``
Text: Run either f or g, whichever minimizes the objective
Code: ``[f, g]``
Textx: Run either f or g, whichever is better, then run h
Code: ``([f, g], h)``
Text: Either expand then simplify or try factor then foosimp. Finally
print
Code: ``([(expand, simplify), (factor, foosimp)], print)``
Objective
---------
"Better" is determined by the objective keyword. This function makes
choices to minimize the objective. It defaults to the identity.
Example
-------
>>> from sympy.strategies.tree import greedy
>>> inc = lambda x: x + 1
>>> dec = lambda x: x - 1
>>> double = lambda x: 2*x
>>> tree = [inc, (dec, double)] # either inc or dec-then-double
>>> fn = greedy(tree)
>>> fn(4) # lowest value comes from the inc
5
>>> fn(1) # lowest value comes from dec then double
0
This funcion selects between options in a tuple. The result is
chosen that
minimizes the objective function.
>>> fn = greedy(tree, objective=lambda x: -x) # maximize
>>> fn(4) # highest value comes from the dec then double
6
>>> fn(1) # highest value comes from the inc
2
Greediness
----------
This is a greedy algorithm. In the example:
([a, b], c) # do either a or b, then do c
the choice between running ``a`` or ``b`` is made without foresight
to c
On Mon, May 19, 2014 at 8:13 PM, Aaron Meurer <[email protected]>
wrote:
> In this case, there is a simplification function that will do it,
> sqrtdenest:
>
> In [3]: sqrtdenest(foo)
> Out[3]: 2
>
> In general, there is no single algorithm for simplification (indeed,
> it's not even an easy concept to define), but simplify() tries to do
> its best. The more you know about the steps that are required to do
> the simplification you want, or the type of expression you have, the
> better you can apply individual simplification functions to get what
> you want.
>
> In this case, though, I would consider it a bug that simplify() did
> not try sqrtdenest.
>
> Aaron Meurer
>
> On Mon, May 19, 2014 at 3:54 PM, Mike Witt <[email protected]> wrote:
> > Is it typical to have to "fiddle around" with different
> > forms of an expression to get it to simplify? For example:
> >
> > In [7]: from sympy import sqrt
> >
> > In [8]: foo=-sqrt(-2*sqrt(2)+3)+sqrt(2*sqrt(2)+3)
> >
> > In [9]: print foo
> > -sqrt(-2*sqrt(2) + 3) + sqrt(2*sqrt(2) + 3)
> >
> > In [10]: print foo.simplify()
> > -sqrt(-2*sqrt(2) + 3) + sqrt(2*sqrt(2) + 3)
> >
> > In [11]: print (foo**2).expand()
> > -2*sqrt(-2*sqrt(2) + 3)*sqrt(2*sqrt(2) + 3) + 6
> >
> > In [12]: print (foo**2).expand().simplify()
> > 4
> >
> > Or is there some kind of "general strategy" that will
> > always work (assuming there is clearly a simplification
> > possible, like an integer as above)?
> >
> > -Mike
> >
> > --
> > You received this message because you are subscribed to the
Google Groups
> > "sympy" group.
> > To unsubscribe from this group and stop receiving emails from it,
send an
> > email to [email protected].
> > To post to this group, send email to [email protected].
> > Visit this group at http://groups.google.com/group/sympy.
> > To view this discussion on the web visit
> >
https://groups.google.com/d/msgid/sympy/1400536494.2532.18%40Vector.
> > For more options, visit https://groups.google.com/d/optout.
>
> --
> You received this message because you are subscribed to the Google
Groups
> "sympy" group.
> To unsubscribe from this group and stop receiving emails from it,
send an
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/sympy.
> To view this discussion on the web visit
>
https://groups.google.com/d/msgid/sympy/CAKgW%3D6LKVAZ5OT-z%2B_asPcLB97wU2GmtqNRxT1ws2Ga9779XuQ%40mail.gmail.com
> .
> For more options, visit https://groups.google.com/d/optout.
>
--
You received this message because you are subscribed to the Google
Groups "sympy" group.
To unsubscribe from this group and stop receiving emails from it,
send an email to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sympy.
To view this discussion on the web visit
https://groups.google.com/d/msgid/sympy/CAJ8oX-G-PDM%2BrPsq5MfRLX0zhkpEdLjCPgGdaQb80ii9v47e-g%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.