I am Currently working on some optimization problem which involves non-linear constraint. The problem is as follows :
I need to perform either of the two minimizations shown in image in python. I found library scipy which has optimize.minimize() function but I am unable to fit in the Non-Linear constraint using scipy.NonLinearConstraint. Can anyone guide? How to solve this? Is there also a way to solve it using some homotopy function given in any of the libraries? I have tried (adding constraint for the alternative one)as:
con = lambda A,x,y : np.matmul(A,x) - y
nlc = NonlinearConstraint(con, 0, epsilon)
So, I finally could solve the above optimization by using spgl1 solver in python. It can be used as shown below:
from spgl1 import spgl1, spg_bp, spg_bpdn
#x01 = psueodinverse of A multiplied by y
x,resid,grad,info = spgl1(A, y, tau = tau, sigma = epsilon, x0 = x01, iter_lim = 150)
one can refer about the above solver at github link or pypi link
Related
I need to solve a large number of small convex optimisation problems with the same constraints, so I am trying to use cvxpy's DPP feature to cache/speedup compilation. It doesn't seem to work for my problem containing a single complex matrix parameter L.
import numpy as np
import cvxpy as cp
A = np.eye(4)+np.eye(4)*1j
L = cp.Parameter((4,4),complex=True)
X = cp.Variable((4,4),hermitian=True)
obj = cp.Minimize(cp.norm(X-L,'fro'))
prob = cp.Problem(obj)
L.value = A
assert prob.is_dcp(dpp=True)
prob.solve(solver=cp.SCS,verbose=True)
If I change the definitions of A and L to A=np.eye(4) and L = cp.Parameter((4,4)), then I do see the (Subsequent compilations of this problem, using the same arguments, should take less time.) message in the verbose print out.
I am using cvxpy version 1.2.1.
Does anyone know what's going on? Many thanks!
When a scalar parameter is multiplied with a variable, CVXPY outputs the DCPError
DCPError: Product of two non-constant expressions is not DCP.
but
problem.is_dcp() returns True
Here is the code to reproduce this error.
import cvxpy as cp
import numpy as np
lam = cp.Variable(pos=True)
lam_min = cp.Parameter(pos=True, value=1.0)
g = cp.Parameter(pos=True, value=1.0)
constraints = [
lam >= lam_min,
]
objective_fn = g*lam
problem = cp.Problem(cp.Minimize(objective_fn), constraints)
print(problem.is_dcp())
problem.solve()
It is solving the following simple linear problem in one dimension
minimize g*lam
subject to lam >= lam_min
The question is
Why does the solver say that the problem is DCP and at the same time output a DCPError?
Update following sascha'a comment
I was running the script from Spyder on Ubuntu. Following sascha's comment that the snippet was generating no error for them, I ran the script inside a terminal and indeed there is no error!
Why is there this error when the script is run within Spyder but not in a terminal?
I have a mixed integer non linear problem in Pyomo with an objective function and several constraints consisting of non-linear terms and binary variables.
The popular solver "ipopt" finds a solution, but it treats the binary variables as continuous variables.
opt=SolverFactory("ipopt")
results=opt.solve(instance)
results.write()
instance.load(results)
Now I have already tried desperately to try two solvers that can solve mixed-integer non-linear problems.
First I tried the MindPy solver ( https://pyomo.readthedocs.io/en/stable/contributed_packages/mindtpy.html). Unfortunately without success:
I always get the error message: "type NoneType doesn't define round method". This surprises me, because the ipopt-solver finds a solution without problems and the mindtpy-solver is a mixture of a linear solver and a non-linear solver and should actually get this solved.
opt=SolverFactory('mindtpy').solve(instance, mip_solver="glpk", nlp_solver="ipopt", tee=True)
results=opt.solve(instance)
results.write()
instance.load(results)
2)Then I tried the apopt solver. You have to download it separately from "https://github.com/APMonitor/apopt" and put all files into the working directory.
Then I tried to execute the following code, unfortunately without success:
opt=SolverFactory("apopt.py")
results=opt.solve(instance)
results.write()
instance.load(results)
I always get the following error message: "Error message: [WinError 193] %1 is not a valid Win32 application". This is probably related to the fact that my Python interpreter requires an apopt.exe since I have a Windows machine. Attempts such as converting the .py to an .exe file have failed. Also, specifying Solverfactory(..., "executable=C\Users\Python...\\apopt.py" separately did not work.
Does anyone have an idea how to get the solver "apopt" and/or the solver "Mindtpy" to work and can do something with the error messages?
Thank you very much in advance!
Edit:
Here is an exemplary and simple concrete model. I have tried to translate it into easier code. As I've already said, the ipopt solver finds a solution:
model = pyo.ConcreteModel()
model.x = pyo.Var([1,2,3,4], domain=pyo.NonNegativeReals)
model.x = pyo.Var([5], domain=pyo.Binary)
model.OBJ = pyo.Objective(expr = 2*model.x[1] + 3*model.x[2] + 3*model.x[3] + 4*model.x[4])
model.Constraint1 = pyo.Constraint(expr = 3*model.x[1] + 4*model.x[2] >= 1)
model.Constraint2 = pyo.Constraint(expr = 3*model.x[3] + 4*model.x[4] >= 1)
model.Constraint3 =pyo.Constraint(expr = 1000*cos(model.x[3]) < 1000)
model. Constraint4=pyo.Constraint(expr = 1000*sin(model.x[4]) < 1000)
model.Constraint5=pyo.Constraint(expr = model.x[2] <= 10000*(1-model.x[5])
model.Constraint6= pyo.Constraint (expr=model.x[2] <= 10000*(model.x[5]))
Try adding the path to apopt.py to the PATH variable. The apopt.py program acts like an executable with the model.nl as an argument to the solver and it produces a sol solution file that is then processed to retrieve the solution. Unlike other solvers in AIMS or Pyomo, APOPT computes remotely on a public server. Here are additional instructions on running APOPT.
APOPT Solver
APOPT (for Advanced Process OPTimizer) is a software package for solving large-scale optimization problems of any of these forms:
Linear programming (LP)
Quadratic programming (QP)
Quadratically constrained quadratic program (QCQP)
Nonlinear programming (NLP)
Mixed integer programming (MIP)
Mixed integer linear programming (MILP)
Mixed integer nonlinear programming (MINLP)
Applications of the APOPT include chemical reactors, friction stir welding, prevention of hydrate formation in deep-sea pipelines, computational biology, solid oxide fuel cells, and flight controls for Unmanned Aerial Vehicles (UAVs). APOPT is supported in AMPL, APMonitor, Gekko, and Pyomo.
APOPT Online Solver for Mixed Integer Nonlinear Programming Reads output from AMPL, Pyomo, or other NL File Writers. Similar to other solvers, this script reads the model (NL) file and produces a solution (sol) file. It sends the NL file to a remote server, computes a solution (remotely), and retrieves a solution (sol) file through an internet connection. It communicates with the server http://byu.apopt.com that is hosting the APOPT solver. Contact support#apmonitor.com for support, especially if there is a feature request or a concern about a problem solution.
Instructions for usage:
Place apopt.py in an appropriate folder in the system path (e.g. Linux, /usr/bin/)
Set appropriate permissions to make the script executable (e.g. chmod 775 apopt.py)
In AMPL, Pyomo, or other NL file write, set solver option to apopt.py
Test installation by running apopt.py -test
Visit apopt.com for additional information and solver option help
Information on the APOPT solver with references can be found at the Wikipedia article for APOPT. APOPT has integration with Gekko and can run locally with m=GEKKO(remote=False).
"type NoneType doesn't define round method"
You should (almost) never use a round() function in your MINLP model. It is not needed either. Instead, use an integer variable, like in:
x-0.5 <= y <= x+0.5
x continuous variable
y integer variable
The reason why round() is really, really bad, is because it is non-differentiable and not continuous. Almost all NLP and MINLP solvers assume smooth functions (sometimes it is useful to read the documentation).
After fixing your model (quite a few problems with it), I could not reproduce the error message about round().
D:\tmp>type pyom1.py
import pyomo.environ as pyo
model = pyo.ConcreteModel()
model.x = pyo.Var([1,2,3,4], domain=pyo.NonNegativeReals)
model.y = pyo.Var(domain=pyo.Binary)
model.OBJ = pyo.Objective(expr = 2*model.x[1] + 3*model.x[2] + 3*model.x[3] + 4*model.x[4])
model.Constraint1 = pyo.Constraint(expr = 3*model.x[1] + 4*model.x[2] >= 1)
model.Constraint2 = pyo.Constraint(expr = 3*model.x[3] + 4*model.x[4] >= 1)
model.Constraint3 = pyo.Constraint(expr = 1000*pyo.cos(model.x[3]) <= 1000)
model.Constraint4 = pyo.Constraint(expr = 1000*pyo.sin(model.x[4]) <= 1000)
model.Constraint5 = pyo.Constraint(expr = model.x[2] <= 10000*(1-model.y))
model.Constraint6 = pyo.Constraint (expr=model.x[2] <= 10000*(model.y))
pyo.SolverFactory('mindtpy').solve(model, mip_solver='cbc', nlp_solver='ipopt', tee=True)
D:\tmp>python.exe pyom1.py
INFO: ---Starting MindtPy---
INFO: Original model has 6 constraints (2 nonlinear) and 0 disjunctions, with
5 variables, of which 1 are binary, 0 are integer, and 4 are continuous.
INFO: rNLP is the initial strategy being used.
INFO: NLP 1: Solve relaxed integrality
INFO: NLP 1: OBJ: 1.666666661289117 LB: -inf UB: inf
INFO: ---MindtPy Master Iteration 0---
INFO: MIP 1: Solve master problem.
INFO: MIP 1: OBJ: 1.6666666499999998 LB: 1.6666666499999998 UB: inf
INFO: NLP 2: Solve subproblem for fixed binaries.
INFO: NLP 2: OBJ: 1.6666666716089886 LB: 1.6666666499999998 UB:
1.6666666716089886
INFO: MindtPy exiting on bound convergence. LB: 1.6666666499999998 + (tol
0.0001) >= UB: 1.6666666716089886
D:\tmp>
I'm fairly new to this, so I'm just going to shoot and hope I'm as precise as possible and you'll think it warrants an answer.
I'm trying to optimize (minimize) a cost/quantity model, where both are continuous variables. Global cost should be minimized, but is dependent on total quantity, which is dependent on specific cost.
My code looks like this so far:
# create model
m = Model('Szenario1')
# create variables
X_WP = {}
X_IWP = {}
P_WP = {}
P_IWP = {}
for year in df1.index:
X_WP[year] = m.addVar(vtype=GRB.CONTINUOUS, name="Wärmepumpe%d" % year)
X_IWP[year] = m.addVar(vtype=GRB.CONTINUOUS, name="Industrielle Wärmepumpe%d" % year)
#Price in year i = Base.price * ((Sum of newly installed capacity + sum of historical capacity)^(math.log(LearningRate)/math.log(2)))
P_WP[year] = P_WP0 * (quicksum(X_WP[year] for year in df1.index) ** (learning_factor)
P_IWP[year] = m.addVar(vtype=GRB.CONTINUOUS, name="Preis Industrielle Wärmepumpe%d" % year)
X_WP[2016] = 0
X_IWP[2016] = 0
# Constraints and Objectives
for year in df1.index:
m.addConstr((X_WP[year]*VLST_WP+X_IWP[year]*VLST_IWP == Wärmemenge[year]), name="Demand(%d)" % year)
obj = quicksum(
((X_WP[year]-X_WP[year-1])*P_WP[year]+X_WP[year]*Strompreis_WP*VLST_WP)+
((X_IWP[year]-X_IWP[year-])*P_IWP[year]+X_IWP[year]*Strompreis_EHK*VLST_IWP)
for year in Wärmemenge.index)
m.setObjective(obj, GRB.MINIMIZE)
m.update()
m.optimize()
X is quantity and P is price. WP and IWP are two different technologies (more will be added later). Since X and P are multiplied the problem is nonlinear, now I haven't found a solution so far as to feed gurobi an objective, that it can handle.
My research online and on stackoverflow basically let me to the conclusion that I can either linearize and solve with gurobi, find another solver that can solve this MINLP or formulate my objective in a way that Gurobi can solve. Since I've already made myself familiar with Gurobi, that would be my prefered choice.
Any advice on what's best at this point?
Would be highly appreciated!
I'd suggest rewriting your Python code using Pyomo.
This is a general-purpose optimization modeling framework for Python which can construct valid inputs for Gurobi as well as a number of other optimization tools.
In particular, it will allow you to use Ipopt as a backend, which does solve (at least some) nonlinear problems. Even if Ipopt cannot solve your nonlinear problem, using Pyomo will allow you to test that quickly and then easily move back to a linearized representation in Gurobi if things don't work out.
Hello and thanks in advance. Fresh off the heels of this question I acquired some more RAM and now have enough memory to fit all the matrices I need to run a linear programming solver. Now the problem is none of the Linear Programming packages in R seem to support long vectors (ie large matrices).
I've tried functions Rsymphony_solve_LP, Rglpk_solve_LP and lp from packages Rsymphony, Rglpk, and lpSolve respectively. All report a similar error to the one below:
Error in rbind(const.mat, const.dir.num, const.rhs) :
long vectors not supported yet: bind.c:1544
I also have my code below in case that helps...the constraint matrix mat is my big matrix (7062 rows by 364520 columns) created using the package bigmemory. When I run this this line the matrix is pulled into memory and then after a while the errors show.
Rsymph <- Rsymphony_solve_LP(obj,mat[1:nrow(mat),1:ncol(mat)],dir,rhs,types=types,max=max, write_lp=T)
I'm guessing this is a hard-coded error in each of the three functions? Is there currently a linear programming solver in R or even Python that supports long vectors? Should I contact the package maintainers or just edit the code myself? Thanks!
The package lpSolveAPI can solve long-vector linear programming problems. You have to first start my declaring a Linear Programming object, then add the constraints:
library(lpSolveAPI)
#Generate Linear Programming Object
lprec <- make.lp(nrow = 0 # Number of Constraints
, ncol = ncol(mat) # Number of Decision Variables
)
#Set Objective Function to Minimize
set.objfn(lprec, obj)
#Add Constraints
#Note Direction and RHS is included along with Constraint Value
for(i in 1:nrow(mat) ){
add.constraint(lprec,mat[i,], dir[i], rhs[i])
print(i)
}
#Set Decision Variable Type
set.type(lprec, c(1:ncol(mat)), type = c("binary"))
#Solve Model
solve(lprec)
#Obtain Solutions
get.total.iter(lprec)
get.objective(lprec)
get.variables(lprec)
There's a good introduction to this package here.