How to use AddBoolXOr in OR-tools - python

I try to understand OR-tools. I want to solve this equations system in modulo 2:
x1 + x2 + x3 + 0 = 0
x1 + x2 + 0 + x4 = 1
x1 + 0 + x3 + x4 = 1
0 + x2 + x3 + x4 = 1
this equates because of the modulo 2 to:
x1 ^ x2 ^ x3 = 0
x1 ^ x2 ^ x4 = 1
x1 ^ x3 ^ x4 = 1
x2 ^ x3 ^ x4 = 1
using the bitwise xor (see here).
So I tried the following code:
from ortools.sat.python import cp_model
# Creates the model.
model = cp_model.CpModel()
# Creates the variables.
x1 = model.NewBoolVar('x1')
x2 = model.NewBoolVar('x2')
x3 = model.NewBoolVar('x3')
x4 = model.NewBoolVar('x4')
# Creates the constraints.
model.AddBoolXOr(x1 ^ x2 ^ x3 == 0)
model.AddBoolXOr(x1 ^ x2 ^ x4 == 1)
model.AddBoolXOr(x1 ^ x3 ^ x4 == 1)
model.AddBoolXOr(x2 ^ x3 ^ x4 == 1)
# Creates a solver and solves the model.
solver = cp_model.CpSolver()
status = solver.Solve(model)
if status == cp_model.OPTIMAL:
print('x1 = %i' % solver.Value(x1))
print('x2 = %i' % solver.Value(x2))
print('x3 = %i' % solver.Value(x3))
print('x4 = %i' % solver.Value(x4))
but I get:
'calling xor on a linear expression is not supported, '
NotImplementedError: calling xor on a linear expression is not supported, please use CpModel.AddBoolXor
If I use AddBoolXor instead of AddBoolXOr I get:
AttributeError: 'CpModel' object has no attribute 'AddBoolXor'

AddBoolXor takes an array of Boolean literals.
model.AddBoolXOr([x1, x2.Not(), x3])
The semantic of AddBoolXor(xi) is sum(xi) % 2 == 1
So, in your case
# Creates the constraints.
model.AddBoolXOr([x1, x2, x3, True])
model.AddBoolXOr([x1, x2, x4])
model.AddBoolXOr([x1, x3, x4])
model.AddBoolXOr([x2, x3, x4])

Related

SymPy - Is there a way to write a summation, that has a variable with an incrementing subscript?

I wanted to write this expression, in code:
x1 + x2 + x3 + x4 + x5
I can currently do this via:
import sympy as sp
x1, x2, x3, x4, x5 = sp.symbols('x1 x2 x3 x4 x5')
x1 + x2 + x3 + x4 + x5
But unfortunately, this doesn't scale very well, incase I wanted to go from x1 to say, x10,000
Any help would be sincerely appreciated.
I tried using SymPy's summation function, like this:
summation(x(i), (i, 0, n))
But unfortunately got a TypeError, stating:
'Symbol' object is not callable
You can use a generic IndexedBase symbol with a summation:
>>> i = Symbol('i'); x = IndexedBase('x')
>>> Sum(x[i],(i,1,10))
Sum(x[i], (i, 1, 10))
>>> _.doit()
x[10] + x[1] + x[2] + x[3] + x[4] + x[5] + x[6] + x[7] + x[8] + x[9]

Python scipy fsolve to solve a large number of nonlinear equations

I want to solve a system of 6 nonlinear equations using Python. I found that I can use scipy's fsolve pretty easily to solve a system of 3 nonlinear equations. However, when I expand this to a larger system, I find that the solution does not solve the system of equations. Is there something I can correct that will allow for the solution of 6 nonlinear equations?
import numpy as np
from scipy.optimize import fsolve
def system(z):
#arbitrary system of 3 nonlinear equations
x1 = z[0]
x2 = z[1]
x3 = z[2]
F = np.empty((3))
F[0] = 20* x1 + x2**2
F[1] = x2 - x1
F[2] = x3 + 5 - x1*x2
return F
def system2(z):
#arbitrary system of 6 nonlinear equations
x1 = z[0]
x2 = z[1]
x3 = z[2]
x4 = z[3]
x5 = z[4]
x6 = z[5]
F = np.empty((6))
F[0] = 20* x1 + x2**2
F[1] = x2 - x1
F[2] = x3 + 5 - x1*x2
F[3] = x3 + x2
F[4] = x5 + x4**2
F[5] = x6**2 + x1 - 20
return F
uInitial = np.array([1,1,1])
u = fsolve(system,uInitial)
print('Solution: ',u)
print('Solution check: ',system(u),'\n') #yields zeros as expected
vInitial = np.array([1,1,1,1,1,1])
v = fsolve(system2,vInitial)
print('Solution: ',v)
print('Solution check: ',system2(v)) #unexpectedly does not yield zeros. Equations not solved correctly.
When applying the given solution back into the system of equations, I should expect to receive zeros (or nearly zero). This would confirm that the computed solution solves the given set of equations. I tried checking with this method for both the system of 3 equations and the system of 6 equations, but only the system of 3 equations is solved correctly with this check. What can I do to solve the system of 6 nonlinear equations?
Your system is inconsistent and your initial guess is off. Try adding fourth equation to the first system of three equations:
F[0] = 20 * x1 + x2**2 # "first" equation
F[1] = x2 - x1 # "second" (=> x1 == x2)
F[2] = x3 + 5 - x1*x2 # "third"
F[3] = x3 + x2 # "fourth" equation (=> x3 == -x2)
First, let's solve first three equations. From the second equation it follows that x1 is equal to x2. Therefore the first equation can be re-written as:
F[0] = 20 * x1 + x1**2
which leads to x1 = -20 (and x2 = -20). Using this in the third equation leads to x3 = 395. Try to modify initial conditions for the first system to uInitial = np.array([-30, -30, 1]) - you should get the correct answer.
Now, let's solve all four equations. The third equation, using the fact that x2 == x1, can be re-written as:
F[2] = x3 + 5 - x1**2
From the fourth equation it follows that x3 == -x2 (and so x3 == -x1 as well). Therefore, this equation can be rewritten as x3 + 5 - x3**2 == 0 => x3 = 0.5 +(-) sqrt(21)/2 which is different from 395 that we got above using first three equations.
This shows that you have an inconsistent system of equations which has no solution.

Mixed-Integer Quadratic Programming in Python

I would like to solve in Python the following Mixed-Integer Quadratic Programming in Python. Nevertheless, I'm not familiar with the optimization
toolboxes of Python.
Can someone provide an example of code with the vectors X1, X2, X3, X4 given as below ?
X1 = np.array([3,10,20,10])
X2 = np.array([5,1,3,4])
X3 = np.array([2,3,1,4])
X4 = np.array([10,0,1,2])
The MIQP is written as :
I tried to solve it with CVXPY but i encoutered problem with the boolean
variable x = cp.Variable(1, boolean=True):
import numpy
import numpy as np
import cvxpy as cp
X1 = np.array([3,10,20,10])
X2 = np.array([5,1,3,4])
X3 = np.array([2,3,1,4])
X4 = np.array([10,0,1,2])
M = 100
x = cp.Variable(1, boolean=True)
Y1 = cp.Parameter(4)
Y2 = cp.Parameter(4)
a = cp.Parameter(1)
b = cp.Parameter(1)
c = cp.Parameter(1)
d = cp.Parameter(1)
delta = cp.Variable(1)
constraints = [Y1 <= X1 - a,
Y1 <= X2 - b,
Y1 >= X1 - a - M*delta,
Y1 >= X2 - b - M*(1-delta),
Y2 <= X3 - c,
Y2 <= X4 - d,
Y2 >= X3 - c - M*delta,
Y2 >= X4 - d - M*(1-delta),
0 <= a, a <= 10,
0 <= b, b <= 5,
0 <= c, c <= 5,
0 <= d, d <= 10,
delta == x]
obj = cp.Minimize(cp.sum_squares(Y1-Y2))
prob = cp.Problem(obj, constraints)
print(prob.solve())
In cvxpy, parameter is something you have a value to set to it. In your problem, basically all symbols other than the X1 to X4 are variables. So do a global replace of cp.Parameter to cp.Variable will work.
Then, I found the result to be
$ python3 cvxtest.py
69.99998471073722
Gekko with the APOPT solver can handle MIQP problems in addition to more general Nonlinear Mixed Integer Programming (MINLP). The solution is:
---------------------------------------------------
Solver : APOPT (v1.0)
Solution time : 2.610000000277068E-002 sec
Objective : 70.0000000000000
Successful solution
---------------------------------------------------
x: 1.0
obj: 70.0
Here is the Python script:
import numpy as np
from gekko import GEKKO
m = GEKKO()
X1 = m.Param([3,10,20,10])
X2 = m.Param([5,1,3,4])
X3 = m.Param([2,3,1,4])
X4 = m.Param([10,0,1,2])
M = 100
p = m.Array(m.FV,4,lb=0,ub=10); a,b,c,d=p
b.upper = 5; c.upper = 5
for pi in p:
pi.STATUS=1
x = m.FV(lb=0,ub=1,integer=True); x.STATUS=1
Y1,Y2 = m.Array(m.Var,2)
delta = m.FV(); delta.STATUS=1
m.Equations([Y1 <= X1 - a,
Y1 <= X2 - b,
Y1 >= X1 - a - M*delta,
Y1 >= X2 - b - M*(1-delta),
Y2 <= X3 - c,
Y2 <= X4 - d,
Y2 >= X3 - c - M*delta,
Y2 >= X4 - d - M*(1-delta),
delta == x])
m.Minimize((Y1-Y2)**2)
m.options.IMODE=2
m.options.SOLVER=1
m.solve()
print('x: ', x.value[0])
print('obj: ', m.options.OBJFCNVAL)

