In Julia when I do:
model = Model();
set_optimizer(model, Cbc.Optimizer);
N=11;
model = Model();
set_optimizer(model, Cbc.Optimizer);
#variable(model, X[1:N,1:N,1:N], Bin);
#variable(model, 1<=K<=10, Int);
for k in K
#constraint(model, (sum(X[1,j,k] for j= 1:N)) ==1 )
end
I get this error:
ArgumentError: invalid index: K of type VariableRef
Because I used a variable reference(k) as index for a vector (X).
How could I fix that?
If you want to K to interact with other variables you need to make it a binary vector with the sum of 1 and then use multiplication for modelling the interaction.
#variable(model, K[1:10], Bin);
#constraint(model, sum(K) == 1)
Now I am not exactly shure what you want to accomplish. If you want to turn off and on equations depending on the value of K this would look like this:
#constraint(model,con[k in 1:10], sum(X[1,j,k] for j= 1:N)*K[k] == K[k] )
This however makes the model non-linear and you would need to use a non-linear solver for it.
Depending on your use case having sums simply up to 1 could be enough (and this yields a model much easier for solvers but might your business needs or not):
#constraint(model,con[k in 1:10], sum(X[1,j,k] for j= 1:N) == K[k] )
Related
I would like to define a constraint in an optimization problem as follows:
(x,y) not in {(x,y)|1.0 < x < 2.0, 3.0 < y < 4.0}.
what I tried is #constraint(model, (1.0 < x < 2.0 + 3.0 < y < 4.0)!=2), but failed.
It seems that boolen operation is not allowed. such that I have no idea about it. Any advice is appreciated!
You should avoid introducing quadratic constraints (as in the other answer) and rather introduce binary variables. This increase number of available solvers and generally linear models take shorter time to solve.
Hence you should note that !(1.0 < x < 2.0) is an equivalent of x <= 1 || x >= 2 which can be written in a linear form as:
#variable(model, bx, Bin)
const M = 1000 # number "big enough"
#constraint(model, x <= 1 + M*bx)
#constraint(model, x >=2 - M*(1-bx))
bx is here a "switcher" variable that makes either first or second constraint obligatory.
I am not sure what you want about y as you have 3.0 < y < 3.0 but basically the pattern to formulate the would be the same.
Just note you cannot have a constraint such as y != 3 as solvers obviously have some numerical accuracy and you would need rather to represent this is as for an example !(3-0.01 < y < 3+0.01) (still using the same pattern as above)
UPDATE: The previous solution in this answer turned out to be wrong (exclude parts of the admissable region), and so I felt obligated to provide another 'right' solution. This solution partitions the admissable region into parts and solves different optimization problems for each part. Keeping the best solution. This is not a nice solution, but if one does not have a good solver (those commercial ones) it is one way. The commercial solvers usually go through a more efficient similar process by the name of branch-and-bound.
using JuMP, Ipopt
function solveopt()
bestobj = Inf
bestx, besty = 0.0,0.0
for (ltside, xvar, val) in (
(true, true, 2.0),(false, true, 3.0),
(true, false, 3.0),(false, false, 4.0))
m = Model(Ipopt.Optimizer)
#variable(m, x)
#variable(m, y)
add_constraint(m, ScalarConstraint(xvar ? x : y,
ltside ? MOI.LessThan(val) : MOI.GreaterThan(val)))
# following is an objective optimal inside the box
#NLobjective(m, Min, (x-2.5)^2+(y-3.5)^2)
optimize!(m)
if objective_value(m) < bestobj
bestx, besty = value(x), value(y)
end
end
return bestx, besty
end
The solution for this example problem is:
julia> solveopt()
:
: lots of solver output...
:
(2.5, 3.9999999625176965)
Lastly, I benchmarked this crude method against a non-commercial solver (Pajarito) with the method from other answer and this one is 2X faster (because of simplicity, I suppose). Commercial solvers would beat both times.
Using Julia's JuMP library, I have a matrix-valued variable A on which I would like to impose a 2-norm constraint (equivalently: the spectral / operator norm). However I am not sure how to do this. Below is a minimal-running code of something I would like to write
using LinearAlgebra
using JuMP
using MathOptInterface
using MosekTools
using Mosek
model = Model(optimizer_with_attributes(
Mosek.Optimizer,
"QUIET" => false,
"INTPNT_CO_TOL_DFEAS" => 1e-9
))
maxnorm = 3.0
# We want opnorm(A) <= maxnorm
#variable(model, A[1:4, 1:5])
# #SDconstraint(model, A' * A <= maxnorm^2) # Mathematically valid, but not accepted!
# Make dummy variable and constraint to satisfy
#variable(model, x)
#constraint(model, x >= 10)
#objective(model, Min, x)
optimize!(model)
A very overkill way to do this is via
#constraint(model, [maxnorm; vec(A)] in SecondOrderCone())
as this bounds the Frobenius norm instead --- but this is not preferable. I would greatly appreciate any insights into how this can be done.
MathOptInterface has a cone for the spectral norm:
https://jump.dev/MathOptInterface.jl/v0.9/apireference/#MathOptInterface.NormSpectralCone
#constraint(model, [maxnorm; vec(A)] in MOI.NormSpectralCone(4, 5))
I'm trying to maximize the portfolio return subject to 5 constraints:
1.- a certain level of portfolio risk
2.- the same above but oposite sign (I need that the risk to be exactly that number)
3.- the sum of weights have to be 1
4.- all the weights must be greater or equal to cero
5.- all the weights must be at most one
I'm using the optiSolve package because I didn't find any other package that allow me to write this problem (or al least that I understood how to use it).
I have three big problems here, the first is that the resulting weights vector sum more than 1 and the second problem is that I can't declare t(w) %*% varcov_matrix %*% w == 0 in the quadratic constraint because it only allows for "<=" and finally I don't know how to put a constraint to get only positives weights
vector_de_retornos <- rnorm(5)
matriz_de_varcov <- matrix(rnorm(25), ncol = 5)
library(optiSolve)
restriccion1 <- quadcon(Q = matriz_de_varcov, dir = "<=", val = 0.04237972)
restriccion1_neg <- quadcon(Q = -matriz_de_varcov, dir = "<=",
val = -mean(limite_inf, limite_sup))
restriccion2 <- lincon(t(vector_de_retornos),
d=rep(0, nrow(t(vector_de_retornos))),
dir=rep("==",nrow(t(vector_de_retornos))),
val = rep(1, nrow(t(vector_de_retornos))),
id=1:ncol(t(vector_de_retornos)),
name = nrow(t(vector_de_retornos)))
restriccion_nonnegativa <- lbcon(rep(0,length(vector_de_retornos)))
restriccion_positiva <- ubcon(rep(1,length(vector_de_retornos)))
funcion_lineal <- linfun(vector_de_retornos, name = "lin.fun")
funcion_obj <- cop(funcion_lineal, max = T, ub = restriccion_positiva,
lc = restriccion2, lb = restriccion_nonnegativa, restriccion1,
restriccion1_neg)
porfavor_funciona <- solvecop(funcion_obj, solver = "alabama")
> porfavor_funciona$x
1 2 3 4 5
-3.243313e-09 -4.709673e-09 9.741379e-01 3.689040e-01 -1.685290e-09
> sum(porfavor_funciona$x)
[1] 1.343042
Someone knows how to solve this maximization problem with all the constraints mentioned before or tell me what I'm doing wrong? I'll really appreciate that, because the result seems like is not taking into account the constraints. Thanks!
Your restriccion2 makes the weighted sum of x is 1, if you also want to ensure the regular sum of x is 1, you can modify the constraint as follows:
restriccion2 <- lincon(rbind(t(vector_de_retornos),
# make a second row of coefficients in the A matrix
t(rep(1,length(vector_de_retornos)))),
d=rep(0,2), # the scalar value for both constraints is 0
dir=rep('==',2), # the direction for both constraints is '=='
val=rep(1,2), # the rhs value for both constraints is 1
id=1:ncol(t(vector_de_retornos)), # the number of columns is the same as before
name= 1:2)
If you only want the regular sum to be 1 and not the weighted sum you can replace your first parameter in the lincon function as you've defined it to be t(rep(1,length(vector_de_retornos))) and that will just constrain the regular sum of x to be 1.
To make an inequality constraint using only inequalities you need the same constraint twice but with opposite signs on the coefficients and right hand side values between the two (for example: 2x <= 4 and -2x <= -4 combines to make the constraint 2*x == 4). In your edit above, you provide a different value to the val parameter so these two constraints won't combine to make the equality constraint unless they match except for opposite signs as below.
restriccion1_neg <- quadcon(Q = -matriz_de_varcov, dir = "<=", val = -0.04237972)
I'm not certain because I can't find precision information in the package documentation, but those "negative" values in the x vector are probably due to rounding. They are so small and are effectively 0 so I think the non-negativity constraint is functioning properly.
restriccion_nonnegativa <- lbcon(rep(0,length(vector_de_retornos)))
A constraint of the form
x'Qx = a
is non-convex. (More general: any nonlinear equality constraint is non-convex). Non-convex problems are much more difficult to solve than convex ones and require specialized, global solvers. For convex problems, there are quite a few solvers available. This is not the case for non-convex problems. Most portfolio models are formulated as convex QP (quadratic programming i.e. risk -- the quadratic term -- is in the objective) or convex QCP/SOCP problems (quadratic terms in the constraints, but in a convex fashion). So, the constraint
x'Qx <= a
is easy (convex), as long as Q is positive-semi definite. Rewriting x'Qx=a as
x'Qx <= a
-x'Qx <= -a
unfortunately does not make the non-convexity go away, as -Q is not PSD. If we are maximizing return, we usually only use x'Qx <= a to limit the risk and forget about the >= part. Even more popular is to put both the return and the risk in the objective (that is the standard mean-variable portfolio model).
A possible solver for solving non-convex quadratic problems under R is Gurobi.
I want to integrate a function involving while loop in R. I have pasted here an MWE. Could anyone please guide about how to get rid of warning messages when integrating such a function?
Thank You
myfun <- function(X, a, b, kmin, kmax){
term <- 0
k <- 1
while(k < kmax | term < 10000){
term <- term + a * b * X^k
k <- k+1
}
fx <- exp(X) * term
return(fx)
}
a <- 5
b <- 4
kmax <- 20
integrate(myfun, lower = 0, upper = 10, a = a, b = b, kmax = kmax)
Produces a warning, accessed via warnings():
In while (k < kmax | term < 10000) { ... :
the condition has length > 1 and only the first element will be used
From the integrate() documentation:
f must accept a vector of inputs and produce a vector of function evaluations at those points.
This is the crux of the problem here, which you can see by running myfun(c(1, 2), a, b, kmin, kmax) and reproducing a similar warning. What's happening is that integrate() wants to pass a vector of inputs to myfun in X; this means that inside your while loop, term will become a vector as well. This creates a problem when the while loop kicks back to the evaluation stage, because now the condition k < kmax | term < 10000 has a vector structure as well (since term does), which while doesn't like.
This warning is very good in this case, because it strongly suggests that integrate() isn't doing what you want it to do. Your goal here isn't to get rid of the warning messages; the function as written simply won't work with integrate() due to the while loop structure.
Your choices for how to proceed are to either (1) rewrite the function in a way that doesn't use a while loop, or (2) just hard-code some numeric integration yourself, perhaps with a for loop. The best way to use R is to vectorize everything and to avoid things like while and for when at all possible.
Finally, I'll note that there seems to be some problem with the underlying function, since myfun(0.5, a, b, kmin, kmax) does not converge (note the problem with the mathematics when the supplied X term is less than 1), so you won't be able to integrate it on the interval [0, 10] no matter what you do.
Below is a parasite growth model:
Ni(a, t) represents the expected number parasites of age a at time t, and ki(a, t) represents the killing effect, while PMF the multiplication factor. This is a discrete model as a equals 1, 2, 3.....48. Can anybody tell me how to implement this equation in R using difference equations? Many thanks for your support.
This is the best I could do with the information you provided. Point me to the rest of it and I might be able to get it to actually work, as stands I think it'll recur infinitely.
Ki <- function(a, t){ ## You need to actually define this properly
return(1)
}
Ni <- function(a, t, PMF){
if ((a %% 1 != 0)) stop("Only Takes Integer values of a")
if ((t %% 1 != 0)) stop("Only Takes Integer values of t")
if (a == 1){
x = Ni(48, t-1, PMF)
y = exp(-Ki(48,t-1))
result = PMF * x * y
return(result)
}
if (a > 1){
x = Ni(a-1, t-1, PMF)
y = exp(-Ki(a-1,t-1))
result = x * y
return(result)
}
}
You don't have a set of initial conditions. Once you've got some initial 48 values for N(a=1..48,t=1) you compute N(a=1,t=2) from the second equation, and then compute N(a=2..48,t=2) from the first equation. Repeat for t=3 and so on.
What you have is a recurrence relation, not a differential equation. You step through a recurrence relation as I've just explained.
It might be possible to convert this to a system of differential equations by looking at N(t)-N(t-1)/dt and solving but that's a maths job not a programming job.