Getting INVALID_MODEL error while solving RMSE

I’m attempting to minimize an RMSE where the optimized coefficients alpha and beta give a forecasted value (xnext) from the original value (x_k). Initially it did not let me add the square root in the objective function, so I tried using sqrt(msd(xnext, x_k)) as my objective function but since xnext is computed dynamically, it gives me an error. Now, with the square root in the objective function, it give me an INVALID_MODEL error. Any ideas or suggestion will be greatly appreciated. The problem formulation is below and the julia code follows

image

My code is below

bn = 33
#x_k = EstimatedVoltage;
x_k = [0.996296998; 0.99494058; 0.974948068; 0.969848525; 0.964424502; 0.947913184; 0.944859396; 0.935953084; 0.929733301; 0.920502051; 0.92148015; 0.918334107; 0.917047839; 0.913723332; 0.914563694; 0.914004943; 0.908324472; 0.909002883; 0.991995169; 0.983359984; 0.991156028; 0.98713166; 0.977664579; 0.968545981; 0.965580768; 0.945010536; 0.937951627; 0.925111218; 0.916413078; 0.91718043; 0.909069676; 0.909483012; 0.911058107]

# Initialize a JuMP Optimization Model
fcst = Model(with_optimizer(Ipopt.Optimizer, print_level=0))

# Defining variables
@variable(fcst, 0.001 <= alpha[i in 1:bn] <= 0.99)
@variable(fcst, 0.001 <= beta[i in 1:bn] <= 0.99)
@variable(fcst, a_k[i in 1:bn] )
@variable(fcst, b_k[i in 1:bn])
@variable(fcst, xnext[i in 1:bn])
@variable(fcst, Error[i in 1:bn])

# Objective function
@NLobjective(fcst, Min, sqrt(sum(xnext[i]-x_k[i] for i in 1:bn)^2/bn))
#@objective(fcst, Min, sum(xnext[i]-x_k[i] for i in 1:bn)^2/bn)
#@objective(fcst, Min, sqrt(msd(x_k,x_k)))

bn = 33
for i in 1:bn

if i == 1
    apast = x_k[1,1]
    bpast = x_k[1,1] - x_k[2,1]
 @constraint(fcst, a_k[i] ==  apast )
 @constraint(fcst, b_k[i] ==  bpast)
 @constraint(fcst, xnext[i] ==  a_k[i] + b_k[i])

else
apast = a_k[i-1]
bpast = b_k[i-1]
@constraint(fcst, a_k[i] ==  alpha[i]*x_k[i] + (1 - alpha[i]*(apast + bpast)))
@constraint(fcst, b_k[i] ==  beta[i]*(a_k[i] - apast) + (1 - beta[i]*bpast))
@constraint(fcst, xnext[i] ==  a_k[i] + b_k[i])
@constraint(fcst, beta[i] <= 0.99*alpha[i])
end

end
# Solve the optimization problem
JuMP.optimize!(fcst)
Alpha = JuMP.value.(alpha)
Beta = JuMP.value.(beta)
Xnext = JuMP.value.(xnext)
Level = JuMP.value.(a_k)
Trend = JuMP.value.(b_k)

# Check that the solver terminated without an error
println("The solver termination status is $(termination_status(fcst))")

# Check the value of the objective function
RMSE = objective_value(fcst)

It means Ipopt is evaluating a function outside of its domain.
Here, make sure it is only evaluating the square root with a positive input; see https://github.com/jump-dev/ipopt.jl#invalid_model-error
For instance,

using JuMP, Ipopt
model = Model(Ipopt.Optimizer)
@variable(model, x <= 2)
@NLobjective(model, Max, sqrt(x - 1))
optimize!(model)
@show termination_status(model)
@show raw_status(model)

gives

termination_status(model) = MathOptInterface.INVALID_MODEL
raw_status(model) = "Invalid_Number_Detected"

but

using JuMP, Ipopt
model = Model(Ipopt.Optimizer)
@variable(model, x <= 2, start = 1.1)
@NLobjective(model, Max, sqrt(x - 1))
optimize!(model)
@show termination_status(model)
@show raw_status(model)

gives

termination_status(model) = MathOptInterface.LOCALLY_SOLVED
raw_status(model) = "Solve_Succeeded"

Tip: always query raw_status when you wonder why a solver gives you a given status.

1 Like

Another trick you can use in some situations (like this one), is to omit the sqrt function entirely. Given that sqrt is a monotone function the arg min of min:sqrt((x-c)^2) and min:(x-c)^2 will be the same. By omitting the sqrt function during the optimization, you avoid the issue of an undefined derivative at 0.0.

2 Likes

Thank for your response. Yes, I can do that. It’ll slightly alter my coefficients and I’ll have to take the square root outside the objective function to get my RMSE but that should be okay.

Is there a better way to define my objective function because if I write it down like below it takes the sum before squaring?

@NLobjective(fcst, Min, sqrt(sum(xnext[i]-x_k[i] for i in 1:bn)^2/bn))

I want to square the values before taking the sum. So, I decided to write the objective function like below
@NLobjective(fcst, Min, (sum((xnext[i] - x_k[i] for i in 1:3).*(xnext[i]-x_k[i] for i in 1:3)))/bn)

However, the above objective function gives me the following error “LoadError: sum() can appear in nonlinear expressions only if the argument is a generator statement, for example, sum(x[i] for i in 1:N)”. How can I get rid of this error?

Thanks again

Thanks for the tip

@NLobjective(fcst, Min, sum((xnext[i] - x_k[i])^2 for i in 1:bn) / bn)

should work.

1 Like

Yes, it does work. The placement of the for loop and parenthesis makes a huge difference

@NLobjective(fcst, Min, sum((xnext[i] - x_k[i])^2 for i in 1:bn) / bn)… this works
@NLobjective(fcst, Min, sum((xnext[i] - x_k[i] for i in 1:3)^2)/bn)…this does not work

With the right placement of the for loop, I was able to define the RMSE objective function with the square root included as shown below

@NLobjective(fcst, Min, sqrt(sum((xnext[i]-x_k[i])^2 for i in 1:bn)/bn))…this works
@NLobjective(fcst, Min, sqrt(sum((xnext[i]-x_k[i] for i in 1:bn)^2/bn))…this does not work

Great thanks for your help.

The placement of the for loop and parenthesis makes a huge difference

Your two lines are not equivalent. The first is correct.

You’re absolutely correct that they’re not equivalent. I stated the two formulations to help anyone that makes reference to this ticket in the future to see the difference and why my initial equation didn’t work.

Thanks for your input.