I'm trying to solve a model using Julia-JuMP. The following is the outline of the model that I created. Here, z[i,j] is a binary variable and d[i,j] is the cost for which z[i,j]=1.
My constraint creates an infinite number of constraint and hence I need to use a separation algorithm to solve it.
First, I solve the model without any constraint, so the answer to all variables z[i,j] and d[i,j] are zero.
Then, I'm including the separation algorithm (which is given inside the if condition). Even though I'm including if z_value == 0, z_values are not passing to it.
Am I missing something in the format of this model?
m = Model(solver=GurobiSolver())
#variable(m, z[N,N], Bin)
#variable(m, d[N,N]>=0)
#objective(m, Min, sum{ d[i,j]*z[i,j], i in N, j in N} )
z_value = getvalue(z)
d_value = getvalue(d)
if z_value == 0
statement
elseif z_value == 1
statement
end
#constraint(m, sum{z[i,j], i in N, j in N}>=2)
solve(m)
println("Final solution: [ $(getvalue(z)), $(getvalue(d)) ]")
You're multiplying z by d which both are variables, hence your model is non-linear,
Are the costs d[i,j] constant or really a variable of the problem ?
If so you need to use a non-linear solver
Related
Hello fellows, i am learning Julia and integer programing but i am stuck at one point
How to model "then" in julia-jump for integer programing leanring.
Stuck here here
#Define the variables of the model
#variable(mo, x[1:N,1:S], Bin)
#variable(mo, a[1:S]>=0)
#Assignment constraint
#constraint(mo, [i=1:N], sum(x[i,j] for j=1:S) == 1)
##constraint (mo, PLEASE HELP )
In cases like this you usually need to use Big-M constraints
So this will be:
a_ij >= s_i^2 - M*(1-x_ij)
where M is a "big enough" number. This means that if x_ij == 0 the inequality will always be true (and hence kind of turned-off). On the other hand when x_ij == 1 the M-part will be zeroed and the equation will hold.
In JuMP terms the code will look like this:
const M = 10_000
#constraint(mo, [i=1:N, j=1:S], a[i, j] >= s[i]^2 - M*(1 - x[i, j]))
However, if s[i] is an external parameter rather than model variable you could simply use x[i,j] <= a[j]/s[i]^2 proposed by #DanGetz. However when s[i] is #variable you really want to avoid dividing or multiplying variables by each other. So this big M approach is more general across use cases.
I'd like to write a LP problem in the standard format with MatOptInterface, e.i.:
min c'*x
S.t A*x .== b
x >= 0
Now, how can one write this problem with MathOptInterface? I'm having many issues, one of them is how to define the variable "model". For example, if I try to run:
x = add_variables(model,3)
I first would need to declare this model variable. But I don't know how one is supposed to do this on MathOptInterface.
IIUC in your situation model has to be an argument to be specified by the user of your function.
The user can then pass GLPK.Optimizer(), Tulip.Optimizer() or any other optimizer inheriting from MathOptInterface.AbstractOptimizer.
See e.g. Manual#A complete example.
Alternatively you can look at MOI.Utilities.Model but I don't know how to get an optimizer to solve that model.
Here is how to implement the LP solver for standard Simplex format:
function SolveLP(c,A,b,model::MOI.ModelLike)
x = MOI.add_variables(model, length(c));
MOI.set(model, MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(c, x), 0.0))
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
for xi in x
MOI.add_constraint(model, MOI.SingleVariable(xi), MOI.GreaterThan(0.0))
end
for (i,row) in enumerate(eachrow(A))
row_function = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(row, x), 0.0);
MOI.add_constraint(model, row_function, MOI.EqualTo(b[i]))
end
MOI.optimize!(model)
p = MOI.get(model, MOI.VariablePrimal(), x);
return p
end
For the model, just choose something like GLPK.Optimizer()
I am working on a supply chain optimisation problem using Pyomo and I need to set up a constraint on specific variables in the model. The constraint is that the variable should be within the set (0,1) or (200, to infinity). However, when I try to set up that constraint I am getting a TypeError, here is my code:
def rail_rule(model):
for route in routes:
if "rail" in route[0].lower():
dest = route[0]
dg = route[1]
sg = route[2]
site = route[3]
return model.x[dest, dg, sg, site]>=200 or model.x[dest, dg, sg, site]<=1
model.railconst = Constraint(rule = rail_rule)
I get this error when I run it :
TypeError: Relational expression used in an unexpected Boolean context.
The inequality expression:
200.0 <= x[RAIL - KENSINGTON,8,8,BROCKLESBY]
contains non-constant terms (variables) that were evaluated in an
unexpected Boolean context at
File '<ipython-input-168-901363ebc86f>', line 8:
return model.x[dest, dg, sg, site]>=200 or model.x[dest, dg, sg, site]<=1
Evaluating Pyomo variables in a Boolean context, e.g.
if expression <= 5:
is generally invalid. If you want to obtain the Boolean value of the
expression based on the current variable values, explicitly evaluate the
expression using the value() function:
if value(expression) <= 5:
or
if value(expression <= 5):
So my understanding is that I cant give Pyomo a boolean expression as a constraint, but I am quite new to Pyomo and not too sure if that's what my issue is or if I am doing it correctly.
This constraint could also be implemented in the variable intialisation as boundaries, but I cant find a way to set up two boundaries on a single variable in Pyomo.
Thanks !
There are different ways to handle this:
(1) Use binary variables. Assume you have a good upper bound on x, i.e., x ∈ [0, U]. Then formulate the constraints
x ≤ 1 + (U-1) δ
x ≥ 200 δ
δ ∈ {0,1} (binary variable)
This is the easiest way.
(2) If you don't have a good upper bound on x, you can use a SOS1 set. (SOS1 means Special Ordered Set of type 1). Assume x,s1,s2 ≥ 0.
x ≤ 1 + s1
x ≥ 200 - s2
s1,s2 ∈ SOS1 (s1,s2 form a SOS1 set)
(3) Use disjunctive programming.
I'm using Julia with JuMP and Gurobi to solve an optimisation problem.
Two of my constraints have "if/else" like properties. I need values to be less than the sum of to real numbers but if the real number is larger than one I need it to be equal to one.
I made a function which returns the sum if they are smaller than one and the sum if they are not. I did a similar solution to my other constraint.
#constraint(m, [l in Locations, i in Locations, r in Rotor_size, wd in WD],
wake_rot[l, wd, r] <= isone(wake_loc, wd, l, i, r))
with isone is
function isone(wake_loc, wd, l, i, r)
a = wake_loc[wd, l, i] + Adj_wake[r]
if a > 1
return 1
else
return a
end
end
My model is unbounded(or infeasible) and I'm wondering if this can be the the source to my problems.
I’m using MathProg (a language specific to the GLPK library, resembling a subset of AMPL) to find topological ranking of vertices of a graph. It’s an assignment for my linear programming class. It’s an introductory exercise to make sure we can formulate a simple linear program and solve it using GLPK.
I’ve written a Perl script that generates the linear program in MathProg for a given graph. It prints values of the variables (ranks of vertices) via printf. If it’s feasible, that’s exactly what I want; otherwise it prints all zeros, but I want to print just Infeasible, has cycles or loops..
I managed to do it in a hacky way (see below). How to do it more elegantly, without repeating the condition for feasibility? Is there a way to detect infeasibility that does not depend on the problem being solved?
param Vsize := 3;
set V "Vertices" := (0..Vsize-1);
set E "Edges" within V cross V := {(0, 1), (1, 2), (2, 0)};
var v{i in V} >= 0;
minimize rank_total: sum{i in V} v[i];
edge{(i, j) in E}: v[j] - v[i] >= 1;
solve;
printf "#OUTPUT:\n";
printf (if ((exists{i in V} v[i] >= 1) or card(E) = 0) then "" else "Infeasible, has cycles or loops.\n");
printf{i in V} (if ((exists{j in V} v[j] >= 1) or card(E) = 0) then "v_%d: %d\n" else ""), i, v[i];
printf "#OUTPUT END\n";
end;
I tried to declare param Feasible binary := (exists{i in V} v[i] >= 1) or card(E) = 0; but GLPK refused it with Model processing error. When I declared it before solve, it said operand preceding >= has invalid type, when after, it said expression following := has invalid type. I was seeking something like a variable in common programming languages.
In AMPL you can check the built-in parameter solve_result to see if the problem is infeasible:
if solve_result = 'infeasible' then
print 'Infeasible, has cycles or loops.';
However, I'm not sure if GLPK supports this parameter in which case you might need to check for feasibility manually.
As for the error, since exists is a logical expression you can't use it as a numeric one. The fix is to simply put logical expression in if:
param Feasible binary :=
if (exists{i in V} v[i].val >= 1) or card(E) = 0 then 1;