Skip to content

Add MOI wrapper for CCOpt - #63

Open
frapac wants to merge 10 commits into
masterfrom
fp/moi_interface
Open

Add MOI wrapper for CCOpt#63
frapac wants to merge 10 commits into
masterfrom
fp/moi_interface

Conversation

@frapac

@frapac frapac commented Apr 30, 2026

Copy link
Copy Markdown
Member

With this PR, we can solve a JuMP model with complementarity constraints using CCOpt:

using JuMP
using CCOpt
using MathOptComplements
using NLPModelsJuMP

function fletcher_leyffer_ex2_model()
    model = Model()
    @variable(model, z[1:2] >= 0)
    @objective(model, Min, z[1] + z[2])
    @constraint(model, z[2]^2 >= 1)
    @constraint(model, [z[1], z[2]]  MOI.Complements(2))
    return model
end


model = fletcher_leyffer_ex2_model()
MathOptComplements.Bridges.add_all_bridges(model)
set_optimizer(model, CCOpt.Optimizer)
JuMP.optimize!(model)

The MOI wrapper is developed as a package extension. It requires MathOptComplements to reformulate automatically the mixed-complementarity constraints in MOI as strict complementarity.

cc @blegat

@frapac
frapac requested a review from apozharski April 30, 2026 10:01
@frapac frapac changed the title Add MOI wrapper for CCOpt [DNMY] Add MOI wrapper for CCOpt Apr 30, 2026
@noahrhodes

Copy link
Copy Markdown

Is this branch fully working? It would be great for a current project

@apozharski apozharski left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor comments, and needs a rebase, but otherwise LGTM.

end

function MOI.get(::Optimizer, ::MOI.DualStatus)
# TODO

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not actually sure what this is supposed to return, but I should be return UNKNOWN_RESULT_STATUS?

ind_x1 = getfield.(ind_cc1, :value)
ind_x2 = getfield.(ind_cc2, :value)

dest.mpcc = CCOpt.MPCCModelVarVar(nlp, ind_x1, ind_x2)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this needs a rename.

contypes = MOI.get(src, MOI.ListOfConstraintTypesPresent())
cc_cons = MOI.get(src, MOI.ListOfConstraintIndices{MOI.VectorOfVariables, _CC_SETS}())
if length(cc_cons) == 0
error("The model does not have any complementarity constraints. Please switch to an appropriate solver.")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Advise perhaps MadNLP 😄

@apozharski

Copy link
Copy Markdown
Member

@noahrhodes Hmmm I am not an MOI/JuMP expert 😅 (and I forgot that you actually asked for review on this, sorry @frapac ) but from what I can tell it seems like it should work, but the best way to know would be for someone to test it.

@frapac frapac changed the title [DNMY] Add MOI wrapper for CCOpt Add MOI wrapper for CCOpt Jul 21, 2026
@frapac

frapac commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

We are almost done with the MO interface. It remains just to solve two issues in the upstream package NLPModelsJuMP:

Also, I observe that sometimes MathOptComplements is not bridging correctly the model to CCOpt (cc @blegat ). This can be addressed directly in MathOptComplements. I will open separate issues to address this.

@frapac

frapac commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

@apozharski what should we do with the MOI tests? They tend to take a significant time. Two options:

  1. We launch them apart in a separate check
  2. We make them optional with a specific trigger to activate if we modify the MOI wrapper in CCOpt

@apozharski

Copy link
Copy Markdown
Member

@apozharski what should we do with the MOI tests? They tend to take a significant time. Two options:

1. We launch them apart in a separate check

2. We make them optional with a specific trigger to activate if we modify the MOI wrapper in CCOpt

I suspect that the right answer is to figure out a way to do option 2 but do it at the "step" level rather than at the "job" level. https://github.com/dorny/paths-filter is one such way to do that it seems. The fact this isn't supported natively is one of those things about Github that astounds me.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants