from optyx import Variable
x = Variable("x")
y = Variable("y")
# Left-hand side >= right-hand side
c1 = x + y >= 1
c2 = 2*x >= y
# Left-hand side <= right-hand side
c3 = x**2 + y**2 <= 100
c4 = x <= 10Constraints API
Defining inequality and equality constraints
1 Constraint
A constraint represents a condition the solution must satisfy.
Constraints are created using comparison operators on expressions:
from optyx import Variable
x = Variable("x")
y = Variable("y")
# Inequality constraints
c1 = x + y >= 1 # Greater than or equal
c2 = x - y <= 5 # Less than or equal
# Equality constraint
c3 = (x + y).eq(10)2 Creating Constraints
2.1 Inequality Constraints
Use >= and <= operators on expressions:
2.2 Equality Constraints
Use the .eq() method:
from optyx import Variable
x = Variable("x")
y = Variable("y")
# x + y = 10
c1 = (x + y).eq(10)
# x = y (equivalent to x - y = 0)
c2 = (x - y).eq(0)
# More complex equality
c3 = (x**2 + y**2).eq(1) # Unit circle
Note
We use .eq() instead of == because Python requires __eq__ to return a boolean for hash operations. This is standard practice in symbolic math libraries.
3 Constraint Properties
| Property | Type | Description |
|---|---|---|
.expr |
Expression |
The constraint expression (normalized to rhs = 0) |
.sense |
str |
One of ">=", "<=", or "==" |
3.1 Normalization
Constraints are automatically normalized so the right-hand side is zero:
from optyx import Variable
x = Variable("x")
# x + 5 >= 10 becomes (x + 5 - 10) >= 0, i.e., (x - 5) >= 0
c = x + 5 >= 10
print(f"Sense: {c.sense}")Sense: >=
4 Using Constraints in Problems
Add constraints to problems with .subject_to():
from optyx import Variable, Problem
x = Variable("x", lb=0)
y = Variable("y", lb=0)
solution = (
Problem()
.minimize(x**2 + y**2)
.subject_to(x + y >= 1) # Inequality
.subject_to(x <= 5) # Upper bound as constraint
.subject_to((x - y).eq(0)) # Equality
.solve()
)
print(f"x* = {solution['x']:.4f}")
print(f"y* = {solution['y']:.4f}")x* = 0.5000
y* = 0.5000
5 Constraint Patterns
5.1 Box Constraints
For simple bounds, prefer using Variable(lb=, ub=):
from optyx import Variable
# Preferred: bounds on variable
x = Variable("x", lb=0, ub=10)
# Alternative: as explicit constraints (less efficient)
y = Variable("y")
c1 = y >= 0
c2 = y <= 105.2 Linear Constraints
from optyx import Variable
x = Variable("x")
y = Variable("y")
z = Variable("z")
# Budget constraint
budget = 10*x + 20*y + 15*z <= 1000
# Resource allocation
allocation = x + y + z >= 1005.3 Nonlinear Constraints
from optyx import Variable, sqrt
x = Variable("x")
y = Variable("y")
# Circle constraint
circle = x**2 + y**2 <= 25
# Norm constraint
norm = sqrt(x**2 + y**2) <= 5
# Ratio constraint
ratio = x / (y + 1) >= 0.55.4 Multiple Constraints
from optyx import Variable, Problem
x = Variable("x", lb=0)
y = Variable("y", lb=0)
prob = Problem().minimize(x + y)
# Add multiple constraints
constraints = [
x + y >= 10,
x - y <= 5,
2*x + y <= 20,
(x - 5).eq(y - 5)
]
for c in constraints:
prob.subject_to(c)
solution = prob.solve()
print(f"x* = {solution['x']:.2f}, y* = {solution['y']:.2f}")x* = 5.00, y* = 5.00
6 Solver Handling
Optyx converts constraints to the format expected by SciPy:
| Optyx | SciPy Equivalent |
|---|---|
f(x) >= 0 |
{'type': 'ineq', 'fun': f} |
f(x) <= 0 |
{'type': 'ineq', 'fun': -f} |
f(x) == 0 |
{'type': 'eq', 'fun': f} |
Gradients are computed automatically and passed to the solver for efficient optimization.