I am trying to use Mystic to minimize a nonlinear function with linear constraints.
As a simple example, I have the following:
import numpy as np
import mystic.symbolic as ms
from mystic.symbolic import generate_constraint
from mystic.symbolic import generate_solvers
from mystic.symbolic import linear_symbolic
from mystic.monitors import Monitor
from mystic.solvers import LatticeSolver
from mystic.solvers import NelderMeadSimplexSolver
from mystic.termination import CandidateRelativeTolerance as CRT
# diamond-shaped constraint
# same format as output of mystic.linear_symbolic()
basic_constraint = '''
1.0*x0 + 1.0*x1 <= 5
1.0*x0 - 1.0*x1 >= -5
1.0*x0 + 1.0*x1 >= -5
1.0*x0 - 1.0*x1 <= 5
'''[1:]
def basic_objective(x, *args):
v1 = x[0] * x[1] / (1 + np.abs(x[0] + x[1]))
v2 = np.min(x)
return v1 + v2/(1+np.abs(v1))
When trying to run the code, I do the following:
def test_basic():
stepmon=Monitor()
nbins = [6,6,]
solver = LatticeSolver(len(nbins), nbins)
solver.SetNestedSolver(NelderMeadSimplexSolver)
print('Generating Solvers')
constraint_solver = generate_solvers(
basic_constraint,
nvars=2
)
print(constraint_solver)
# HERE IS ISSUE, IF COMMENTED ISSUE BELOW
print(constraint_solver[0](np.ones(2)))
print('Setting Constraints')
solver.SetConstraints(
generate_constraint(constraint_solver)
)
solver.SetGenerationMonitor(stepmon)
solver.SetTermination(CRT())
print('Solving...')
# ISSUE APPEARS HERE IF print(constraint_solver[0]...)
# IS COMMENTED OUT
solver.Solve(basic_objective)
solution = solver.Solution()
print(solution)
return solution
test_basic()
When I run the above, the error occurs at
print(constraint_solver[0](np.ones(2)))
or, if I comment it out,
solver.Solve(basic_objective)
The only noticeable difference is the size of the call stack.
The error I get is
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 12, in test_basic
File "<string>", line 4, in solver_139632515562208
File "<string>", line 1
SyntaxError: cannot assign to operator
This is a result of Mystic trying to compile Python code from a string and encountering a syntax error, but I do not know how to fix this issue.
I'm the
mystic
author. You are missing one key function, and a second that is not needed in this case but often is.If you print the doc for your constraint solvers, you'll see that they are not formed well.
You need to isolate a single variable on the left-hand side. Hence, we either need to
solve
orsimplify
. For inequalities,simplify
works better, and for equalitiessolve
generally works. I am not sure the level of documentation that states that. Anyway, I usesimplify
before building the constraints.Now, your code works as expected.
However, I'd generally make one other modification.
Without the
join=and_
, your code still works. The difference is that without an explicitjoin
statement, it's assumed the constraints are independent of each other, and can be solved one at a time. Usingjoin=and_
forces the constraints to be solved simultaneously, which is slower. There's alsoor_
and other more complex combinations in building constraints, but the default is to assume independence.Both points are subtle, and, I believe, in the documentation it should state that the constraints solvers need the symbolic equations need to have a single variable isolated on the left-hand side. However, it's probably not obvious as that's often missed.