Solving linear equations error in python

I am trying to solve the following system of linear equations:
#x0 + 1/10 * (x1 + x2 + x3 + x4) = 10
#x1 + 1/15 * (x1 + x2 + x3 + x4 + x5) = 20
#x2 + 1/21 * (x1 + x2 + x3 + x4 + x5 + x6) = 30
To do so I am doing:
a = np.array([[1,1/10,1/10,1/10,1/10,0,0],[0,1+1/15,1/15,1/15,1/15,1/15,0],[0,1/21,1+1/21,1/21,1/21,1/21]])
b=np.array([10,20,30])
x = np.linalg.solve(a, b)
For which I get the following error:
LinAlgError: 1-dimensional array given. Array must be at least two-dimensional
Can someone point out what am I doing wrong? The array has correct entries as I checked. I am following the example here
It looks to me as though there is an error in the last line of the matrix - I count 5 commas rather than 6.
With your version a.shape is (3,)
a = np.array([[1,1/10,1/10,1/10,1/10,0,0],[0,1+1/15,1/15,1/15,1/15,1/15,0],[0,1/21,1+1/21,1/21,1/21,1/21,1/21]])
With the missing element as above, a.shape is (3,7) which seems correct.
Also as noted in the comment, you have 7 unknowns and only 3 equations so you have an underdetermined system.

How to I get Gurobi to give only integer solutions?

I'm trying to optimize the following problem in python using Gurobi and the answer comes out as a decimal. How do I get the output to solve for optimal integers?
from gurobipy import *
def main():
pass
if __name__ == '__main__':
main()
try:
#Create a new model
m = Model("Investment");
#Create variables
x1 = m.addVar(vtype=GRB.CONTINUOUS, name="x1")
x2 = m.addVar(vtype=GRB.CONTINUOUS, name="x2")
x3 = m.addVar(vtype=GRB.CONTINUOUS, name="x3")
x4 = m.addVar(vtype=GRB.CONTINUOUS, name="x4")
x5 = m.addVar(vtype=GRB.CONTINUOUS, name="x5")
#Intigrate new variables
m.update()
#Set Objective
m.setObjective(160*x1 + 160*x2 + 160*x3 + 75*x4 + 75*x5, GRB.MINIMIZE)
m.addConstr( x1 + x2 + x3 >= 3, "c0")
m.addConstr( x1 >= 1, "c1")
m.addConstr( x2 >= 0, "c2")
m.addConstr( x3 >= 1, "c3")
m.addConstr( x4 >= 0, "c4")
m.addConstr( x5 >= 0, "c5")
m.addConstr(40*x1 + 40*x2 + 40*x3 + 25*x4 + 25*x5 >= 365,"c6")
m.optimize()
for v in m.getVars():
print v.varName, v.x
print "Obj:", m.objVal
except GurobiError:
print "Error reported"
Use .addVar(vtype=GRB.INTEGER, ...).
See http://www.gurobi.com/documentation/5.6/reference-manual/py_model_addvar
vtype = GRB.INTEGER
For binary vtype = GRB.BINARY, total 5 variables types

Categories

Resources