1

Is there some way to use variable names in mystic constraints?

i.e.

equations = '''
abs(x0 - init_velocity) <= acceleration_constraint
abs(x1 - init_heading) <= turning_constraint
'''

The above causes this error:

Traceback (most recent call last):

  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/IPython/core/interactiveshell.py", line 3418, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)

  File "<ipython-input-68-254fb3031193>", line 14, in <module>
    eqn = simplify(equations, all=True)

  File "<string>", line 120, in simplify

  File "<string>", line 93, in _simplify

  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/mystic/symbolic.py", line 381, in equals
    after, before = eval(after,{},locals_), eval(before,{},locals_)

  File "<string>", line unknown
    
    ^
SyntaxError: unexpected EOF while parsing

EDIT:

Code used below is trying to minimize l2 norm between current local point (x_0, y_0) and next local point (x_1, y_1) while following constraints (physical acceleration and turning radius). This distance is minimized with respect to velocity and heading.

def formulate_objective(curr_x, curr_y, desired_x, desired_y):
    def objective(x):
        next_x = curr_x + x[0] * np.cos(np.radians(x[1]))
        next_y = curr_y + x[0] * np.sin(np.radians(x[1]))
        return np.linalg.norm(np.vstack([desired_x - next_x, desired_y - next_y]), ord=2)
    return objective

objective = formulate_objective(init_x, init_y, desired_x, desired_y)

equations = '''
abs(x0 - iv) <= ac
abs(x1 - ih) <= tc
'''
var_dict = dict(iv=init_velocity, ih=init_heading, 
                ac=acceleration_constraint, tc=turning_constraint)
eqn = simplify(equations, locals=var_dict)
cf = generate_constraint(generate_conditions(eqn, nvars=2), join=and_)

x0 = [init_velocity, init_heading]
fmin(objective, x0=x0, constraint=cf)
johnnyboy
  • 33
  • 6
  • After your edit, I think the issue is likely that simplify is not isolating `x0` and `x1` on the LHS, due to the `abs`. At least that's what I saw when I tested it. You might want to try manually simplifying the equations, Mystic can take a tuple of equations, and then combine the equations in he tuple with an `and_` or `or_` to make a single constraint. That could work here for the `abs`. You might also want to report an issue / make a feature request on mystic's GitHub, regarding `abs`. – Mike McKerns Nov 19 '20 at 14:49

2 Answers2

1

You should be able to use the locals keyword to make substitutions for names that are not optimization variable names.

>>> import mystic.symbolic as ms
>>> equations = '''
... x0 + x1 = A
... x1 * x0 = B
... '''
>>> 
>>> eqn = ms.simplify(equations, locals=dict(A=7,B=12))
>>> print(eqn)
x0 = 7 - x1
x0 != 0
x1 = 12/x0
>>>
Mike McKerns
  • 33,715
  • 8
  • 119
  • 139
  • This works but it seems like the constraints are not being followed in the solver. Any clue why this might be? – johnnyboy Nov 17 '20 at 19:25
  • The most common issues: (1) the individual constraints are not able to be independently applied, you can see above that `x0` is on the LHS twice. There's a keyword in `simplify` that requests isolation on the LHS be in the order specified; (2) constraints are not solved simultaneously, unless you use `join=and` in the constraint function generator; (3) lastly, if the solution space is very narrow, you may want to move one or more of the constraints equations to a penalty, which will give more flexibility to the solver to find a solution. – Mike McKerns Nov 18 '20 at 14:24
  • I posted my code in the original question. Can you check if I am doing it correctly? I tried out all your explanations but none seem to fix the issue of the solver following constraints/penalties – johnnyboy Nov 18 '20 at 19:24
0

You can use so called Python f-Strings:

https://realpython.com/python-f-strings/

example:

k = 'x0'
i = 'init_velocity'
a = 'acceleration_constraint'
b = 'turning_constraint'
equations = f'''
abs({k} - {i}) <= {a}
abs({k} - {i}) <= {b}
'''
print(equations)

gives me this output:

abs(x0 - init_velocity) <= acceleration_constraint
abs(x0 - init_velocity) <= turning_constraint
Patrik
  • 499
  • 1
  • 7
  • 24
  • Were you able to call ```simplify``` on that equation? I still get the parsing error. The thing is the code still runs without calling simplify but then the solver doesn't follow the constraints for some reason maybe I'm doing something wrong. – johnnyboy Nov 16 '20 at 20:56