Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected interactions with JuMP.Parameter (in QPs) #3947

Open
sstroemer opened this issue Feb 23, 2025 · 7 comments
Open

Unexpected interactions with JuMP.Parameter (in QPs) #3947

sstroemer opened this issue Feb 23, 2025 · 7 comments

Comments

@sstroemer
Copy link

Note:
I was unsure which parts of this belong to JuMP, MOI, HiGHS itself (or maybe HiGHS.jl), if you can point that out I'll happily split/move this issue to the appropriate repos. Sorry for the "collection" in a single issue, but I also didn't want to flood everything with multiple ones.


Brief summary/overview of examples provided:

  1. Wrong solution found by HiGHS when using Parameter.
  2. Same issue - without Parameter, when using fixed variables - and a weird workaround.
  3. Issue using write_to_file for a QP with Parameter, when writing to MPS.
  4. dimension mismatch errors (and extreme iteration overhead) in HiGHS when solving a QP with Parameter.

All examples are run after

using JuMP
import HiGHS

with

JuMP             v1.24.0
MathOptInterface v1.36.0
HiGHS            v1.13.0
HiGHS_jll        v1.9.0+0

and showing the following commit info: HiGHS 1.9.0 (git hash: 66f735e60).

Note: Not sure if these issues only appear for QPs, had no time to test with other problem types.


Example 1

This is a MWE showing a wrong solution being found by HiGHS, printing an error, but then communicating optimality.

model = Model(HiGHS.Optimizer)
@variable(model, x >= 1)
@variable(model, p, set = Parameter(1.0))
@objective(model, Min, x * p)
optimize!(model)

which results in

termination_status(model)  # OPTIMAL::TerminationStatusCode = 1
objective_value(model)     # 0.0

with the following (shortened) output from HiGHS

ERROR:   QP solver claims optimality, but with num/max/sum primal(2/1/2) infeasibilities
Model status        : Optimal
Objective value     :  0.0000000000e+00

Example 2

I suspected the issue to arise from the use of Parameter, but this example shows that even a "normal" variable with bounds fixed to 1.0 fails in the same way... until a superfluous constraint is added that HiGHS will disregard anyways.

model = Model(HiGHS.Optimizer)
@variable(model, x >= 1)
@variable(model, p == 1)        # this alone does not fix the problem
@constraint(model, p >= -1e20)  # HiGHS treats lower bounds <= -1e+20 as -Inf
@objective(model, Min, x * p)
optimize!(model)

which (only when adding the constraint) gives the correct solution

Model status        : Optimal
Objective value     :  1.0000000000e+00

Example 3

Writing a JuMP model to a MPS file "forgets" about the parameters, not preserving the bounds. Not sure if that is a problem arising from the JuMP or MOI side of things.

model = Model()
@variable(model, p1, set = Parameter(1.0))
@variable(model, p2 == 1.0)
write_to_file(model, "model.mps")

lead to the following bound section, where I assume that p1 should actually get the same fixed bound:

BOUNDS
 FR bounds    p1
 FX bounds    p2        1

Example 4

Running a small QP previously written to highs_qp.mof.json

