Skip to content

Initial package implementation - #5

Open
dnguyen227 wants to merge 18 commits into
infiniteopt:mainfrom
dnguyen227:package_updates
Open

dnguyen227 wants to merge 18 commits into
infiniteopt:mainfrom
dnguyen227:package_updates

Conversation

@dnguyen227

@dnguyen227 dnguyen227 commented Aug 23, 2026 •

Copy link
Copy Markdown
Collaborator

Sample how we'd use this:

using DisjunctiveProgramming, DisjunctiveAlgorithms, Gurobi, Ipopt
import DisjunctiveAlgorithms as DA

model = GDPModel(() -> DA.Optimizer(Ipopt.Optimizer, Gurobi.Optimizer))
set_silent(model)
@variable(model, 0 <= x <= 10)
@variable(model, Y[1:2], Logical)
@constraint(model, x <= 3, Disjunct(Y[1]))
@constraint(model, x^2 == 64, Disjunct(Y[2]))
@disjunction(model, Y)
@objective(model, Max, x)
optimize!(model, gdp_method = Direct())

# status
termination_status(model)   # MOI.LOCALLY_SOLVED
primal_status(model)        # MOI.FEASIBLE_POINT
raw_status(model)           # solver-reported string from the LOA loop
result_count(model)         # 1
is_solved_and_feasible(model)

#obj and bounds
objective_value(model)      # 8.0
objective_bound(model)      # master bound at termination
relative_gap(model)

# solution (can't get duals)
value(x)                    # 8.0
value(Y[1])                 # false
value(Y[2])                 # true
value.(Y)                   # Bool vector

# Solve statistics
solve_time(model)
solver_name(model)          # "DisjunctiveAlgorithms"

# Algorithm attributes read back through JuMP
get_attribute(model, DA.Algorithm())
get_attribute(model, DA.NumIterationLimit())
get_attribute(model, DA.ConvergenceTolerance())

# example of calls not supported.
# dual(con)                 # DualStatus is always NO_SOLUTION
# value(con)                # ConstraintPrimal is refused, not computed

@dnguyen227

Copy link
Copy Markdown
Collaborator Author

@pulsipher ready for review.

@pulsipher pulsipher left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A few comments/questions:

  • I believe this requires that we first at support for MOI disjunctions in DisjunctiveProgramming, right?
  • It doesn't appear that this optimizer supports the full MOI API for queries (i.e., not requiring the user to call the inner solver directly)
  • Are the methods in the main src folder truly general and not specific to LOA? (especially master.jl and nlp.jl)
  • It would be good to have a test for the natural user interface via DisjunctiveProgramming

Comment thread src/problem.jl Outdated
@dnguyen227

Copy link
Copy Markdown
Collaborator Author

A few comments/questions:

* I believe this requires that we first at support for MOI disjunctions in DisjunctiveProgramming, right?

* It doesn't appear that this optimizer supports the full MOI API for queries (i.e., not requiring the user to call the inner solver directly)

* Are the methods in the main src folder truly general and not specific to LOA? (especially  master.jl and nlp.jl)

* It would be good to have a test for the natural user interface via DisjunctiveProgramming

All these items are covered one way or another. Pls see points below.

  • https://github.com/infiniteopt/DisjunctiveProgramming.jl/pull/140 is the additional DisjunctionSet we need to support.
  • We don't support certain things like duals, and as it stands now the user only needs to call our optimizer at the end. I aimed to like Juniper in this way because they also use two optimizers.
  • I've rearranged the files so that we can be more general later.
  • Not sure how we'd test the natural user interface right now, I think cutting another version of DP.jl after we settle most things will allow me to do this?

@pulsipher

Copy link
Copy Markdown
Contributor

This is looking better, let's get the new set in DP merged so we can cut a release to so we can use it here.

MOI's own `convert` is rough-and-ready: it reads a two-argument `*`
as coefficient times variable and rejects `-`, so promoted rows such
as `x * y` or `x * y - 3` threw there. `_polynomial` walks the tree
instead, and `_to_affine` gains a constant method.
`MultiGenerationSize` evaluates several indicator combinations per
master solve. They come from the `mip_solver`'s solution pool where it
exposes one, and otherwise from re-solving the master behind a no-good
cut per combination already taken. `BatchedSubproblems` stacks them
into one NLP, with the sequential subproblem as the fallback for a
failed batch. Adds `MasterSolveCount` and `NLPSolveCount`.
`combination_sources.jl` holds the default pool-then-re-solve source
alongside the experimental `Neighborhood`, `LPRounding`,
`RandomCombinations` and `CutoffResolve`, none of which need anything
from the solver. A source extends `_candidate_combinations`.
The README install note pinned a patch version, when what the branch
requirement is really about is `DisjunctionSet` and `Direct()` not
being in a registered release yet. Say that instead.
`MasterSolveTime` and `NLPSolveTime` report where a run spent its
time. The default combination source now takes as many pool entries
as the solver holds, and re-solves the master only when there is no
pool at all.
The covering pass was solving the full OA master, cuts and continuous
variables included, so initialization was already MILP/NLP instead of
the NLP-only pass Turkay and Grossmann describe.

`_SetCoverModel` is the disjunct binaries under the exactly-one and
propositional rows only, with its own no-good cuts, and stops once a
solve covers nothing new. The master MILP now first solves in the main
loop.

Also adds `NLPInfeasibleCount`, and drops indicator rows from the LP
copy in `_relaxed_activations`, where a gated row has no relaxation
without its binary.
master.jl, nlp.jl and cuts.jl are specific to logic-based outer
approximation rather than general, so they belong beside LOA.jl;
`_instantiate` moves to optimizer.jl.
@pulsipher

Copy link
Copy Markdown
Contributor

DisjunctiveProgramming v0.7 has ben released.

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.

3 participants