modelparameters.sympy.strategies package

Subpackages

Submodules

modelparameters.sympy.strategies.core module

Generic SymPy-Independent Strategies

modelparameters.sympy.strategies.core.chain(*rules)[source]

Compose a sequence of rules so that they apply to the expr sequentially

modelparameters.sympy.strategies.core.condition(cond, rule)[source]

Only apply rule if condition is true

modelparameters.sympy.strategies.core.debug(rule, file=None)[source]

Print out before and after expressions each time rule is used

modelparameters.sympy.strategies.core.do_one(*rules)[source]

Try each of the rules until one works. Then stop.

modelparameters.sympy.strategies.core.exhaust(rule)[source]

Apply a rule repeatedly until it has no effect

modelparameters.sympy.strategies.core.identity(x)
modelparameters.sympy.strategies.core.memoize(rule)[source]

Memoized version of a rule

modelparameters.sympy.strategies.core.minimize(*rules, **kwargs)[source]

Select result of rules that minimizes objective

>>> from ..strategies import minimize
>>> inc = lambda x: x + 1
>>> dec = lambda x: x - 1
>>> rl = minimize(inc, dec)
>>> rl(4)
3
>>> rl = minimize(inc, dec, objective=lambda x: -x)  # maximize
>>> rl(4)
5
modelparameters.sympy.strategies.core.null_safe(rule)[source]

Return original expr if rule returns None

modelparameters.sympy.strategies.core.switch(key, ruledict)[source]

Select a rule based on the result of key called on the function

modelparameters.sympy.strategies.core.tryit(rule)[source]

Return original expr if rule raises exception

modelparameters.sympy.strategies.rl module

Generic Rules for SymPy

This file assumes knowledge of Basic and little else.

modelparameters.sympy.strategies.rl.distribute(A, B)[source]

Turns an A containing Bs into a B of As

where A, B are container types

>>> from ..strategies import distribute
>>> from .. import Add, Mul, symbols
>>> x, y = symbols('x,y')
>>> dist = distribute(Mul, Add)
>>> expr = Mul(2, x+y, evaluate=False)
>>> expr
2*(x + y)
>>> dist(expr)
2*x + 2*y
modelparameters.sympy.strategies.rl.flatten(expr, new=<function Basic.__new__>)[source]

Flatten T(a, b, T(c, d), T2(e)) to T(a, b, c, d, T2(e))

modelparameters.sympy.strategies.rl.glom(key, count, combine)[source]

Create a rule to conglomerate identical args

>>> from ..strategies import glom
>>> from .. import Add
>>> from ..abc import x
>>> key     = lambda x: x.as_coeff_Mul()[1]
>>> count   = lambda x: x.as_coeff_Mul()[0]
>>> combine = lambda cnt, arg: cnt * arg
>>> rl = glom(key, count, combine)
>>> rl(Add(x, -x, 3*x, 2, 3, evaluate=False))
3*x + 5

Wait, how are key, count and combine supposed to work?

>>> key(2*x)
x
>>> count(2*x)
2
>>> combine(2, x)
2*x
modelparameters.sympy.strategies.rl.rebuild(expr)[source]

Rebuild a SymPy tree

This function recursively calls constructors in the expression tree. This forces canonicalization and removes ugliness introduced by the use of Basic.__new__

modelparameters.sympy.strategies.rl.rm_id(isid, new=<function Basic.__new__>)[source]

Create a rule to remove identities

isid - fn :: x -> Bool — whether or not this element is an identity

>>> from ..strategies import rm_id
>>> from .. import Basic
>>> remove_zeros = rm_id(lambda x: x==0)
>>> remove_zeros(Basic(1, 0, 2))
Basic(1, 2)
>>> remove_zeros(Basic(0, 0)) # If only identites then we keep one
Basic(0)

See also

unpack

modelparameters.sympy.strategies.rl.sort(key, new=<function Basic.__new__>)[source]

Create a rule to sort by a key function

>>> from ..strategies import sort
>>> from .. import Basic
>>> sort_rl = sort(str)
>>> sort_rl(Basic(3, 1, 2))
Basic(1, 2, 3)
modelparameters.sympy.strategies.rl.subs(a, b)[source]

Replace expressions exactly

modelparameters.sympy.strategies.rl.unpack(expr)[source]

Rule to unpack singleton args

>>> from ..strategies import unpack
>>> from .. import Basic
>>> unpack(Basic(2))
2

modelparameters.sympy.strategies.tools module

modelparameters.sympy.strategies.tools.canon(*rules, **kwargs)[source]

Strategy for canonicalization

Apply each rule in a bottom_up fashion through the tree. Do each one in turn. Keep doing this until there is no change.

modelparameters.sympy.strategies.tools.subs(d, **kwargs)[source]

Full simultaneous exact substitution

Examples

>>> from .tools import subs
>>> from .. import Basic
>>> mapping = {1: 4, 4: 1, Basic(5): Basic(6, 7)}
>>> expr = Basic(1, Basic(2, 3), Basic(4, Basic(5)))
>>> subs(mapping)(expr)
Basic(4, Basic(2, 3), Basic(1, Basic(6, 7)))
modelparameters.sympy.strategies.tools.typed(ruletypes)[source]

Apply rules based on the expression type

inputs:

ruletypes – a dict mapping {Type: rule}

>>> from ..strategies import rm_id, typed
>>> from .. import Add, Mul
>>> rm_zeros = rm_id(lambda x: x==0)
>>> rm_ones  = rm_id(lambda x: x==1)
>>> remove_idents = typed({Add: rm_zeros, Mul: rm_ones})

modelparameters.sympy.strategies.traverse module

Strategies to Traverse a Tree.

modelparameters.sympy.strategies.traverse.bottom_up(rule, fns={'children': <function <lambda>>, 'leaf': <function <lambda>>, 'new': <function Basic.__new__>, 'op': <class 'type'>})[source]

Apply a rule down a tree running it on the bottom nodes first.

modelparameters.sympy.strategies.traverse.bottom_up_once(rule, fns={'children': <function <lambda>>, 'leaf': <function <lambda>>, 'new': <function Basic.__new__>, 'op': <class 'type'>})[source]

Apply a rule up a tree - stop on success.

modelparameters.sympy.strategies.traverse.sall(rule, fns={'children': <function <lambda>>, 'leaf': <function <lambda>>, 'new': <function Basic.__new__>, 'op': <class 'type'>})[source]

Strategic all - apply rule to args.

modelparameters.sympy.strategies.traverse.top_down(rule, fns={'children': <function <lambda>>, 'leaf': <function <lambda>>, 'new': <function Basic.__new__>, 'op': <class 'type'>})[source]

Apply a rule down a tree running it on the top nodes first.

modelparameters.sympy.strategies.traverse.top_down_once(rule, fns={'children': <function <lambda>>, 'leaf': <function <lambda>>, 'new': <function Basic.__new__>, 'op': <class 'type'>})[source]

Apply a rule down a tree - stop on success.

modelparameters.sympy.strategies.tree module

modelparameters.sympy.strategies.tree.allresults(tree, leaf=<function yieldify>)[source]

Execute a strategic tree. Return all possibilities.

Returns a lazy iterator of all possible results

Exhaustiveness

This is an exhaustive algorithm. In the example

([a, b], [c, d])

All of the results from

(a, c), (b, c), (a, d), (b, d)

are returned. This can lead to combinatorial blowup.

See sympy.strategies.greedy for details on input

modelparameters.sympy.strategies.tree.brute(tree, objective=<function <lambda>>, **kwargs)[source]
modelparameters.sympy.strategies.tree.greedy(tree, objective=<function <lambda>>, **kwargs)[source]

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.

Examples

>>> from .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 function 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

modelparameters.sympy.strategies.tree.identity(x)
modelparameters.sympy.strategies.tree.treeapply(tree, join, leaf=<function <lambda>>)[source]

Apply functions onto recursive containers (tree)

join - a dictionary mapping container types to functions

e.g. {list: minimize, tuple: chain}

Keys are containers/iterables. Values are functions [a] -> a.

Examples

>>> from .tree import treeapply
>>> tree = [(3, 2), (4, 1)]
>>> treeapply(tree, {list: max, tuple: min})
2
>>> add = lambda *args: sum(args)
>>> def mul(*args):
...     total = 1
...     for arg in args:
...         total *= arg
...     return total
>>> treeapply(tree, {list: mul, tuple: add})
25

modelparameters.sympy.strategies.util module

modelparameters.sympy.strategies.util.assoc(d, k, v)[source]

Module contents

Rewrite Rules

DISCLAIMER: This module is experimental. The interface is subject to change.

A rule is a function that transforms one expression into another

Rule :: Expr -> Expr

A strategy is a function that says how a rule should be applied to a syntax tree. In general strategies take rules and produce a new rule

Strategy :: [Rules], Other-stuff -> Rule

This allows developers to separate a mathematical transformation from the algorithmic details of applying that transformation. The goal is to separate the work of mathematical programming from algorithmic programming.

Submodules

strategies.rl - some fundamental rules strategies.core - generic non-SymPy specific strategies strategies.traverse - strategies that traverse a SymPy tree strategies.tools - some conglomerate strategies that do depend on SymPy