{"name":"MathOptFormat Model","version":{"major":1,"minor":7},"variables":[{"name":"x1"},{"name":"x2"},{"name":"x3"},{"name":"x4"},{"name":"x5"},{"name":"x6"},{"name":"x7"},{"name":"x8"},{"name":"x9"},{"name":"x10"},{"name":"x11"},{"name":"x12"},{"name":"x13"},{"name":"x14"},{"name":"x15"},{"name":"x16"},{"name":"x17"},{"name":"x18"},{"name":"x19"},{"name":"x20"},{"name":"x21"},{"name":"x22"},{"name":"x23"},{"name":"x24"},{"name":"x25"},{"name":"x26"},{"name":"x27"},{"name":"x28"},{"name":"x29"},{"name":"x30"},{"name":"x31"},{"name":"x32"},{"name":"x33"},{"name":"x34"},{"name":"x35"},{"name":"x36"},{"name":"x37"}],"objective":{"sense":"min","function":{"type":"ScalarQuadraticFunction","affine_terms":[{"coefficient":30.0,"variable":"x8"},{"coefficient":30.0,"variable":"x9"},{"coefficient":30.0,"variable":"x10"},{"coefficient":30.0,"variable":"x11"},{"coefficient":30.0,"variable":"x12"},{"coefficient":150.0,"variable":"x23"},{"coefficient":150.0,"variable":"x24"},{"coefficient":150.0,"variable":"x25"},{"coefficient":150.0,"variable":"x26"},{"coefficient":150.0,"variable":"x27"}],"quadratic_terms":[{"coefficient":1.0,"variable_1":"x7","variable_2":"x1"},{"coefficient":1.0,"variable_1":"x13","variable_2":"x2"},{"coefficient":1.0,"variable_1":"x14","variable_2":"x3"},{"coefficient":1.0,"variable_1":"x15","variable_2":"x4"},{"coefficient":1.0,"variable_1":"x16","variable_2":"x5"},{"coefficient":1.0,"variable_1":"x17","variable_2":"x6"},{"coefficient":1.0,"variable_1":"x37","variable_2":"x37"},{"coefficient":-1.0,"variable_1":"x17","variable_2":"x37"},{"coefficient":1.0,"variable_1":"x32","variable_2":"x37"},{"coefficient":1.0,"variable_1":"x17","variable_2":"x17"},{"coefficient":-1.0,"variable_1":"x32","variable_2":"x17"},{"coefficient":1.0,"variable_1":"x32","variable_2":"x32"},{"coefficient":1.0,"variable_1":"x33","variable_2":"x33"},{"coefficient":-1.0,"variable_1":"x13","variable_2":"x33"},{"coefficient":1.0,"variable_1":"x28","variable_2":"x33"},{"coefficient":1.0,"variable_1":"x13","variable_2":"x13"},{"coefficient":-1.0,"variable_1":"x28","variable_2":"x13"},{"coefficient":1.0,"variable_1":"x28","variable_2":"x28"},{"coefficient":1.0,"variable_1":"x36","variable_2":"x36"},{"coefficient":-1.0,"variable_1":"x16","variable_2":"x36"},{"coefficient":1.0,"variable_1":"x31","variable_2":"x36"},{"coefficient":1.0,"variable_1":"x16","variable_2":"x16"},{"coefficient":-1.0,"variable_1":"x31","variable_2":"x16"},{"coefficient":1.0,"variable_1":"x31","variable_2":"x31"},{"coefficient":1.0,"variable_1":"x34","variable_2":"x34"},{"coefficient":-1.0,"variable_1":"x14","variable_2":"x34"},{"coefficient":1.0,"variable_1":"x29","variable_2":"x34"},{"coefficient":1.0,"variable_1":"x14","variable_2":"x14"},{"coefficient":-1.0,"variable_1":"x29","variable_2":"x14"},{"coefficient":1.0,"variable_1":"x29","variable_2":"x29"},{"coefficient":1.0,"variable_1":"x35","variable_2":"x35"},{"coefficient":-1.0,"variable_1":"x15","variable_2":"x35"},{"coefficient":1.0,"variable_1":"x30","variable_2":"x35"},{"coefficient":1.0,"variable_1":"x15","variable_2":"x15"},{"coefficient":-1.0,"variable_1":"x30","variable_2":"x15"},{"coefficient":1.0,"variable_1":"x30","variable_2":"x30"}],"constant":0.0}},"constraints":[{"name":"c1","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":1.0,"variable":"x8"},{"coefficient":-1.1111111111111112,"variable":"x18"}],"constant":0.0},"set":{"type":"EqualTo","value":0.0}},{"name":"c2","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":1.0,"variable":"x9"},{"coefficient":-1.1111111111111112,"variable":"x19"}],"constant":0.0},"set":{"type":"EqualTo","value":0.0}},{"name":"c3","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":1.0,"variable":"x10"},{"coefficient":-1.1111111111111112,"variable":"x20"}],"constant":0.0},"set":{"type":"EqualTo","value":0.0}},{"name":"c4","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":1.0,"variable":"x11"},{"coefficient":-1.1111111111111112,"variable":"x21"}],"constant":0.0},"set":{"type":"EqualTo","value":0.0}},{"name":"c5","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":1.0,"variable":"x12"},{"coefficient":-1.1111111111111112,"variable":"x22"}],"constant":0.0},"set":{"type":"EqualTo","value":0.0}},{"name":"c6","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":-1.0,"variable":"x13"},{"coefficient":1.0,"variable":"x18"}],"constant":0.0},"set":{"type":"EqualTo","value":0.0}},{"name":"c7","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":-1.0,"variable":"x14"},{"coefficient":1.0,"variable":"x19"}],"constant":0.0},"set":{"type":"EqualTo","value":0.0}},{"name":"c8","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":-1.0,"variable":"x15"},{"coefficient":1.0,"variable":"x20"}],"constant":0.0},"set":{"type":"EqualTo","value":0.0}},{"name":"c9","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":-1.0,"variable":"x16"},{"coefficient":1.0,"variable":"x21"}],"constant":0.0},"set":{"type":"EqualTo","value":0.0}},{"name":"c10","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":-1.0,"variable":"x17"},{"coefficient":1.0,"variable":"x22"}],"constant":0.0},"set":{"type":"EqualTo","value":0.0}},{"name":"c11","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":0.22444444444444445,"variable":"x18"},{"coefficient":-1.0,"variable":"x23"}],"constant":0.0},"set":{"type":"EqualTo","value":0.0}},{"name":"c12","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":0.22444444444444445,"variable":"x19"},{"coefficient":-1.0,"variable":"x24"}],"constant":0.0},"set":{"type":"EqualTo","value":0.0}},{"name":"c13","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":0.22444444444444445,"variable":"x20"},{"coefficient":-1.0,"variable":"x25"}],"constant":0.0},"set":{"type":"EqualTo","value":0.0}},{"name":"c14","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":0.22444444444444445,"variable":"x21"},{"coefficient":-1.0,"variable":"x26"}],"constant":0.0},"set":{"type":"EqualTo","value":0.0}},{"name":"c15","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":0.22444444444444445,"variable":"x22"},{"coefficient":-1.0,"variable":"x27"}],"constant":0.0},"set":{"type":"EqualTo","value":0.0}},{"name":"c1_1","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":1.0,"variable":"x7"}],"constant":0.0},"set":{"type":"GreaterThan","lower":0.0}},{"name":"c1_2","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":1.0,"variable":"x7"}],"constant":0.0},"set":{"type":"LessThan","upper":0.0}},{"name":"c2_1","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":-1.0,"variable":"x7"},{"coefficient":1.0,"variable":"x18"}],"constant":0.0},"set":{"type":"LessThan","upper":10.0}},{"name":"c3_1","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":-1.0,"variable":"x7"},{"coefficient":1.0,"variable":"x19"}],"constant":0.0},"set":{"type":"LessThan","upper":10.0}},{"name":"c4_1","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":-1.0,"variable":"x7"},{"coefficient":1.0,"variable":"x20"}],"constant":0.0},"set":{"type":"LessThan","upper":10.0}},{"name":"c5_1","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":-1.0,"variable":"x7"},{"coefficient":1.0,"variable":"x21"}],"constant":0.0},"set":{"type":"LessThan","upper":10.0}},{"name":"c6_1","function":{"type":"ScalarAffineFunction","terms":[{"coefficient":-1.0,"variable":"x7"},{"coefficient":1.0,"variable":"x22"}],"constant":0.0},"set":{"type":"LessThan","upper":10.0}},{"function":{"type":"Variable","name":"x8"},"set":{"type":"GreaterThan","lower":0.0}},{"function":{"type":"Variable","name":"x9"},"set":{"type":"GreaterThan","lower":0.0}},{"function":{"type":"Variable","name":"x10"},"set":{"type":"GreaterThan","lower":0.0}},{"function":{"type":"Variable","name":"x11"},"set":{"type":"GreaterThan","lower":0.0}},{"function":{"type":"Variable","name":"x12"},"set":{"type":"GreaterThan","lower":0.0}},{"function":{"type":"Variable","name":"x13"},"set":{"type":"GreaterThan","lower":0.0}},{"function":{"type":"Variable","name":"x14"},"set":{"type":"GreaterThan","lower":0.0}},{"function":{"type":"Variable","name":"x15"},"set":{"type":"GreaterThan","lower":0.0}},{"function":{"type":"Variable","name":"x16"},"set":{"type":"GreaterThan","lower":0.0}},{"function":{"type":"Variable","name":"x17"},"set":{"type":"GreaterThan","lower":0.0}},{"function":{"type":"Variable","name":"x18"},"set":{"type":"GreaterThan","lower":0.0}},{"function":{"type":"Variable","name":"x19"},"set":{"type":"GreaterThan","lower":0.0}},{"function":{"type":"Variable","name":"x20"},"set":{"type":"GreaterThan","lower":0.0}},{"function":{"type":"Variable","name":"x21"},"set":{"type":"GreaterThan","lower":0.0}},{"function":{"type":"Variable","name":"x22"},"set":{"type":"GreaterThan","lower":0.0}},{"function":{"type":"Variable","name":"x23"},"set":{"type":"GreaterThan","lower":0.0}},{"function":{"type":"Variable","name":"x24"},"set":{"type":"GreaterThan","lower":0.0}},{"function":{"type":"Variable","name":"x25"},"set":{"type":"GreaterThan","lower":0.0}},{"function":{"type":"Variable","name":"x26"},"set":{"type":"GreaterThan","lower":0.0}},{"function":{"type":"Variable","name":"x27"},"set":{"type":"GreaterThan","lower":0.0}},{"function":{"type":"Variable","name":"x1"},"set":{"type":"Parameter","value":0.0}},{"function":{"type":"Variable","name":"x2"},"set":{"type":"Parameter","value":-3.8}},{"function":{"type":"Variable","name":"x3"},"set":{"type":"Parameter","value":-3.8}},{"function":{"type":"Variable","name":"x4"},"set":{"type":"Parameter","value":-3.8}},{"function":{"type":"Variable","name":"x5"},"set":{"type":"Parameter","value":-3.8}},{"function":{"type":"Variable","name":"x6"},"set":{"type":"Parameter","value":-3.8}},{"function":{"type":"Variable","name":"x28"},"set":{"type":"Parameter","value":0.0}},{"function":{"type":"Variable","name":"x29"},"set":{"type":"Parameter","value":0.0}},{"function":{"type":"Variable","name":"x30"},"set":{"type":"Parameter","value":0.0}},{"function":{"type":"Variable","name":"x31"},"set":{"type":"Parameter","value":0.0}},{"function":{"type":"Variable","name":"x32"},"set":{"type":"Parameter","value":0.0}},{"function":{"type":"Variable","name":"x33"},"set":{"type":"Parameter","value":-3.8}},{"function":{"type":"Variable","name":"x34"},"set":{"type":"Parameter","value":-3.8}},{"function":{"type":"Variable","name":"x35"},"set":{"type":"Parameter","value":-3.8}},{"function":{"type":"Variable","name":"x36"},"set":{"type":"Parameter","value":-3.8}},{"function":{"type":"Variable","name":"x37"},"set":{"type":"Parameter","value":-3.8}}]}

