How to express exponential of a variable in docplex? - numpy

I need to define a constraint as follows:
mdl.add_constraints(p_pg[plan, segment] == np.exp(u_pg[plan, segment] for plan in range(1, p+1) for segment in range(1, g+1))
In this constraint both p_pg and u_pg are variable and are defined as mdl.continuous_var_dict. However I get the following error:
loop of ufunc does not support argument 0 of type Var which has no callable exp method
Can anyone help how to define this constraint?

exp is not linear so you could either try to do a piecewise linear approximation or use Constraint Programming within CPLEX.
See this example in Easy optimization with python
from docplex.cp.model import CpoModel
mdl = CpoModel(name='buses')
nbbus40 = mdl.integer_var(0,1000,name='nbBus40')
nbbus30 = mdl.integer_var(0,1000,name='nbBus30')
mdl.add(nbbus40*40 + nbbus30*30 >= 300)
#non linear objective
mdl.minimize(mdl.exponent(nbbus40)*500 + mdl.exponent(nbbus30)*400)
msol=mdl.solve()
print(msol[nbbus40]," buses 40 seats")
print(msol[nbbus30]," buses 30 seats")

Related

How to properly specify Jacobian & Hessian functions of inequality constraints in Optim

I’m trying to use the Optim package in Julia to optimize an objective function with 19 variables, and the following inequality constraints:
0 <= x[1]/3 - x[2] <= 1/3
5 <= 1/x[3] + 1/x[4] <= 6
I’m trying to use either IPNewton() or NewtonTrustRegion , so I need to supply both a Jacobian and Hessian for the constraints. My question is: what is the correct way to write the Jacobian and Hessian functions?
I believe the constraint function would be
function con_c!(c,x)
c[1] = x[1]/3 - x[2]
c[2] = 1/x[3] + 1/x[4]
c
end
Would the Jacobian function be
function con_jacobian!(J,x)
#first constraint:
J[1,1] = 1/3
J[1,2] = -1.0
#second constraint:
J[2,3] = -1/(x[3])^2
J[2,4] = -1/(x[4])^2
J
end
? (I assume all other indices of J are automatically set to zero?)
My main question: What would the Hessian function be? This is where I’m most confused. My understanding was that we take Hessians of scalar-valued functions. So do we have to enter multiple Hessians, one for each constraint function (2 in my case)?
I’ve looked at the multiple constraints example given here https://github.com/JuliaNLSolvers/ConstrainedOptim.jl , but I’m still confused. In the example, it looks like they are adding together two Hessian matrices…? Would greatly appreciate some help.
FD: I posted this question on Discourse two days ago but didn't receive a single response, which is why I'm posting it here.

CVXPY constraint: variable == 0 OR variable >= min

I am trying to solve a portfolio optimisation problem with the constraint that weights can be either zero or at least min (a Nx1 vector).
import cvxpy as cp
w = cp.Variable(len(mu))
mins = np.ones(len(mu)) * 0.03
risk = cp.quad_form(w, S)
prob = cp.Problem(cp.Minimize(risk),
[cp.sum(w) == 1,
w >= 0,
w >= min OR w == 0 # pseudocode for my desired constraint]
This is equivalent to a constraint that the weights are NOT 0 < w <= min, but I cannot find a way to express this in CVXPY (I have googled things like "cvxpy OR constraint" to no avail).
It feels like I'm missing something obvious. Perhaps there is a solution involving some boolean vector?
This is called w being a semi-continuous variable. Most advanced solvers support this type of variable directly. As CVXPY does not understand semi-continuous variables, we can use binary variables δ ∈ {0,1} and form the constraints:
δ⋅min ≤ w ≤ δ⋅max
where we can set max=1.
This makes the problem a MIQP (Mixed-Integer Quadratic Programming) problem. This usually means that you need to use a high-end solver that supports this type of model.
Based on Erwin's answer, this is the working code.
import cvxpy as cp
w = cp.Variable(n)
mins = np.ones(n) * 0.03
maxs = np.ones(n)
risk = cp.quad_form(w, S)
prob = cp.Problem(cp.Minimize(risk),
[cp.sum(w) == 1,
w >= 0,
w >= cp.multiply(k, mins),
w <= cp.multiply(k, maxs)])
prob.solve(solver="ECOS_BB")
EDIT: changed k # mins to cp.multiply(k, mins) as per comment

Why does AMPL not recognize degrees[j] as integer when 'degrees' is a set of integers?

Or is there another problem?
It is my first time trying AMPL. I am trying to solve a nonlinear dynamic program. Here are parts of the first draft:
#defining degree
param degree >= 0 integer; # degree of polynomial approximation
param degrees {alpha in 0..degree}; # for storing degrees
...
# defining variables for optimization
var b {alpha in 0..degree}; # coefficient of polynomial
...
# defining constraints
subject to Upper_bound {i in M}: v[i] <=
sum {k in 0..n} (comb[n,k]*(p^k)*((1-p)^(n-k))*((k/n)*((ch[k,i])^d)/(1-d)) +
((n-k)/n)*(cl[k,i]^d)/(1-d)+(1/(1+r))*(sum {j in 0..degree}
(b[j]*cos(degrees[j]*acos((2*Anew[i]-Amax)/(Amax)))))));
I get a syntax error when I pass the mod file:
model DP.mod;
DP.mod, line 41 (offset 1658):
syntax error
context: >>> (b[j]*cos(degrees[j]*acos((2*Anew[i]-Amax)/(Amax))))))) <<< ;
Please help.
It has been solved, thanks! There was an extra ending bracket.

Scipy code to solve optimization problem ( gurobi code is written!)

I wrote a Gorubi optimization code, but because of some issues, I need to convert to Scipy code. Still have difficulties to convert it. Here is a part of code related to Gorubi:
m = Model()
#x is charging, discharging variable
x = m.addVars(n,lb=-1.5,ub=1.5,vtype=GRB.INTEGER, name="x")
#Y is SOC variable
Y = m.addVars(n+1,lb=0,ub=100,vtype=GRB.CONTINUOUS, name="Y")
# Add constraint: SOC[start]=50, initial SOC
m.addConstr(Y[0]==initialsoc,name='c1')
#Final targeted SOC
m.addConstr(Y[n]>=65,name='c2')
m.addConstrs((Y[i+1]-Y[i] == 3.75*x[i] for i in range(n)), name='c0')
#Objective function. 6 comes from capacity of inverter.
obj1=sum(((load[i+1]-(6*x[i]))*(load[i+1]-(6*x[i])) for i in range (n)))
m.setObjective(obj1,GRB.MINIMIZE)
m.optimize()
My x constraint can only have -1 or 0 or 1 values. The other constraint is Y where at each step y(i+1)-y(i) equals to 3.75*X(i).
Is it possible to convert this code to Scipy? Or do you recommend any other libraries?

How can I use a CVX variable in a Numpy product that is to be Minimized?

I'm trying to optimize a configuration X (boolean), such that the total price : base_price + discount, on a configuration is minimized, but the problem formulation gives a Matmul error since x is a cvxpy Variable and thus doesn't conform to the Numpy shape even though it was defined with the correct length.
n = len(Configuration)
x = cp.Variable(n, boolean=True)
problem = cp.Problem(cp.Minimize(base_price + price#(price_rules_A#x <= price_rules_B)), [
config_rules_A#x <= config_rules_B,
config_rules_2A#x == config_rules_2B
])
# where price#(price_rules_A#x <= price_rules_B) is the total discount
# and price, price_rules_A and price_rules_B are numpy arrays
The error i get is
ValueError: matmul: Input operand 1 does not have enough dimensions (has 0, gufunc core with signature (n?,k),(k,m?)->(n?,m?) requires 1)
I expect it to find an optimal config for x ( 0010110...) such that the discount is minimized but it doesn't. Any idea what might be causing this?
Assuming the evaluation of the inequality in the objective function is suppose to work as index to price, you can rewrite the function as
cp.Minimize(base_price + price#(1-(price_rules_B - price_rules_A#x))
Then the elements in price where the inequality is true will be summed.