Exemplo n.º 1
0
def form_size(expr: Expr) -> typing.Tuple[Size, typing.Optional[Symbol]]:
    """Form a size object from a SymPy expression."""

    symbs = expr.atoms(Symbol)
    n_symbs = len(symbs)

    if n_symbs == 0:
        symb = None
        coeff_exprs = [expr]
    elif n_symbs == 1:
        symb = symbs.pop()
        coeff_exprs = Poly(expr, symb).all_coeffs()
        coeff_exprs.reverse()
    else:
        raise ValueError(
            'Invalid expression', expr,
            'expecting single variate polynomial (or number)'
        )

    if all(i.is_integer for i in coeff_exprs):
        dtype = int
    else:
        dtype = float

    if len(coeff_exprs) > 1:
        coeffs = np.array(coeff_exprs, dtype=dtype)
        cost = SVPoly(coeffs)
    elif len(coeff_exprs) == 1:
        cost = dtype(coeff_exprs[0])
    else:
        assert False

    return cost, symb
Exemplo n.º 2
0
 def _get_custom_constraint(self, constraint_expr: Expr, condition_template: str) -> Callable[..., Expr]:
     wilds = list(map(lambda x: x.name, constraint_expr.atoms(_WildAbstract)))
     lambdaargs = ', '.join(wilds)
     fullexpr = _get_srepr(constraint_expr)
     condition = condition_template.format(fullexpr)
     return matchpy.CustomConstraint(
         self._get_lambda(f"lambda {lambdaargs}: ({condition})"))
Exemplo n.º 3
0
def _get_only_symb(expr: Expr):
    """Get the only symbol in the given expression.

    The expression has to have only one symbol.
    """

    symbols = expr.atoms(Symbol)
    assert len(symbols) == 1
    return symbols.pop()
Exemplo n.º 4
0
 def round_expr(self, expr: sympy.Expr, num_digits: int) -> sympy.Expr:
     """
     Rounds all the numbers in a SymPy expression. This is useful for pretty-printing.
     :param expr: SymPy expression to round.
     :param num_digits: number of digits to leave.
     :return: expression with rounded numbers.
     """
     return expr.xreplace(
         {n: round(n, num_digits)
          for n in expr.atoms(sympy.Number)})
Exemplo n.º 5
0
    def __call__(self, expr: Expr):
        """Try to resolve an expression."""

        known = self._known
        if self._strict:
            if expr in known:
                return known[expr]
        else:
            for i in expr.atoms(Symbol):
                if i in known:
                    return known[i]
                continue

        return None
Exemplo n.º 6
0
def get_cost_key(cost: Expr) -> typing.Tuple[int, typing.List[Expr]]:
    """Get the key for ordering the cost.

    The cost should be a polynomial of at most one undetermined variable.  The
    result gives ordering of the cost agreeing with our common sense.
    """

    symbs = cost.atoms(Symbol)
    n_symbs = len(symbs)

    if n_symbs == 0:
        return 0, [cost]
    elif n_symbs == 1:
        symb = symbs.pop()
        coeffs = Poly(cost, symb).all_coeffs()
        return len(coeffs) - 1, coeffs
    else:
        raise ValueError('Invalid cost to compare', cost,
                         'expecting univariate polynomial or number')
Exemplo n.º 7
0
    def __sub__(self, other: Expr):
        """Subtract the current value with another.

        This method is mainly to be able to work together with the Kronecker
        delta class from SymPy.  The difference is only guaranteed to have
        correct ``is_zero`` property.  The actual difference might not make
        mathematical sense.
        """

        if isinstance(other, type(self)):
            return self.args[0] - other.args[0]
        elif len(other.atoms(Symbol)) == 0:
            raise ValueError(
                'Invalid operation for ', (self, other),
                'concrete symbols can only be subtracted for the same type')
        else:
            # We are having a symbolic value at the other expression.  We just
            # need to make sure that the result is fuzzy.
            assert other.is_zero is None
            return other
Exemplo n.º 8
0
    def __init__(self, f: Expr, g: Expr):
        self.f = f
        self.g = g

        x = sorted(f.atoms(), key=lambda s: s.name)
        self.m = m = len(g)
        self.n = len(x)

        l = array_sym("lambda", m)
        s = Symbol("obj_factor")

        L = s * f + sum(l_i * g_i for l_i, g_i in zip(l, g))
        """Lagrangian"""

        jac_g = [[g_i.diff(x_i) for x_i in x] for g_i in g]
        jac_g_sparse, jac_g_sparsity_indices = sparsify(jac_g)

        h = [[dL.diff(x_j) for x_j in x] for dL in [L.diff(x_i) for x_i in x]]
        h_sparse, h_sparsity_indices = sparsify(ll_triangular(h))
        self.grad_f = [f.diff(x_i) for x_i in x]
        self.jac_g = jac_g_sparse
        self.h = h_sparse
        self.h_sparsity_indices = transpose(h_sparsity_indices)
        self.jac_g_sparsity_indices = transpose(jac_g_sparsity_indices)
Exemplo n.º 9
0
def _round_sympy_expr(expr: sympy.Expr, num_digits: int = 4) -> sympy.Expr:
    return expr.xreplace(
        {n: round(n, num_digits)
         for n in expr.atoms(sympy.Number)})
Exemplo n.º 10
0
def common_denominator(expr: sp.Expr) -> sp.Expr:
    """Finds least common multiple of all denominators occurring in an expression"""
    denominators = [r.q for r in expr.atoms(sp.Rational)]
    return sp.lcm(denominators)
Exemplo n.º 11
0
def check_max_constant(sympy_expr: sympy.Expr, options: dict) -> bool:
    """Check whether the expression contains constant that is higher than allowed"""
    for atom in sympy_expr.atoms():
        if atom.is_real and abs(atom) > options['max_constant_allowed']:
            return False
    return True
Exemplo n.º 12
0
 def round_expr(self, expr: sympy.Expr, num_digits: int) -> sympy.Expr:
     return expr.xreplace(
         {n: round(n, num_digits)
          for n in expr.atoms(sympy.Number)})
Exemplo n.º 13
0
 def from_twoform(twoform: Expr):
     """Create a CoordSystem from a sympy.Expr that represents a metric as a twoform
     by extracting the coordinates from the given metric (reversing this dependency)
     """
     cs = twoform.atoms(_CoordSystem).pop()
     return CoordSystem.from_sympy_coordsystem(cs)