by running

model = read_from_file("highs_qp.mof.json")
set_optimizer(model, HiGHS.Optimizer)
optimize!(model)

leads to dimension mismatch errors in the (shortened) output, that originate from solveL in factor.hpp:

  Iteration        Objective     NullspaceDim
          0        36.100007                0      0.00s
dimension mismatch
dimension mismatch
         39        36.100007                1      0.00s
Model status        : Optimal
QP ASM    iterations: 39
Objective value     :  3.6100000000e+01

To investigate, I manually replaced all Parameters by their current value:

obj = objective_function(model)
obj_params = zero(AffExpr)

# Extract and convert objective terms related to parameters.
for var in all_variables(model)
    is_parameter(var) || continue

    pval = parameter_value(var)

    # Handle: Objective terms like `... + coeff * param + ...`.
    add_to_expression!(obj_params, coefficient(obj, var) * pval)

    # Handle: Objective terms like `... + coeff * param * variable + ...`.
    # Note: `variable` can be a parameter itself (and even the same as `param`).
    for other in all_variables(model)
        ov = is_parameter(other) ? parameter_value(other) : other
        add_to_expression!(obj_params, coefficient(obj, var, other) * pval * ov)
    end
end

# Drop all parameters from the model, and irrelevant zeros from the objective expression.
delete(model, [var for var in all_variables(model) if is_parameter(var)])
drop_zeros!(obj_params)

