I'm trying to optimize a function using NLopt.
I tried to use the example in NLopt.jl but I wasn't able to fix the error.
using JuMP
using NLopt
m = Model(solver=NLoptSolver(algorithm=:LD_MMA))
a1 = 2
b1 = 0
a2 = -1
b2 = 1
#variable(m, x1)
#variable(m, x2 >= 0)
#NLobjective(m, Min, sqrt(x2))
#NLconstraint(m, x2 >= (a1*x1+b1)^3)
#NLconstraint(m, x2 >= (a2*x1+b2)^3)
setvalue(x1, 1.234)
setvalue(x2, 5.678)
status = solve(m)
println("got ", getobjectivevalue(m), " at ", [getvalue(x1),getvalue(x2)])
I don't know how to use with_optimizer.
For those still looking, there is currently no solution to the problem.
Currently, JuMP uses the syntax
model = Model(optimizer)
set_optimizer_attribute(model, "attribue", value)
That would be the correct way to setting the "algorithm" = algorithm attribute for NLoptSolver.
However, the NLoptSolver package has not been updated to allow for loading the optimizer without the algorithm attribute, and so it is currently unable to use JuMP.
Source
Related
I am struggling with a probably minor problem while calling compiled ODEs to be solved
via the R package 'deSolve' and I seeking advice from more expert users.
Background
I have a couple of ODE systems to be solved with 'deSolve'. I have defined the ODEs in separate C++ functions (one for each model) I am calling through R in conjunction with 'Rcpp'. The initial values of the system change if the function takes input from another model (so basically to have a cascade).
This works quite nicely, however, for one model I have to set the initial parameters for t < 2. I've tried to do this in the C++ function, but it does not seem to work.
Running code example
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export("set_ODE")]]
SEXP set_ODE(double t, NumericVector state, NumericVector parameters) {
List dn(3);
double tau2 = parameters["tau2"];
double Ae2_4 = parameters["Ae2_4"];
double d2 = parameters["d2"];
double N2 = parameters["N2"];
double n2 = state["n2"];
double m4 = state["m4"];
double ne = state["ne"];
// change starting conditions for t < 2
if(t < 2) {
n2 = (n2 * m4) / N2;
m4 = n2;
ne = 0;
}
dn[0] = n2*d2 - ne*Ae2_4 - ne/tau2;
dn[1] = ne/tau2 - n2*d2;
dn[2] = -ne*Ae2_4;
return(Rcpp::List::create(dn));
}
/*** R
state <- c(ne = 10, n2 = 0, m4 = 0)
parameters <- c(N2 = 5e17, tau2 = 1e-8, Ae2_4 = 5e3, d2 = 0)
results <- deSolve::lsoda(
y = state,
times = 1:10,
func = set_ODE,
parms = parameters
)
print(results)
*/
The output reads (here only the first two rows):
time ne n2 m4
1 1 1.000000e+01 0.000000e+00 0.000000e+00
2 2 1.000000e+01 2.169236e-07 -1.084618e-11
Just in case: How to run this code example?
My example was tested using RStudio:
Copy the code into a file with the ending *.cpp
Click on the 'Source' button (or <shift> + <cmd> + <s>)
It should work also without RStudio present, but the packages 'Rcpp' and 'deSolve' must be installed and to compile the code it needs Rtools on Windows, GNU compilers on Linux and Xcode on macOS.
Problem
From my understanding, ne should be 0 for time = 1 (or t < 2). Unfortunately, the solver does not seem to consider what I have provided in the C++ function, except for the ODEs. If I change state in R to another value, however, it works. Somehow the if-condition I have defined in C++ is ignored, but I don't understand why and how I can calculate the initial values in C++ instead of R.
I was able to reproduce your code. It seems to me that this is indeed elegant, even if it does not leverage the full power of the solver. The reason is, that Rcpp creates an interface to the compiled model via an ordinary R function. So back-calls from the slovers (e.g. lsoda) to R are necessary in each time step. Such back-calls are not for the "plain" C/Fortran interface. Here communication between solver and model takes place at the machine code level.
With this informational, I can see that we don't need to expect initialization issues at the C/C++ level, but it looks like a typical case. As the model function is simply the derivative of the model (and only this). The integration is done by the solver "from outside". It calls the model always with the actual integration state, derived from the time step before (roughly speaking). Therefore, it is not possible to force the state variables to fixed values within the model function.
However, there are several options how to resolve this:
chaining of lsoda calls
use of events
The following shows a chained approach, but I am not yet sure about the initialization of the parameters in the first time segment, so may only be part of the solution.
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export("set_ODE")]]
SEXP set_ODE(double t, NumericVector state, NumericVector parameters) {
List dn(3);
double tau2 = parameters["tau2"];
double Ae2_4 = parameters["Ae2_4"];
double d2 = parameters["d2"];
double N2 = parameters["N2"];
double n2 = state["n2"];
double m4 = state["m4"];
double ne = state["ne"];
dn[0] = n2*d2 - ne*Ae2_4 - ne/tau2;
dn[1] = ne/tau2 - n2*d2;
dn[2] = -ne*Ae2_4;
return(Rcpp::List::create(dn));
}
/*** R
state <- c(ne = 10, n2 = 0, m4 = 0)
parameters <- c(N2 = 5e17, tau2 = 1e-8, Ae2_4 = 5e3, d2 = 0)
## the following is not yet clear to me !!!
## especially as it is essentially zero
y1 <- c(ne = 0,
n2 = unname(state["n2"] * state["m4"]/parameters["N2"]),
m4 = unname(state["n2"]))
results1 <- deSolve::lsoda(
y = y,
times = 1:2,
func = set_ODE,
parms = parameters
)
## last time step, except "time" column
y2 <- results1[nrow(results1), -1]
results2 <- deSolve::lsoda(
y = y2,
times = 2:10,
func = set_ODE,
parms = parameters
)
## omit 1st time step in results2
results <- rbind(results1, results2[-1, ])
print(results)
*/
The code has also another potential problem as the parameters span several magnitudes from 1e-8 to 1e17. This can lead to numerical issues, as the relative precision of most software, including R covers only 16 orders of magnitude. Can this be the reason, why the results are all zero? Here it may help to re-scale the model.
While solving a differential equation on satellite motion encountered this error:
dt <= dtmin. Aborting. If you would like to force continuation with dt=dtmin, set force_dtmin=true
Here is my code:
using JPLEphemeris
spk = SPK("some-path/de430.bsp")
jd = Dates.datetime2julian(DateTime(some-date))#date of the calculatinons
yyyy/mm/dd hh/mm/ss
jd2 = Dates.datetime2julian(DateTime(some-date))#date of the calculatinons
yyyy/mm/dd hh/mm/ss
println(jd)
println(jd2)
st_bar_sun = state(spk, 0, 10, jd)
st_bar_moon_earth = state(spk, 0, 3, jd)
st_bar_me_earth = state(spk, 3, 399, jd)
st_bar_me_moon = state(spk, 3, 301, jd)
moon_cord = st_bar_me_moon - st_bar_me_earth
a = st_bar_moon_earth + st_bar_me_earth
sun_cord = st_bar_sun - a
println(sputnik_cord)
sputnik_cord = [8.0,8.0,8.0,8.0,8.0,8.0,8.0]
moon_sputnik = sputnik_cord - moon_cord
sun_sputnic = sputnik_cord - sun_cord
Req = 6378137
J2 = 1.08262668E-3
GMe = 398600.4418E+9
GMm = 4.903E+12
GMs = 1.32712440018E+20
function f(dy,y,p,t)
re2=(y[1]^2 + y[2]^2 + y[3]^2)
re3=re2^(3/2)
rs3 = ((y[1]-sun_cord[1])^2 + (y[2]-sun_cord[2])^2 + (y[3]-sun_cord[3])^2)^(3/2)
rm3 = ((y[1]-moon_cord[1])^2 + (y[2]-moon_cord[2])^2 + (y[3]-moon_cord[3])^2)^(3/2)
w = 1 + 1.5J2*(Req*Req/re2)*(1 - 5y[3]*y[3]/re2)
w2 = 1 + 1.5J2*(Req*Req/re2)*(3 - 5y[3]*y[3]/re2)
dy[1] = y[4]
dy[2] = y[5]
dy[3] = y[6]
dy[4] = -GMe*y[1]*w/re3
dy[5] = -GMe*y[2]*w/re3
dy[6] = -GMe*y[3]*w2/re3
end
function f2(dy,y,p,t)
re2=(y[1]^2 + y[2]^2 + y[3]^2)
re3=re2^(3/2)
rs3 = ((y[1]-sun_cord[1])^2 + (y[2]-sun_cord[2])^2 + (y[3]-sun_cord[3])^2)^(3/2)
rm3 = ((y[1]-moon_cord[1])^2 + (y[2]-moon_cord[2])^2 + (y[3]-moon_cord[3])^2)^(3/2)
w = 1 + 1.5J2*(Req*Req/re2)*(1 - 5y[3]*y[3]/re2)
w2 = 1 + 1.5J2*(Req*Req/re2)*(3 - 5y[3]*y[3]/re2)
dy[1] = y[4]
dy[2] = y[5]
dy[3] = y[6]
dy[4] = -GMe*y[1]*w/re3 - GMm*y[1]/rm3 - GMs*y[1]/rs3
dy[5] = -GMe*y[2]*w/re3 - GMm*y[2]/rm3 - GMs*y[2]/rs3
dy[6] = -GMe*y[3]*w2/re3- GMm*y[3]/rm3 - GMs*y[3]/rs3
end
y0 = sputnik_cord
jd=jd*86400
jd2=jd2*86400
using DifferentialEquations
prob = ODEProblem(f,y0,(jd,jd2))
sol = solve(prob,DP5(),abstol=1e-13,reltol=1e-13)
prob2 = ODEProblem(f2,y0,(jd,jd2))
sol2 = solve(prob2,DP5(),abstol=1e-13,reltol=1e-13)
println("Without SUN and MOON")
println(sol[end])
for i = (1:6)
println(sputnik_cord[i]-sol[end][i])
end
println("With SUN and MOON")
println(sol2[end])
What(except the values) can be a reason of this? It worked well before I added the terms with sun_coords and moon_coords in definition of dy[4], dy[5], dy[6] in function f2(As I suppose the function f1 works correctly).
There are two reasons this could be happening. For one, you could see this error because the model is unstable due to implementation issues. If you accidentally put something in wrong, the solution may be diverging to infinity and as it diverges the time steps shorten and it exists with this error.
Another thing that can happen is that your model might be stiff. This can happen if you have large time scale differences between different components. In that case, DP5(), an explicit Runge-Kutta method, is not an appropriate algorithm for this problem. Instead, you will want to look at something for stiff equations. I would recommend giving Rosenbrock23() a try: it's not the fastest but it's super stable and if the problem is integrable it'll handle it.
That's a very good way to diagnose these issues: try other integrators. Try Rosenbrock23(), CVODE_BDF(), radau(), dopri5(), Vern9(), etc. If none of these are working, then you will have just tested your algorithm with a mixture of the most well-tested algorithms (some of them Julia implementations, but others are just wrappers to standard classic C++ and Fortran methods) and this suggests that the issue is in your model formulation and not a peculiarity of a specific solver on this problem. Since I cannot run your example (you should make your example runnable, i.e. no extra files required, if you want me to test things out), I cannot be sure that your model implementation is correct and this would be a good way to find out.
My guess is that the model you have written down is not a good implementation because of floating point issues.
GMe = 398600.4418E+9
GMm = 4.903E+12
GMs = 1.32712440018E+20
these values have only precision 16 digits less than their prescribed value:
> eps(1.32712440018E+20)
16384.0
> 1.32712440018E+20 + 16383
1.3271244001800002e20
> 1.32712440018E+20 + 16380
1.3271244001800002e20
> 1.32712440018E+20 + 16000
1.3271244001800002e20
Notice the lack of precision below the machine epsilon for this value. Well, you're asking for
sol = solve(prob,DP5(),abstol=1e-13,reltol=1e-13)
precision to 1e-13 when it's difficult to be precise to 1e5 given the size of your constants. You need to adjust your units or utilize BigFloat numbers if you want this kind of precision on this problem. So what's likely going on is that the differential equation solvers are realizing that they are not hitting 1e-13 precision, shrinking the stepsize, and repeating this indefinitely (because they can never hit 1e-13 precision due to the size of the floating point numbers) until the stepsize is too small and it exits. If you change the units so that way the constants are more reasonable in size then you can fix this problem.
I'm attempting to code the method described here to estimate production functions of metal manufacturers. I've done this in Python and Matlab, but am trying to learn Julia.
spain_clean.csv is a dataset of log capital (lnk), log labor (lnl), log output (lnva), and log materials (lnm) that I am loading. Lagged variables are denoted with an "l" before them.
Code is at the bottom. I am getting an error:
ERROR: LoadError: MethodError: no method matching parseNLExpr_runtime(::JuMP.Model, ::JuMP.GenericQuadExpr{Float64,JuMP.Variable}, ::Array{ReverseDiffSparse.NodeData,1}, ::Int32, ::Array{Float64,1})
I think it has to do with the use of vector sums and arrays going into the non-linear objective, but I do not understand Julia enough to debug this.
using JuMP # Need to say it whenever we use JuMP
using Clp, Ipopt # Loading the GLPK module for using its solver
using CSV # csv reader
# read data
df = CSV.read("spain_clean.csv")
#MODEL CONSTRUCTION
#--------------------
acf = Model(solver=IpoptSolver())
#variable(acf, -10<= b0 <= 10) #
#variable(acf, -5 <= bk <= 5 ) #
#variable(acf, -5 <= bl <= 5 ) #
#variable(acf, -10<= g1 <= 10) #
const g = sum(df[:phihat]-b0-bk* df[:lnk]-bl* df[:lnl]-g1* (df[:lphihat]-b0-bk* df[:llnk]-bl* df[:llnl]))
const gllnk = sum((df[:phihat]-b0-bk* df[:lnk]-bl* df[:lnl]-g1* (df[:lphihat]-b0-bk* df[:llnk]-bl* df[:llnl])).*df[:llnk])
const gllnl = sum((df[:phihat]-b0-bk* df[:lnk]-bl* df[:lnl]-g1* (df[:lphihat]-b0-bk* df[:llnk]-bl* df[:llnl])).*df[:llnl])
const glphihat = sum((df[:phihat]-b0-bk* df[:lnk]-bl* df[:lnl]-g1* (df[:lphihat]-b0-bk* df[:llnk]-bl* df[:llnl])).*df[:lphihat])
#OBJECTIVE
#NLobjective(acf, Min, g* g + gllnk* gllnk + gllnl* gllnk + glphihat* glphihat)
#SOLVE IT
status = solve(acf) # solves the model
println("Objective value: ", getobjectivevalue(acf)) # getObjectiveValue(model_name) gives the optimum objective value
println("b0 = ", getvalue(b0))
println("bk = ", getvalue(bk))
println("bl = ", getvalue(bl))
println("g1 = ", getvalue(g1))
No an expert in Julia, but I think a couple of things are wrong about your code.
first, constant are not supposed to change during iteration and you are making them functions of control variables. Second, what you want to use there are nonlinear expression instead of constants. so instead of the constants what you want to write is
N = size(df, 1)
#NLexpression(acf, g, sum(df[i, :phihat]-b0-bk* df[i, :lnk]-bl* df[i, :lnl]-g1* (df[i, :lphihat]-b0-bk* df[i, :llnk]-bl* df[i, :llnl]) for i=1:N))
#NLexpression(acf, gllnk, sum((df[i,:phihat]-b0-bk* df[i,:lnk]-bl* df[i,:lnl]-g1* (df[i,:lphihat]-b0-bk* df[i,:llnk]-bl* df[i,:llnl]))*df[i,:llnk] for i=1:N))
#NLexpression(acf,gllnl,sum((df[i,:phihat]-b0-bk* df[i,:lnk]-bl* df[i,:lnl]-g1* (df[i,:lphihat]-b0-bk* df[i,:llnk]-bl* df[i,:llnl]))*df[i,:llnl] for i=1:N))
#NLexpression(acf,glphihat,sum((df[i,:phihat]-b0-bk* df[i,:lnk]-bl* df[i,:lnl]-g1* (df[i,:lphihat]-b0-bk* df[i,:llnk]-bl* df[i,:llnl]))*df[i,:lphihat] for i=1:N))
I tested this and it seems to work.
Is there a way to make certain functions such as isinteger() work with JuMPArrays?
I am using Julia/JuMP to solve an optimization problem, and after I get the solution, I want to check if the solution is integer. So here is what I wrote:
#defVar(m, 0<= x[1:3] <= 1)
...
xstar = getValue(x)
if isinteger(xstar)
...
end
And I get an error saying isinteger() has no method matching isinteger(::JuMPArray).
Thanks
So in general you can get an underlying array from a JuMPArray by using [:], e.g.
m = Model()
#variable(m, 0 <= x[1:3] <= 1)
#variable(m, 0 <= y[1:10, 1:10] <= 1)
solve(m)
xstar = getvalue(x)[:]
ystar = getvalue(y)[:,:]
Note that the reason for this is that JuMPArrays don't have to start with index 1, so the user needs to explicitly say they want a normal Julia array before doing things.
Regardless, you shouldn't use isinteger. Solvers don't always return very precise answers, e.g. they might say x[1] = 0.999996 but they really mean it is 1. You should do something like
for i in 1:3
if getvalue(x[i]) >= 0.999
println("x[$i] is 1!")
elseif getvalue(x[i]) <= 0.001
println("x[$i] is 0!")
end
end
to make sure you don't get any false negatives. If the variable is restricted to be integer or binary, use iround, e.g.
for i in 1:3
v = iround(getvalue(x[i]))
if v == 1
println("x[$i] is 1!")
elseif v == 0
println("x[$i] is 0!")
end
end
but it looks like in this case you are just seeing if the solution is naturally 0 or 1.
I asked a question a few days ago here and got an answer that seems like it would work- it involves using linsolve to find the solutions to a system of equations that are all modulo p, where p is a non-prime integer.
However, when I try to run the commands from the provided answer, or the linsolve help page, I get an error saying linsolve doesn't support arguments of type 'sym'. Is using linsolve with sym variables only possible in R2013b? I've also tried it with my school's copy, which is R2012b. Here is the code I'm attempting to execute (from the answer at the above link):
A = [0 5 4 1;1 7 0 2;8 1 0 2;10 5 1 0];
b = [2946321;5851213;2563617;10670279];
s = mod(linsolve(sym(A),sym(b)),8)
And the output is:
??? Undefined function or method linsolve' for input arguments of type 'sym'.
I've also tried to use the function solve for this, however even if I construct the equations represented by the matrices A and b above, I'm having issues. Here's what I'm attempting:
syms x y z q;
solve(5*y + 4*z + q == 2946321, x + 7*y + 2*q == 5851213, 8*x + y + 2*q == 2563617, 10*x + 5*y + z == 10670279,x,y,z,q)
And the output is:
??? Error using ==> char
Conversion to char from logical is not possible.
Error in ==> solve>getEqns at 169
vc = char(v);
Error in ==> solve at 67
[eqns,vars] = getEqns(varargin{:});
Am I using solve wrong? Should I just try to execute my code in R2013b to use linsolve with symbolic data types?
The Symbolic Math toolbox math toolbox has changed a lot (for the better) over the years. You might not have sym/linsolve, but does this work?:
s = mod(sym(A)\sym(b),8)
That will basically do the same thing. sym/linsolve just does some extra input checking and and rank calculation to mirror the capabilities of linsolve.
You're using solve correctly for current versions, but it looks like R2010b may not understand the == operator (sym/eq) in this context. You can use the old string format to specify your equations:
eqs = {'5*y + 4*z + q = 2946321',...
'x + 7*y + 2*q = 5851213',...
'8*x + y + 2*q = 2563617',...
'10*x + 5*y + z = 10670279'};
vars = {'x','y','z','q'};
[x,y,z,q] = solve(eqs{:},vars{:})