CPLEX and MOSEK with YALMIP gives different results - optimization

I am solving an optimization problem using MATLAB with YALMIP which is similar to a unit commitment problem.
This is a Mixed Integer Linear Programming problem.
I am considering two decision variables --> P and T_room
I formulated the problem in MATLAB with YALMIP,
When I use CPLEX and MOSEK solvers, I am getting different results.
Can anyone explain to me why that is happening?
CPLEX solver results
MOSEK solver results
clc;
clear all;
rng(0,'twister');
%% time step of the demand response --> 15 mins
deltaT = 15/60 ;
%% number of air conditioners
Nunits = 3;
%% demand required for each interval
Pdemand = [2 3 4 2 5 5 8 9]';
% Pdemand = randi([2,10],8,1);
%% time interval considered for the study --> 15 mins intervals for 2
%%% hours
Horizon = length(Pdemand) ;
%% cost for each appliance ( need to think little about this approach )
Q = diag([rand(1,Nunits)]);
%% defining the possible reduction levels for the appliances
% ratedPower = [1 6 4]';
ratedPower = randi([5,7],Nunits,1);
%% defining minimum and maximum power limits for the appliances
Pmax = randi([6,8],Nunits,1);
Pmin = zeros(Nunits,1);
% possible power levels for appliances (discrete levels)
LevelsOutput = [0 0.5 0.75 1.0] ;
% matrix containing all the possible levels of output power for all the
%% appliances
PowerLevelMatrix = ratedPower * LevelsOutput ;
%% parameters based on the temperature
%%% outside temperature (we assume that the outdoor temperature remains the same throughout the optimisation process)
T_outdoor = randi([34, 38], Nunits,1);
%%% preferred lower level of temperature for the appliances
T_lower = randi([20,21], Nunits,1) ;
%%% preferred upper level of temperature for the appliances
T_upper = randi([28, 29], Nunits,1) ;
%%% initial temperature for the appliances
T_initial = randi([22, 28], Nunits,1);
%% parameters of the house
%% equivalent thermal resistance
R = (2.5-1.5)*rand(Nunits,1) + 1.5 ;
%%% equivalent thermal capacitance
Ca = (2.5-1.5)*rand(Nunits,1) + 1.5 ;
%% for the air condtioner
c = repmat(0.03,Nunits,1);
d = repmat(-0.4,Nunits,1);
a = repmat(0.06,Nunits,1);
b = repmat(-0.3,Nunits,1);
%% defining the variables of the demand response problem
%%% power levels for the appliances
P = sdpvar(Nunits, Horizon, 'full');
%% slack variable for exceeding the demand
% Demand_Penalty = 50;
% DemandSlack = sdpvar(1,Horizon);
%% decision variable for the room temperature
T_room = sdpvar(Nunits,Horizon,'full') ;
%% Constraints for the optimisation problem
Constraints = [];
for k = 1: Horizon
% Constraints = [Constraints, sum(P(:,k)) + DemandSlack(k) >= Pdemand(k)];
% Constraints = [Constraints,DemandSlack(k) >= 0];
Constraints = [Constraints, sum(P(:,k))>= Pdemand(k)];
end
%%% constraint on min amd max power levels
for k = 1: Horizon
Constraints = [Constraints, Pmin <= P(:,k) <= Pmax];
end
%%% adding the constraint on discrete power levels for each appliance
for nApp = 1 : Nunits
for k = 1 : Horizon
Constraints = [Constraints, ismember(P(nApp,k),PowerLevelMatrix(nApp,:))];
end
end
%% the temperature should be within the desired limits --> cannot go beyond those limits
for k = 2: Horizon
Constraints = [Constraints, T_lower <= T_room(:,k) <= T_upper ];
end
%% adding the initial constraint of temperature
Constraints = [Constraints, T_room(:,1) == T_initial];
%%% adding the temperature model of the constraint for the inverter type
%%% air condtioner
for k = 2: Horizon
Constraints = [Constraints, T_room(:,k) == T_outdoor - ((a./c).*P(:,k) + ((b.*c - a.*d)./c)).*R.*(1- exp((-deltaT)./(R.*Ca))) - T_outdoor.* exp((-deltaT)./(R.*Ca)) + T_room(:,k-1).* exp((-deltaT)./(R.*Ca)) ];
end
%% adding a sample constraints to the temperature update
% for k =2: Horizon
%
% Constraints = [Constraints, T_room(:,k) == T_room(:,k-1) ];
% end
%%% defining the objective function
% weighting factors
alpha = 1 ;
beta = 1 ;
Objective = 0 ;
for k = 2 : Horizon
Objective = Objective + alpha * Q * P(:,k) + beta * ((2* T_room(:,k) - T_lower - T_upper)./(T_upper - T_lower));
% Objective = Objective + P(:,k)' * Q * P(:,k);
% Objective = Objective + Demand_Penalty * DemandSlack(k) ;
end
%%% solving the optimisation problem
%
ops = sdpsettings('verbose',2, 'debug', 1, 'solver', 'mosek');
% ops = sdpsettings('verbose',1, 'debug', 1);
solution = optimize (Constraints, Objective, ops) ;
Pout = value(P);
T_room_out = value(T_room);

Your code does not make sense to begin with, as your objective is a vector
>> Objective
Linear matrix variable 3x1 (full, real, 42 variables)
With that, YALMIP will solve three optimization problems, and then values you obtain when applying value command will be the values from the last solution.
Having said that, concentrating on the last objective you have defined (although I think you intended to minimize the sum or something), I get the same objective with both solvers (not the same solution, the solution simply isn't unique)
>> solution = optimize (Constraints, Objective(3), sdpsettings('solver','cplex'))
>> value(Objective(3))
ans =
1.8418
>> value(P)
ans =
0 5.2500 3.5000 5.2500 3.5000 5.2500 5.2500 5.2500
0 3.0000 3.0000 6.0000 6.0000 6.0000 3.0000 4.5000
5.0000 5.0000 5.0000 5.0000 5.0000 5.0000 0 0
>> solution = optimize (Constraints, Objective(3), sdpsettings('solver','mosek'))
>> value(Objective(3))
ans =
1.8418
ans =
3.5000 3.5000 3.5000 3.5000 3.5000 3.5000 5.2500 5.2500
3.0000 3.0000 3.0000 3.0000 6.0000 0 3.0000 6.0000
3.7500 5.0000 5.0000 5.0000 5.0000 5.0000 0 0

Related

Create arrays of variables in loop GEKKO

I'm wondering if it is possible to create arrays of variables with different lenghts in a loop in GEKKO.
Below is just a simple example of what I mean. Parameters in the list "lengths" define what length each GEKKO array should have:
lengths = [10,20,30]
m = GEKKO()
for i in lengths:
# something...
So from this I would like to get something like:
array1 = m.Array(m.Var,10)
array2 = m.Array(m.Var,20)
array3 = m.Array(m.Var,30)
In the real problem that I'm trying to solve there will be quite many arrays that I want to include in the optimization, and they might be different depending on the situation. So it is not a good option to manually create them every time.
There is no problem to define arrays in a loop. Here is an example:
from gekko import GEKKO
model = GEKKO(remote=True)
lengths = [10,20,30]
m = GEKKO()
x = []
for i in lengths:
x.append(m.Array(m.Var,i))
for j in range(i):
m.Minimize((x[-1][j]-j)**2)
m.solve()
for xi in x:
print(xi)
This gives a unique solution where the value is equal to the index.
This is Ipopt version 3.12.10, running with linear solver ma57.
Number of nonzeros in equality constraint Jacobian...: 0
Number of nonzeros in inequality constraint Jacobian.: 0
Number of nonzeros in Lagrangian Hessian.............: 60
Total number of variables............................: 60
variables with only lower bounds: 0
variables with lower and upper bounds: 0
variables with only upper bounds: 0
Total number of equality constraints.................: 0
Total number of inequality constraints...............: 0
inequality constraints with only lower bounds: 0
inequality constraints with lower and upper bounds: 0
inequality constraints with only upper bounds: 0
iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
0 1.1310000e+04 0.00e+00 5.80e+01 0.0 0.00e+00 - 0.00e+00 0.00e+00 0
1 0.0000000e+00 0.00e+00 0.00e+00 -11.0 2.90e+01 - 1.00e+00 1.00e+00f 1
Number of Iterations....: 1
(scaled) (unscaled)
Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00
Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00
Constraint violation....: 0.0000000000000000e+00 0.0000000000000000e+00
Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00
Overall NLP error.......: 0.0000000000000000e+00 0.0000000000000000e+00
Number of objective function evaluations = 2
Number of objective gradient evaluations = 2
Number of equality constraint evaluations = 0
Number of inequality constraint evaluations = 0
Number of equality constraint Jacobian evaluations = 0
Number of inequality constraint Jacobian evaluations = 0
Number of Lagrangian Hessian evaluations = 1
Total CPU secs in IPOPT (w/o function evaluations) = 0.001
Total CPU secs in NLP function evaluations = 0.000
EXIT: Optimal Solution Found.
The solution was found.
The final value of the objective function is 0.000000000000000E+000
---------------------------------------------------
Solver : IPOPT (v3.12)
Solution time : 4.600000000209548E-003 sec
Objective : 0.000000000000000E+000
Successful solution
---------------------------------------------------
[[0.0] [1.0] [2.0] [3.0] [4.0] [5.0] [6.0] [7.0] [8.0] [9.0]]
[[0.0] [1.0] [2.0] [3.0] [4.0] [5.0] [6.0] [7.0] [8.0] [9.0] [10.0] [11.0]
[12.0] [13.0] [14.0] [15.0] [16.0] [17.0] [18.0] [19.0]]
[[0.0] [1.0] [2.0] [3.0] [4.0] [5.0] [6.0] [7.0] [8.0] [9.0] [10.0] [11.0]
[12.0] [13.0] [14.0] [15.0] [16.0] [17.0] [18.0] [19.0] [20.0] [21.0]
[22.0] [23.0] [24.0] [25.0] [26.0] [27.0] [28.0] [29.0]]

Optimizing a Summation function - GEKKO

I just started learning optimization and I have some issues finding the optimal value for the problem below.
Note: This is just a random problem that came to my mind and has no real application.
Problem:
where x can be any value from the list ([2,4,6]) and y is between 1 and 3.
My attempt:
from gekko import GEKKO
import numpy as np
import math
def prob(x,y,sel):
z = np.sum(np.array(x)*np.array(sel))
cst = 0
i=0
while i <= y.VALUE:
fact = 1
for num in range(2, i + 1): # find the factorial value
fact *= num
cst += (z**i)/fact
i+=1
return cst
m = GEKKO(remote=False)
sel = [2,4,6] # list of possible x values
x = m.Array(m.Var, 3, **{'value':1,'lb':0,'ub':1, 'integer': True})
y = m.Var(value=1,lb=1,ub=3,integer=True)
# switch to APOPT
m.options.SOLVER = 1
m.Equation(m.sum(x) == 1) # restrict choice to one selection
m.Maximize(prob(x,y,sel))
m.solve(disp=True)
print('Results:')
print(f'x: {x}')
print(f'y : {y.value}')
print('Objective value: ' + str(m.options.objfcnval))
Results:
----------------------------------------------------------------
APMonitor, Version 0.9.2
APMonitor Optimization Suite
----------------------------------------------------------------
--------- APM Model Size ------------
Each time step contains
Objects : 0
Constants : 0
Variables : 4
Intermediates: 0
Connections : 0
Equations : 2
Residuals : 2
Number of state variables: 4
Number of total equations: - 1
Number of slack variables: - 0
---------------------------------------
Degrees of freedom : 3
----------------------------------------------
Steady State Optimization with APOPT Solver
----------------------------------------------
Iter: 1 I: 0 Tm: -0.00 NLPi: 2 Dpth: 0 Lvs: 0 Obj: -7.00E+00 Gap: 0.00E+00
Successful solution
---------------------------------------------------
Solver : APOPT (v1.0)
Solution time : 0.024000000000000004 sec
Objective : -7.
Successful solution
---------------------------------------------------
Results:
x: [[0.0] [0.0] [1.0]]
y : [1.0]
Objective value: -7.0
x should be [0,0,1] (i.e. 6) and y should be 3 to get the maximum value (61). x value I get is correct but for some reason the y value I get is wrong. What is causing this issue ? Is there something wrong with my formulation ? Also it would be very helpful if you could kindly point me towards more information about the various notations (like Tm, NLPi, etc) in APOPT solver output.
Here is a solution in gekko:
x=6.0
y=3.0
You'll need to use the gekko functions to build the functions and pose the problem in a way so that the equations don't change as the variable values change.
from gekko import GEKKO
import numpy as np
from scipy.special import factorial
m = GEKKO(remote=False)
x = m.sos1([2,4,6])
yb = m.Array(m.Var,3,lb=0,ub=1,integer=True)
m.Equation(m.sum(yb)==1)
y = m.sum([yb[i]*(i+1) for i in range(3)])
yf = factorial(np.linspace(0,3,4))
obj = x**0/yf[0]
for j in range(1,4):
obj += x**j/yf[j]
m.Maximize(yb[j-1]*obj)
m.solve()
print('x='+str(x.value[0]))
print('y='+str(y.value[0]))
print('Objective='+str(-m.options.objfcnval))
For your problem, I used a Special Ordered Set (type 1) to get the options of 2, 4, or 6. To select y as 1, 2, or 3 I calculated all possible values and then used a binary selector yb to choose one. There is a constraint that only one of them can be used with m.sum(yb)==1. There are gekko examples, documentation, and a short course available if you need additional resources.
Here is the solver output:
----------------------------------------------------------------
APMonitor, Version 0.9.2
APMonitor Optimization Suite
----------------------------------------------------------------
--------- APM Model Size ------------
Each time step contains
Objects : 1
Constants : 0
Variables : 11
Intermediates: 1
Connections : 4
Equations : 10
Residuals : 9
Number of state variables: 11
Number of total equations: - 7
Number of slack variables: - 0
---------------------------------------
Degrees of freedom : 4
----------------------------------------------
Steady State Optimization with APOPT Solver
----------------------------------------------
Iter: 1 I: 0 Tm: 0.00 NLPi: 6 Dpth: 0 Lvs: 0 Obj: -6.10E+01 Gap: 0.00E+00
Successful solution
---------------------------------------------------
Solver : APOPT (v1.0)
Solution time : 0.047799999999999995 sec
Objective : -61.
Successful solution
---------------------------------------------------
x=6.0
y=3.0
Objective=61.0
Here is more information on the solver APOPT options. The iteration summary describes the branch and bound progress. It is Iter=iteration number, Tm=time to solve the NLP, NLPi=NLP iterations, Dpth=depth in the branching tree, Lvs=number of candidates leaves, Obj=NLP solution objective, and Gap=gap between integer solution and best non-integer solution.
equation to be minimzedhey how to solve these type of prolems
problem:
Minimization
summation(xij*yij)
i=from 0 to 4000
j= from 0 to 100
y is coast matrix given
m = GEKKO(remote=False)
dem_var = m.Array(m.Var,(4096,100),lb=0)
for i,j in s_d:
m.Minimize(sum([dem_var[i][j]*coast_new[i][j]]))
here y=coast_new
x= dem_var

Optimization of MiniZinc model

I have a MiniZinc model which is supposed to find d[1 .. n] and o[1..k, 0 .. n] such that
x[k] = o[k,0] + d[1]*o[k,1] + d[2]*o[k,2] ... d[n]+o[k,n] and the sum of absolute values of o[k,i]'s is minimized.
I have many different x[i] and d[1..n] should remain the same for all of them.
I have a working model which is pasted below, which finds a good solution in the n=2 case really quickly (less than a second) however, if I go to n=3 (num_dims in the code) even after an hour I get no answer except the trivial one (xi=o0), even though the problem is somewhat recursive, in that a good answer for 2 dimensions can serve as a starting point for 3 dimensions by using o0 as xi for a new 2 dimensional problem.
I have used MiniZinc before, however, I do not have a background in OR or Optimization, thus I do not really know how to optimize my model. I would be helpful for any hints on how to do that, either by adding constraints or somehow directing the search. Is there a way to debug such performance problems in MiniZinc?
My current model:
% the 1d offsets
array [1 .. num_stmts] of int : x;
x = [-10100, -10001, -10000, -9999, -9900, -101, -100, -99, -1, 1, 99, 100, 101, 9900, 9999, 10000, 10001, 10100];
int : num_stmts = 18;
% how many dimensions we decompose into
int : num_dims = 2;
% the dimension sizes
array [1 .. num_dims] of var int : dims;
% the access offsets
array [1 .. num_stmts, 1 .. num_dims] of var int : offsets;
% the cost function: make access distance (absolute value of offsets) as small as possible
var int : cost = sum (s in 1 .. num_stmts, d in 1 .. num_dims) (abs(offsets[s,d]));
% dimensions must be positive
constraint forall (d in 1 .. num_dims) (dims[d] >= 0);
% offsets * dimensions must be equal to the original offsets
constraint forall (s in 1 .. num_stmts) (
x[s] = offsets[s,1] + sum(d in 2 .. num_dims) (offsets[s,d] * dims[d-1])
);
% disallow dimension crossing
constraint forall (s in 1 .. num_stmts, d in 1 .. num_dims) (
abs(offsets[s,d]) < dims[d]
);
% all dims together need to match the array size
constraint product (d in 1..num_dims) (dims[d]) = 1300000;
solve minimize cost;
output ["dims = ", show(dims), "\n"] ++
[ if d == 1 then show_int(6, x[s]) ++ " = " else "" endif ++
" " ++ show_int(4, offsets[s, d]) ++ if d>1 then " * " ++ show(dims[d-1]) else "" endif ++
if d == num_dims then "\n" else " + " endif |
s in 1 .. num_stmts, d in 1 .. num_dims];
Are you using the MiniZinc IDE? Have you tried using a different solver?
I was struggling with a problem of dividing n random positive integers into m groups (m < n) where the sum of each group was supposed to be as close as possible to some other number.
When n reached about 100 and m about 10, it took significantly longer time (30 min+) and the result was not satisfying. This was using the default Gecode (bundled) solver. By chance I went through each and everyone of the solvers and found that the COIN-OR CBC (bundled) found an optimal solution within 15 s.

Constrained quadratic minimization in Mathematica with matrices

I'm attempting to solve the familiar mean-variance optimization problem using matrices in Mathematica, with a few added constraints on the solution vector "w". (The mean-variance optimization problem is basically choosing how to allocate a given budget over a number of assets according to their means and covariances in order to minimize the risk of the portfolio for a chosen level of mean return.)
My question: I'm not sure which function to use to perform the minimization of the objective function, which is quadratic:
obj = 0.5*w'* Sig * w
where w is the Nx1 vector of weights for each of the N assets and Sig is the NxN covariance matrix
From what I've been able to find (I'm fairly new to Mathematica), it seems that FindMinimum, NMinimize, etc. are meant to deal only with scalar inputs, while LinearProgramming is meant for an objective function that's linear (not quadratic) in the weight vector w. I could very well be wrong here--any help in steering me toward the correct function would be much appreciated!
If it helps, I've attached my sample code--I'm not sure how, but if there's a place to upload the sample .csv data, I can do that as well if someone could point me to it.
Thank you very much for any help you can provide.
-Dan
CODE
(* Goal: find an Nx1 vector of weights w that minimizes total \
portfolio risk w'*Sig*w (where Sig is the covariance matrix) subject to:
-The portfolio expected return is equal to the desired level d: w'*M \
= d, where M is the Nx1 vector of means
-There are exactly two assets chosen from each of the refining, \
construction, hitech, and utility sectors, and exactly one asset \
chosen from the "other" sector
^ The above two constraints are represented together as w'*R = k, \
where R is the matrix [M SEC] and k is the vector [d 2 2 2 2 1]
-Each weight in w takes an integer value of either 0 or 1, \
representing buying or not buying that physical asset (ex. a plant) -- \
this constraint is achieved as a combination of an integer constraint \
and a boundary constraint
**Note that for the T=41 days of observations in the data, not every \
asset generates a value for every day; by leaving the days when the \
asset is "off" as blanks, this shouldn't affect the mean or \
covariance matrices.
*)
Clear["Global`*"]
(* (1) Import the data for today *)
X = Import["X:\\testassets.csv", "Data"];
Dimensions[X];
(* (2) Create required vectors and matrices *)
P = Take[X, {2, 42}, {4}];
Dimensions[P]; (* Should be N assets x 1) *)
r = Take[X, {2, 42}, {10, 50}];
Dimensions[r]; (* Should be N x T *)
Sig = Covariance[
r]; (* When there's more time, add block diagonal restriction here \
*)
Dimensions[Sig]; (* Should be N x N *)
M = Mean[r\[Transpose]];
Dimensions[M]; (* Should be N x 1 *)
SEC = Take[X, {2, 42}, {5, 9}];
Dimensions[SEC]; (* Should be N x 5 *)
(* (3) Set up constrained optimization *)
d = 200; (* desired level of return *)
b = 60000;(* budget constraint *)
R = Join[M, POS];
Dimensions[R]; (* Should be N x 6 *)
k = {d, 2, 2, 2, 2, 1};
obj = w*Sig*w\[Transpose];
constr = w*R;
budgetcap = w*P;
lb = ConstantArray[0, 41];
ub = ConstantArray[1, 41];
FindMinimum[{obj, constr = k, budgetcap <= b, Element[w, Integers],
lb <= w <= ub}, w]

LP modeling with two binary variables with XPRESS

I am trying to solve a LP, which is a facility location problem.
The task asks me to deduct 10.000$ iff the optimal model results in having less than 3 Distribution Centers open (y1,y2,y3,y4).
The objective function looks like this: min z = Σ(fiyi) + ΣΣ(cijxij) + ΣΣ(xij*bi) - Σqi*10.000
fi: fixed costs
yi: binary variable; yi = 1 - DC is open; yi = 0 - DC is closed
cij: transportation costs from DC i to customer j
xij: quantity shipped from DC i to customer j
bi: variable warehouse costs at DC i
qi: binary variable; bi = 1 - IT Cost reduction yes; bi = 0 - no IT cost reduction
Now I need to introduce a logical constraint for having the "if..then..." thingy in it. I want to express the following dependence as a constraint in xpress:
if Σyi ≤ 2 ; then Σqi = 1 → IT cost reduction
if Σyi > 2 ; then Σqi = 0 → no IT cost reduction
Any help highly appreciated!
Solved it myself by introducing the following constraints:
3 ≤ Σyi + 2q ≤ 4