# Set the new objective function and solve.
set_objective_function(model, objective_function(model) + obj_params)
optimize!(model)

which then shows

  Iteration        Objective     NullspaceDim
          0             36.1                0      0.00s
         10             36.1                0      0.00s
Model status        : Optimal
QP ASM    iterations: 10
Objective value     :  3.6100000000e+01

Not only does the error not occur anymore, it also needs considerably less iterations to solve the model. Not sure if these iterations actual cost a lot, but since it's 29 iterations overhead with just ending up twice in solveL, I assume that may impact larger models.

Note: Deleting all ParameterRef constraints and fixing the parameter variables using fix to their values, while also adding "auxiliary constraints" as in example 2, does not change anything here. I have no idea how presolve works for the QP solver in HiGHS, nor how a fixed bound (or EqualTo) is actually passed via the API, but "substituting" variables that are constrained to a specific value seems like an "easy" thing to do on the solver's side?

@joaquimg
Copy link
Member

The fundamental thing to remember is that JuMP is not presolving parameters, as you noted they appear as variables in the MPS files.

If you use POI, all (except example 2) your problems would be properly solved as it pre-solves the parameters, giving you a smaller problem that does not include variable products. This is exactly what you are asking for.

About example 1:

Your objective function, x * p, has the Q matrix:

