Nonlinearly constrained maximization problem using MathProgBase in Julia - julia

The objective function is f(x,y)=sqrt(x^2+2*y^2-xy), subject to 10 > x > 0, 10 > y > 0, x > y. I am going to find the x and y which maximize objective function. I am required to use Nonlinear models in MathProgBase.jl packages. The tutorial from https://mathprogbasejl.readthedocs.io/en/latest/nlp.html is difficult for me to follow since I am a beginner. I really appreciate your help!

It seems that JuMP doesn't support strictly greater/lower constraints (as result that most solver engines doesn't either).
A modellisation in Julia of your problem would be:
using JuMP, Ipopt
m = Model(with_optimizer(Ipopt.Optimizer, print_level=0))
#variable(m, 0 <= x <= 10, start=1)
#variable(m, 0 <= y <= 10, start=1)
#constraint(m, c1, y <= x )
#NLobjective(m, Max, sqrt(x^2+2*y^2-x*y))
optimize!(m)
status = termination_status(m)
if (status == MOI.OPTIMAL || status == MOI.LOCALLY_SOLVED || status == MOI.TIME_LIMIT) && has_values(m)
if (status == MOI.OPTIMAL)
println("** Problem solved correctly **")
else
println("** Problem returned a (possibly suboptimal) solution **")
end
println("- Objective value : ", objective_value(m))
println("- Optimal solutions:")
println("x: $(value.(x))")
println("y: $(value.(y))")
else
println("The model was not solved correctly.")
println(status)
end
(see https://lobianco.org/antonello/personal/blog/2017/0203_jump_for_gams_users for an explanation of the various steps)
That results of the script is:
** Problem returned a (possibly suboptimal) solution **
- Objective value : 14.14213575988668
- Optimal solutions:
x: 10.0
y: 10.0

Related

Julia JuMP feasibility slack of constraints

In Julia, by using JuMP am setting up a simple optimization problem (MWE, the real problem is much bigger).
model = Model()
set_optimizer(model, MosekTools.Optimizer)
#variable(model, 0 <= x[1:2])
#constraint(model, sum(x) <= 2)
#constraint(model, 1 <= sum(x))
#objective(model, Min, sum(x))
print(model)
Which gives this model:
Min x[1] + x[2]
Subject to
x[1] + x[2] ≤ 2.0
-x[1] - x[2] ≤ -1.0
x[1] ≥ 0.0
x[2] ≥ 0.0
I optimize this model via optimize!(model).
Now, obviously, the constraint x[1] + x[2] <= 2 is redundant and it has a feasibility slack of "3". My goal is to determine all the constraints that have slacks larger than 0 and display the slacks. Then I will delete those from the model.
To this end, I iterate over the constraints which are not variable bounds and print their values.
for (F, S) in list_of_constraint_types(model)
# Iterate over constraint types
if F!= JuMP.VariableRef #for constraints that
for ci in all_constraints(model, F, S)
println(value(ci))
end
end
end
However, because I print the value of the constraints, I get the left-hand sides:
1.0
-1.0
I want to instead see the slacks as
0
3
How may I do this? Note that I am not necessarily interested in linear programs, so things like shadow_value is not useful for me.
Based on the accepted answer, I am adding a MWE that solves this problem.
model = Model()
set_optimizer(model, MosekTools.Optimizer)
#variable(model, 0 <= x[1:2])
#constraint(model, sum(x) <= 2)
#constraint(model, 1 <= sum(x))
#constraint(model, 0.9 <= sum(x))
#objective(model, Min, sum(x))
print(model)
optimize!(model)
constraints_to_delete = vec([])
for (F, S) in list_of_constraint_types(model)
if F!= JuMP.VariableRef
for ci in all_constraints(model, F, S)
slack = normalized_rhs(ci) - value(ci)
if slack > 10^-5
push!(constraints_to_delete, ci)
println(slack)
#delete(model, ci)
end
end
end
end
for c in constraints_to_delete
delete(model, c)
end
print(model)
Read this (hot off the press) tutorial: https://jump.dev/JuMP.jl/dev/tutorials/linear/lp_sensitivity/.
Although focused on LPs, it shows how to compute slacks etc using normalized_rhs(ci) - value(ci).

Checking for a counterexample to a conjecture on even deficient-perfect numbers using Pari-GP

I am trying to check for counterexamples to the conjecture stated in this MSE question, using the Pari-GP interpreter of Sage Cell Server.
I reproduce the statement of the conjecture here: If N > 8 is an even deficient-perfect number and Q = N/(2N - sigma(N)), then Q is prime.
Here, sigma(N) is the classical sum of divisors of N.
I am using the following code:
for(x=9, 1000, if(((Mod(x,(2*x - sigma(x))) == 0)) && ((fromdigits(Vecrev(digits(x / (2*x - sigma(x)))))) == (x / (2*x - sigma(x)))) && !(isprime((x / (2*x - sigma(x))))), print(x,factor(x))))
However, the Pari-GP interpreter of Sage Cell Server would not accept it, and instead gives the following error message:
*** at top-level: for(x=9,1000,if(((Mod(x,(2*x-sigma(x)))==0))&&
*** ^----------------------------
*** Mod: impossible inverse in %: 0.
What am I doing wrong?
Here's a better implementation of your algorithm
{
forfactored(X = 9, 10^7,
my (s = sigma(X), t = 2*X[1] - s);
if (t <= 0, next);
my ([q, r] = divrem(X[1], t));
if (r == 0 && fromdigits(Vecrev(digits(q))) == q && !ispseudoprime(q),
print(X)))
}
It's a bit more readable but most importantly it avoids factoring the same x over and over again: each time you write sigma(x), we need to factor x (the interpreter is not clever enough to compute subexpressions once). In fact, it doesn't perform a single factorization, through the use of forfactored which performs a sieve instead (and the variable X contains [x, factor(x)]). This is about 3 times faster than the original implementation in this range.
I let it run to 10^9 (about 10 minutes), there was no further counterexample.
I got it to work myself.
Here is the code that I used:
for(x=9, 10000000, if((2*x > sigma(x)) && ((Mod(x,(2*x - sigma(x))) == 0)) && ((fromdigits(Vecrev(digits(x / (2*x - sigma(x)))))) == (x / (2*x - sigma(x)))) && !(isprime((x / (2*x - sigma(x))))), print(x,factor(x))))
The search returns the odd counterexample N = 9018009, which is expected.
It did not return any even counterexamples, in the specified range.

Julia: How to introduce binary integers for mixed integers optimization problems with JuMP?

Problem description
I am trying to do a mixed-integer optimization for a "Unit Commitment" problem in Julia with Jump. But JuMP expects my introduction of the unit activation variable, x[1:N], to be a number and not a variable. However, the unit activation is a binary integer decision variable for the optimization problem so I have trouble including the variable into the optimization problem.
What am I doing wrong?
My approaches have been:
Approach 1: Include x[1:N] as part of #variable macro for P_G.
m = Model(Cbc.Optimizer) # Model
#variable(m, x[1:N], Bin) # Unit activation
#variable(m, P_C[i,1]*x[i] <= P_G[i=1:N,1:T] <= P_C[i,2]*x[i]) # Unit generation limit
for i in 1:T # Load balance
#constraint(m, sum(P_G[:,i]) == P_D[i])
end
#objective(m,Min,sum(P_G[:,1:T].*F[1:N]*x[1:N])) # Objective function
optimize!(m) # Solve
This leads to the following error:
LoadError: InexactError: convert(Float64, 50 x[1]).
Approach 2: Define the feasible region for P_G as a constraint including x[1:N]:
m = Model(Cbc.Optimizer) # Model
#variable(m, x[1:N]) # Unit activation
#variable(m, P_G[i=1:N,1:T] ) # Unit generation limit
for i in 1:T # Load balance
#constraint(m, sum(P_G[:,i]) == P_D[i])
end
for i in 1:N # Unit generation limit
for j in 1:T
#constraint(m, P_C[i,1]*x[i] <= P_G[i,j] <= P_C[i,2]*x[i])
end
end
#objective(m,Min,sum(P_G[:,1:T].*F[1:N]*x[1:N])) # Objective function
optimize!(m) # Solve
This leads to: LoadError: [..] '#constraint(m, $(Expr(:escape, :(P_C[i, 1]))) * $(Expr(:escape, :(x[i]))) <= P_G[i, j] <= $(Expr(:escape, :(P_C[i, 2]))) * $(Expr(:escape, :(x[i]))))': Expected 50 x[1] to be a number.
NB: there might be more proper iteration methods but this should be idiot proof to Julia and JuMP newbies like me.
Working code without mixed-integer optimization
using JuMP, Cbc # Optimization and modelling
using Plots, LaTeXStrings # Plotting
# DATA
P_C = [50 200; # Power capacity [:, (min, max)]
25 200;
100 200;
120 500;
10 500;
20 500;
200 800;
200 800;
100 800;
200 1000;]
P_D = LinRange(sum(P_C[:,1]), sum(P_C[:,2]), 100) # Power demand
F = rand(100:500,10) # Random prod. prices
T = length(P_D) # Number of time steps
N = length(P_C[:,1]) # Number of generators
# MODEL
m = Model(Cbc.Optimizer) # Model
#variable(m, x[1:N], Bin) # Unit activation
#variable(m, P_C[i,1] <= P_G[i=1:N,1:T] <= P_C[i,2]) # Unit generation limit
for i in 1:T # Load balance
#constraint(m, sum(P_G[:,i]) == P_D[i])
end
#objective(m,Min,sum(P_G[:,1:T].*F[1:N])) # Objective function
optimize!(m) # Solve
# PLOT
plt = plot(P_D[:],value.(P_G[:,1:T])', xlab = L"P_{load} [MW]", ylab = L"P_{unit} [MW]")
#show plt
Which should produce something similar:
The expected outcome of introducing the unit activation variable would be that each unit is not required to generate power in the the lower region of the P_load.
Preliminary
I have introduced the basics of the problem with success:
Objective function: Minimize the cost of power generation
Variable, P_G: for power generation (feasible region defined by min and max capacity, P_C)
Production cost, F (as constant only!)
Power demand, P_D, is set to be a linear space from the min power cap. to the max cap.
Mathematically expressed:
Variable bounds cannot include other variables. Do:
m = Model(Cbc.Optimizer)
#variable(m, x[1:N], Bin)
#variable(m, P_G[i=1:N,1:T])
#constraint(m, [i=1:N, t=1:T], P_C[i, 1] * x[i] <= P_G[i, t])
#constraint(m, [i=1:N, t=1:T], P_G[i, t] <= P_C[I, 2] * x[i])

How can I change the code so it can solve the model?

It is not possible for Julia to solve it when I use a[i, j] = 1. how can i get julia to solve this problem?
using JuMP
using GLPK
u = [1 2 3 ; 1 2 3 ; 1 2 3]
m = Model(GLPK.Optimizer)
#variable(m, a[1:3,1:3], Bin)
#objective(m, Max, sum(u[i,j]*a[i,j] for i=1:3, j=1:3))
#constraint(m, [a[i,j]=1], sum(a[i:j][i:j]) == 1)
solution = optimize!(m)
opt_value = value.(a)
in the line
#constraint(m, [a[i,j]=1], sum(a[i:j][i:j]) == 1)
1) You're trying to set a variable, not to test equality, instead use
a[i,j] == 1
2) i and j are undefined. Without a minimal example to run, I would say according to the previous line of your code, I would say something like
sum(<what-to-sum-here> for i=1:3, j=1:3)
Or loop on the list of index you want to use if not the proper one.

Minimize the maximum variable

I have a Mixed Integer Programming problem. The objective function is a minimization of the maximum variable value in the a vector. The variable is has an upper bound of 5. The problem is like this:
m = Model(solver = GLPKSolverMIP())
#objective(m, Min, max(x[i] for i=1:12))
#variable(m, 0 <= x[i] <= 5, Int)
#constraint(m, sum(x[i] for i=1:12) == 12)
status = solve(m)
The max variable is not part of the julia JuMP syntax. So I modified the problem to
t=1
while t<=5 && (status == :NotSolved || status == :Infeasible)
m = Model(solver = GLPKSolverMIP())
i = 1:12
#objective(m, Min, max(x[i] for i=1:12))
#variable(m, 0 <= x[i] <= t, Int)
#constraint(m, sum(x[i] for i=1:12) == 12)
status = solve(m)
t += 1
end
This solution does the job by solving the problem iterative for starting with a upper bound for the variable at 1 and then increase by one until the solutoin is feasible. Is this really the best way to do this?
The question wants to minimize a maximum, this maximum can be held in an auxiliary variable and then we will minimize it. To do so, add constraints to force the new variable to actually be an upper bound on x. In code it is:
using GLPKMathProgInterface
using JuMP
m = Model(solver = GLPKSolverMIP())
#variable(m, 0 <= x[i=1:3] <= 5, Int) # define variables
#variable(m, 0 <= t <= 12) # define auxiliary variable
#constraint(m, t .>= x) # constrain t to be the max
#constraint(m, sum(x[i] for i=1:3) == 12) # the meat of the constraints
#objective(m, Min, t) # we wish to minimize the max
status = solve(m)
Now we can inspect the solution:
julia> getValue(t)
4.0
julia> getValue(x)
3-element Array{Float64,1}:
4.0
4.0
4.0
The actual problem the poster wanted to solve is probably more complex that this, but it can be solved by a variation on this framework.

Resources