Converting non-linear optimization with fmincom from Matlab to Julia

Hi,
I’m new to Julia language and I’m trying to replicate an optimization function created in Matlab using fmincom in Julia in order to improve the computation time that is quite huge in Matlab.
I’ve used the JuMP modeling language with the Ipopt solver to specify and optimize my model but i always get the error message: EXIT: Converged to a point of local infeasibility. Problem may be infeasible.
This is my objective function:

function Jfun(k::T...) where {T<:Real}
    k0=optimization_data["k0"];
    a=optimization_data["a"];
    b=optimization_data["b"];
    s_sweep=optimization_data["sweep"];
    k1=T[k0];
    
    for item in k
        push!(k1,item);
    end
    
    ds=[s_sweep[i+1]-s_sweep[i] for i in range(start=1,stop=length(s_sweep)-1)];
    ah=[0.5*(a[i+1]+a[i]) for i in range(start=1,stop=length(a)-1)];
    bh=[0.5*(b[i+1]+b[i]) for i in range(start=1,stop=length(b)-1)];
    kh=[0.5*(k1[i+1]+k1[i]) for i in range(start=1,stop=length(k1)-1)];
    f_temp=[k1[i+1]-k1[i] for i in range(start=1,stop=length(k1)-1)];
    
    f=[]
    for i in range(start=1,stop=length(f_temp))
        push!(f,f_temp[i]/ds[i]+ah[i]*kh[i]+bh[i]);
    end
    
    Jval=0;
    for i in range(start=1,stop=length(f))
        Jval+=(f[i]^2)*ds[i];
    end
    return Jval
end

This is the main of the application:

model = Model((Ipopt.Optimizer));
@variable(model,k[i=1:length(k0guess)],upper_bound=upper_bounds[i+1],lower_bound=lower_bounds[i+1],start=k0guess[i])
register(model,:Jfun,length(k0guess),Jfun;autodiff=true)
# Objective function
@NLobjective(model, Min, Jfun(k...))
register(model,:timeConstrain,length(k0guess),timeConstrain,autodiff=true)
# Equality constraint
@NLconstraint(model,timeConstrain(k...)==0)
# Solve the optimization problem
JuMP.optimize!(model)

After some debugging I found out that in my Julia code, the lower and upper bounds and the initial guess of my objective function can be only numeric values, while in Matlab, those parameters were array of numbers. So, when the optimization is running, I found out that in Matlab the objective function receives the entire array k0guess as k, while in Julia k is an array filled with zeros, because of that the objective function returns a wrong value that is different from the Matlab one.

These are the lines of codes of the objective function that gives me a different result from Matlab:

k1=T[k0];
for item in k
     push!(k1,item);
end

Is there a way to emulate the same behavior of Matlab or i have to change my objective function in order to adapt it to compute a single value at a time?
Thank you so much in advance for your help!!

Hi @Alfespo97, welcome to the forum.

I have quite a few ideas for how we can improve your model, but the biggest problem that the moment is that I don’t know what optimization_data or timeConstrain is, so I cannot reproduce your issue.

Do you have a reproducible example that you can share?

I don’t have the data so I can’t test this (or check if I made a mistake), but this should point you in the right direction:

using JuMP, Ipopt
k0 = optimization_data["k0"]
a = optimization_data["a"]
b = optimization_data["b"]
s_sweep = optimization_data["sweep"]
N = length(k0guess)
ds = [s_sweep[i] - s_sweep[i-1] for i in 2:length(s_sweep)]
d(x, i) = 0.5 (x[i+1] + x[i])
model = Model(Ipopt.Optimizer)
@variable(model, lower_bounds[i+1] <= k[i=1:N] <= upper_bounds[i+1], start=k0guess[i])
@variable(model, f[1:N])
k1 = T[k0, k...]
@constraint(
    model, 
    [i in 1:N], 
    f[i] == (k1[i+1]-k1[i]) / ds[i] + d(a, i) * d(k1, i) + d(b, i),
)
@objective(model, Min, sum(f[i]^2 * ds[i] for i in 1:N))
2 Likes

fmincon in Matlab is a multi-algorithm. Do you know which one(s) are used?

1 Like

Thank you really much for the quick response.
Regarding optimization_data, it is a struct that i have exported from Matlab that contains the parameters used to compute the objective and constraint function. I did this because i wanted to test the performance and computation time of the optimization in Julia before translating all my Matlab scripts.
Here is the link to the JSON file:
https://drive.google.com/file/d/1SsCsqWB_FiXvPTJR2f-zjNJw_tKLQTA3/view?usp=drive_link

While this is the timeConstrain function:

function timeConstrain(k::T...) where {T<:Real}
    k0=optimization_data["k0"]
    s_sweep=optimization_data["sweep"]
    tmax=optimization_data["tmax"];
    m=1;
    k1=T[k0];
    
    for item in k
        push!(k1,item);
    end
    ds=[s_sweep[i+1]-s_sweep[i] for i in range(start=1,stop=length(s_sweep)-1)];
    kh=[0.5*(k1[i+1]+k1[i]) for i in range(start=1,stop=length(k1)-1)];
    g=[]
    for item in kh
        push!(g,sqrt(m./(2*item)))
    end
    #c=[];  vincolo di disuglianza non lineare (in questo caso non è presente)
    ceq=0;
    for i in range(start=1,stop=length(g))
        
        ceq+=g[i]*ds[i]-tmax;
    end
    return ceq
end

However i will try to modify my code following your advices. Thank you for your help!

1 Like

Hi, thank you for the response, the algorithm used in Matlab is ‘interior point’ which is the default algorithm if none is set. Here is the Matlab code with the call to fmincon.

timecon=@(k)timeConstrain(k0,k,Tmax, s_sweep, m); % time constraint
nonlcon=@(k)constrainFun(k0,k,Tmax, VehicleData.FmapCoeff, s_sweep, a, b, m, Kref, Lref, mrif)
fun=@(k)Jfun(k0,k, s_sweep, a, b); % objective function
options=optimoptions('fmincon','SpecifyObjectiveGradient',true,'SpecifyConstraintGradient',true,'ScaleProblem',false);
options.Display = 'off'; %'final-detailed';
options.Diagnostics='off';
options.MaxFunctionEvaluations=1e8;
options.StepTolerance=1.e-8;
options.MaxIterations=1e6;
[K1guess]=fmincon(fun,k0guess,[],[],[],[],lb(2:end),ub(2:end),timecon,options);
% Ottimizzazione con vincolo temporale e vincoli di forza
[K0guess,~,exitflag,~]=fmincon(fun,K1guess,[],[],[],[],lb(2:end),ub(2:end),nonlcon,options); %aggiunta commentando la precedente minimizzazione

Thank you again for your help, appreciate it a lot!!

My understanding is that fmincon switches algorithms depending on the convergence behaviour. There is some setting that causes the algorithm to be printed in the output (‘Display’).

Edit: I can’t find it in Matlab 2023 anymore. Perhaps this was abandoned?

1 Like

fmincon function is still there in Matlab in the latest release (R2023b), namely in the official Optimization Toolbox for Matlab, see Find minimum of constrained nonlinear multivariable function - MATLAB fmincon. Not seeing the toolbox can mean that the toolbox just has not been installed on your machine.

Some description of implemented algorithms is in Choosing the Algorithm - MATLAB & Simulink.

1 Like

I meant I could not find the output of the used algorithm from fmincon.

1 Like

For convenience, the Display option is available through optimoptions. Perhaps the most detailed info is obtained by setting opts = optimoptions('fmincon','Display','iter-detailed') before calling the solver x = fmincon(...,opts).

1 Like

I didn’t test this locally, but something like this should work:

using JuMP, Ipopt
k0 = optimization_data["k0"]
a = optimization_data["a"]
b = optimization_data["b"]
s_sweep = optimization_data["sweep"]
tmax = optimization_data["tmax"]
m = 1
N = length(k0guess)
ds = [s_sweep[i] - s_sweep[i-1] for i in 2:length(s_sweep)]
d(x, i) = 0.5 (x[i+1] + x[i])
model = Model(Ipopt.Optimizer)
@variable(model, lower_bounds[i+1] <= k[i=1:N] <= upper_bounds[i+1], start=k0guess[i])
@variable(model, f[1:N])
k1 = T[k0, k...]
@constraint(
    model, 
    [i in 1:N], 
    f[i] == (k1[i+1]-k1[i]) / ds[i] + d(a, i) * d(k1, i) + d(b, i),
)
@constraint(model, sum(sqrt(m / (2 * d(k1, i))) * ds[i] for i in 1:N) == N * tmax)
@objective(model, Min, sum(f[i]^2 * ds[i] for i in 1:N))
1 Like

Thank you for the answer :slight_smile: and sorry for bothering you for my lack of knowledge in Julia even if i like the code syntax, it’s really cool!
However I’m still getting an error: ‘UndefVarError: T not defined’ on ‘k1 = T[k0, k…]’. Do you have any advice for this?
Edit: i declared T as any and i think this made the trick.

1 Like

Yeah, i tried to display it on the output console but i could only see the numeric values of each iteration, it didn’t show any info on the algorithm

Just delete the T

1 Like