Q = [
           0 1
           1 0
       ]

with eigenvalues:

julia> eigvals(Q)
2-element Vector{Float64}:
 -1.0
  1.0

Hence, it is not positive semidefinite hence this QP is not Convex, so HiGHS is not guaranteed to work:

As noted here, it may not be as explicit as it could be: https://github.com/jump-dev/ParametricOptInterface.jl HiGHS solves convex QPs.

About example 2,

To say more we might need HiGHS devs help, but your problems is still not guaranteed to work, but it might just work. It does not surprise me it worked. The solver might be taking a different and more lucky path in this second example.

About example 3,

MPS does not support writing parameters.

Probably the correct behavior was for it to give a warning, at least.

If you try to print what is inside HiGHS, it works as expected:

model = Model(HiGHS.Optimizer)
@variable(model, p1, set = Parameter(1.0))
@variable(model, p2 == 1.0)
write_to_file(model, "model.mps")
optimize!(model)
highs = unsafe_backend(model).inner
tmp_filename = "model.mps"
HiGHS.Highs_writeModel(highs, tmp_filename)

and you get:

NAME        
ROWS
 N  NoObj   
COLUMNS
    c0        NoObj     0
    c1        NoObj     0
RHS
BOUNDS
 FX BOUND     c0        1
 FX BOUND     c1        1
ENDATA

About example 4,

Use POI, it will do the presolve you want.

I have not dug deep into this as it is less minimal.

possible JuMP side improvements

  • check Q positive semidefiniteness (maybe also on HiGHS side) Tools to test and debug JuMP models #3664
  • warn on mps writer about unsupported constraints
  • possibly better document the parameters section, talking about caveats and POI
  • a warn about parameters products might be considered

@joaquimg
Copy link
Member

joaquimg commented Feb 23, 2025

Note that your example is very similar to the parameters limitations section:

https://jump.dev/JuMP.jl/stable/manual/variables/#Limitations

Which might be boosted by a link to POI

@odow
Copy link
Member

odow commented Feb 23, 2025

3 is a bug: jump-dev/MathOptInterface.jl#2653

I think 1, 2, and 4 are "expected" behavior, but I'll take a look to see if we can better catch these in HiGHS.jl.

@sstroemer
Copy link
Author

Thanks for the quick replies! I'll try to keep it "short" 😀

(joaquimg) If you use POI, [...] it pre-solves the parameters, giving you a smaller problem that does not include variable products.

I'm presolving the models manually anyways, which is less overhead (since it does not have to be generalized) than POI - so I was more trying to test if it makes sense to integrate JuMP.Parameter in some code for "parametric models" (just purely to streamline it more with what JuMP offers as features).

