Home > database >  Weird issue found trying to match a expression with a input that has paranthesis without evaluating(
Weird issue found trying to match a expression with a input that has paranthesis without evaluating(

Time:07-01

I have gone into detail in this issue thread https://github.com/sympy/sympy/issues/23709

but the gist is that I am trying to get the coefficients of an equation in the form:

parsed_input = 7*x   4*(10*x   6) >= 8*x   15

I am using the pattern:

x = Wild("x",  properties=[lambda x: isinstance(x, Symbol)])
a = Wild("a",  properties=[lambda x: isinstance(x, Integer)])
p = Wild("p",  properties=[lambda x: isinstance(x, Integer)])
q = Wild("q",  properties=[lambda x: isinstance(x, Integer)])
b = Wild("b",  properties=[lambda x: isinstance(x, Integer)])
c = Wild("c",  properties=[lambda x: isinstance(x, Integer)])
r = Wild("r",  properties=[lambda x: isinstance(x, Integer)])
s = Wild("s",  properties=[lambda x: isinstance(x, Integer)])

expected_output = Ge(Mul(a, (p*x   q))  b*x   c,  r*x   s)

But when I do:

matching = parsed_input.match(expected_output)

I am mostly getting a=1 , p=40, q=24 and some other times I get a=4,p=10, q=6

How can I get a=4,p=10, q=6 everytime?

CodePudding user response:

Sometimes a custom parser can help:

def parse(lhs):
  """
  >>> parse(lhs = 7*x   Mul(8,x 1,evaluate=False)   3) #= a*x   b*(c*x   d)   e
  {'e': 3, 'a': 7, 'b': 8, 'c': 1, 'd': 1}
  >>> parse(3*x 4)
  {'e': 4, 'a': 3}
  >>> parse(S(3))
  {'e': 1}
  """
  if lhs == x:
      return {'a': 1}
  if lhs.is_Number:
      return {'e': lhs}
  assert lhs.args
  hit = {}
  for arg in lhs.args:
    if arg.is_Mul:
        if not any(ai.args for ai in arg.args):
            a,X = arg.as_coeff_Mul()
            assert 'a' not in hit
            hit['a'] = a
            assert X == x
        else:
            b, A = arg.as_coeff_Mul()
            assert A.is_Add
            d, cx= A.as_coeff_Add()
            c, X = cx.as_coeff_Mul()
            assert X == x
            assert not any(i in hit for i in 'bcd')
            hit.update(dict(zip('bcd',(b,c,d))))
    else:
        assert not arg.args
        assert 'e' not in hit
        hit['e'] = arg
  return hit
  • Related