Source code for tfields.lib.symbolics

"""
sympy helper functions
"""
import sympy
from sympy.logic.boolalg import BooleanFunction


[docs]def split_expression(expr): """ Return the expression split up in the basic boolean functions. """ if isinstance(expr, sympy.Not): expr = expr.to_nnf() if isinstance(expr, BooleanFunction): expressions = expr.args else: expressions = [expr] return expressions
[docs]def to_planes(expr): """ Resolve BooleanFunctions to retrieve multiple planes Examples: >>> import sympy >>> from tfields.lib.symbolics import to_planes, to_plane >>> x, y, z = sympy.symbols('x y z') >>> eq1 = 2*x > 0 >>> eq2 = 2*y + 3*z <= 4 >>> p12 = to_planes(eq1 & eq2) >>> p1 = to_plane(eq1) >>> p12[0] == p1 True >>> p2 = to_plane(eq2) >>> p12[1] == p2 True """ expressions = split_expression(expr) return [to_plane(e) for e in expressions]
[docs]def to_plane(expr): """ Tranlate the expression (coordinate form) to normal form and return as Plane Examples: Get 3-d plane for linear equations >>> import sympy >>> from tfields.lib.symbolics import to_plane >>> x, y, z = sympy.symbols('x y z') >>> eq1 = 2*x - 4 >>> p1 = to_plane(eq1) >>> assert eq1, p1.equation() # multiple dimensions work >>> eq2 = x + 2*y + 3*z - 4 >>> p2 = to_plane(eq2) >>> assert eq2, p2.equation() The base point is calculated independent of the coords >>> eq3 = 2*y + 3*z - 4 >>> p3 = to_plane(eq3) >>> assert eq3, p3.equation() Inequalities will be treated like equations >>> ie1 = 2*y + 3*z > 4 >>> p4 = to_plane(ie1) >>> assert ie1.lhs - ie1.rhs, p4.equation() Returns: sympy.Plane """ x, y, z = sympy.symbols('x y z') # convert inequalities if "Than" in str(expr.__class__): expr = expr.rhs - expr.lhs poly = expr.as_poly(x, y, z, domain='RR') if poly is None: raise ValueError("Expression {expr} can not be described as a polygon." .format(**locals())) coords = (x, y, z) degrees = tuple(poly.degree(c) for c in coords) if any([d > 1 for d in degrees]): raise TypeError("Expression {0} can not be represented as plane" "since the poly dimension is > 1 for one variable!" .format(expr)) norm = tuple(expr.coeff(coord) for coord in coords) # now we need any point on the plane # find the variable to solve for reduced_expr = expr.copy() non_zero_coord = None for coord, degree in zip(coords, degrees): if degree == 0 or non_zero_coord is not None: if degree > 0: reduced_expr = reduced_expr.subs(coord, 0.) else: non_zero_coord = coord non_zero_value = sympy.solve(reduced_expr, non_zero_coord)[0] point = sympy.Point3D(*[non_zero_value if non_zero_coord == coord else 0. for coord in coords]) return sympy.Plane(point, normal_vector=norm)