(joaquimg, regarding ex. 1) [...] is not positive semidefinite hence this QP is not Convex, so HiGHS is not guaranteed to work

Yes I know. My point was that I kind of expect either:

  1. the solver rejects a non-convex QP, or
  2. tries to solve the non-convex QP

If the solver applies (2.), then I was assuming the "expected" behaviour to be that it returns a proper termination status. It currently prints an error and then claims optimality in the returned status code. For related models it fails with QpModelStatus::kUndetermined, which is fine (since that is then mapped to OTHER_ERROR).

(odow) I think 1, 2, and 4 are "expected" behavior, but I'll take a look to see if we can better catch these in HiGHS.jl.

Regarding example 1: This is kind of related to this comment on a previous HiGHS issue - for other algorithms a similar issues has been handled on their side of things. Should I report it over there, or do you think that's something that should be done in HiGHS.jl?

(joaquimg, regarding ex. 2) The solver might be taking a different and more lucky path in this second example
(joaquimg, regarding ex. 4) Use POI, it will do the presolve you want

The constraint removal just indicated to me that at least some minimal preprocessing is done on the model before solving it. Eliminating p is something other solvers handle directly - that's why I was assuming that if at all that topic would fall into HiGHS' area. These examples just felt like "easy wins" to improve on the solver side, so I was just trying to make sure that I'm not missing something obvious on the JuMP side of things.


Note: Yes POI would be an option (as is manually presolving), it's just that these "small" issues prevent a straight forward application of HiGHS to some QP related topics (it's hard to debug and isolate these problems if they occur in some large scale iterative algorithms that someone sends me because it just "suddenly failed without any explicit reason").

@sstroemer
Copy link
Author

3 is a bug: jump-dev/MathOptInterface.jl#2653

I think 1, 2, and 4 are "expected" behavior, but I'll take a look to see if we can better catch these in HiGHS.jl.

Any of those that you think I should report over at HiGHS? Otherwise, it seems the only "real" issue outside the solver is the one you opened in MOI already so I think this one here could be closed again?

@odow
Copy link
Member

odow commented Feb 23, 2025

Example 1

This is expected behavior and working as expected. You cannot rely only on termination_status to check the status of the solution.

julia> using JuMP, HiGHS

julia> model = Model(HiGHS.Optimizer)
A JuMP Model
├ solver: HiGHS
├ objective_sense: FEASIBILITY_SENSE
├ num_variables: 0
├ num_constraints: 0
└ Names registered in the model: none

julia> @variable(model, x >= 1)
x

julia> @variable(model, p, set = Parameter(1.0))
p

julia> @objective(model, Min, x * p)
x*p

julia> optimize!(model)
Running HiGHS 1.9.0 (git hash: 66f735e60): Copyright (c) 2024 HiGHS under MIT licence terms
Coefficient ranges:
  Cost   [0e+00, 0e+00]
  Bound  [1e+00, 1e+00]
  Iteration        Objective     NullspaceDim
ERROR:   QP solver claims optimality, but with num/max/sum primal(2/1/2) infeasibilities
Model status        : Optimal
Objective value     :  0.0000000000e+00
HiGHS run time      :          0.00

julia> solution_summary(model)
* Solver : HiGHS

* Status
  Result count       : 1
  Termination status : OPTIMAL
  Message from the solver:
  "kHighsModelStatusOptimal"

* Candidate solution (result #1)
  Primal status      : INFEASIBLE_POINT
  Dual status        : FEASIBLE_POINT
  Objective value    : 0.00000e+00
  Objective bound    : 0.00000e+00
  Relative gap       : 0.00000e+00
  Dual objective value : 0.00000e+00

* Work counters
  Solve time (sec)   : 7.58261e-05
  Simplex iterations : 0
  Barrier iterations : 0
  Node count         : -1


julia> is_solved_and_feasible(model)
false

Example 2 and 4

Expected behavior. The HiGHS QP solver has a number things that could be improved. But I don't think that better presolve is on the list anytime soon. They're focused on the MIP solver.

@odow
Copy link
Member

odow commented Feb 23, 2025

The action item could be: we should add a tutorial on the specifics of POI to the JuMP docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants