Skip to content

Move code to MOI and add JuMP layer #19

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

Merged
merged 36 commits into from
May 24, 2025
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
4018990
Move code to MOI and add JuMP layer
joaquimg Apr 30, 2025
4f716b0
format
joaquimg May 1, 2025
3185a6f
Improve API
joaquimg May 1, 2025
cea96e6
fixes
joaquimg May 1, 2025
7b0c0a2
name_source -> model
joaquimg May 1, 2025
2c79007
suggestions
joaquimg May 1, 2025
9241ee1
small fix
joaquimg May 1, 2025
9c83751
Merge branch 'main' into jg/moi
joaquimg May 1, 2025
ed42075
feasibility almost ready
joaquimg May 7, 2025
87aacb2
Finish feasibility rewrite
joaquimg May 7, 2025
e378889
Merge branch 'main' into jg/moi
joaquimg May 7, 2025
85e00fb
MOI infeasibility analysis
joaquimg May 8, 2025
38ae419
use MA
joaquimg May 9, 2025
2e39b0c
MOI IIS
joaquimg May 13, 2025
997200a
format
joaquimg May 13, 2025
e059c41
add query functions in numerical
joaquimg May 13, 2025
fc09db0
format
joaquimg May 13, 2025
f0d70fa
Add query tools
joaquimg May 13, 2025
833e6c1
Add query tools
joaquimg May 13, 2025
a88f0e8
add tests
joaquimg May 14, 2025
1cd08a3
add tests
joaquimg May 22, 2025
b5253c7
add tests
joaquimg May 22, 2025
4fc7565
add comments
joaquimg May 22, 2025
5ecd302
simplify api
joaquimg May 22, 2025
ceccb9f
cleanup api
joaquimg May 22, 2025
97cde56
add tests
joaquimg May 22, 2025
0b3e9e4
add tests
joaquimg May 22, 2025
e1288d6
format
joaquimg May 22, 2025
e719b96
more tests
joaquimg May 23, 2025
7e36757
more tests
joaquimg May 23, 2025
90903ee
fix and test
joaquimg May 23, 2025
1426502
add tests and cleanup
joaquimg May 23, 2025
6f641ad
format
joaquimg May 23, 2025
e9035d7
add features and tests
joaquimg May 24, 2025
ad37c02
add tests
joaquimg May 24, 2025
2fc4f3f
add docs
joaquimg May 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 87 additions & 6 deletions src/ModelAnalyzer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

module ModelAnalyzer

import MathOptInterface as MOI

abstract type AbstractIssue end

abstract type AbstractData end
Expand All @@ -25,7 +27,7 @@
function analyze end

"""
summarize([io::IO,] AbstractData; verbose = true, max_issues = typemax(Int), kwargs...)
summarize([io::IO,] AbstractData; name_source = nothing, verbose = true, max_issues = typemax(Int), kwargs...)

Print a summary of the analysis results contained in `AbstractData` to the
specified IO stream. If no IO stream is provided, it defaults to `stdout`.
Expand All @@ -41,9 +43,11 @@
explaning the issue. In the non-verbose case it will provide just the issue
name.

summarize([io::IO,] issue::AbstractIssue; verbose = true)
summarize([io::IO,] issue::AbstractIssue; name_source = nothing, verbose = true)

This variant allows summarizing a single issue instance of type `AbstractIssue`.
The model tha led to the issue can be provided to `name_source`, it will be used
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
The model tha led to the issue can be provided to `name_source`, it will be used
The model that led to the issue can be provided to `name_source`, it will be used

Copy link
Member

Choose a reason for hiding this comment

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

Why not just ; model::Union{Nothing,JuMP.AbstractModel} = nothing?

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed!
I don't want to type this because I want to have JuMP as a weakdep

to generate the name of variables and constraints in the issue summary.
"""
function summarize end

Expand Down Expand Up @@ -72,17 +76,23 @@
end
end

function summarize(io::IO, issue::AbstractIssue; verbose = true)
function summarize(
io::IO,
issue::AbstractIssue;
name_source = nothing,
verbose = true,
)
if verbose
return _verbose_summarize(io, issue)
return _verbose_summarize(io, issue, name_source)
else
return _summarize(io, issue)
return _summarize(io, issue, name_source)
end
end

function summarize(
io::IO,
issues::Vector{T};
name_source = nothing,
verbose = true,
max_issues = typemax(Int),
) where {T<:AbstractIssue}
Expand All @@ -92,7 +102,7 @@
print(io, "\n\n## List of issues\n\n")
for issue in first(issues, max_issues)
print(io, " * ")
summarize(io, issue, verbose = verbose)
summarize(io, issue, verbose = verbose, name_source = name_source)
print(io, "\n")
end
return
Expand All @@ -102,11 +112,82 @@
return summarize(stdout, data; kwargs...)
end

"""
value(issue::AbstractIssue)

Return the value associated to a particular issue. The value is a number
with a different meaning depending on the type of issue. For example, for
some numerical issues, it can be the coefficient value.
"""
function value(issue::AbstractIssue, ::Nothing)
return value(issue)

Check warning on line 123 in src/ModelAnalyzer.jl

View check run for this annotation

Codecov / codecov/patch

src/ModelAnalyzer.jl#L122-L123

Added lines #L122 - L123 were not covered by tests
end
function value(issue::AbstractIssue, ::MOI.ModelLike)
return value(issue)

Check warning on line 126 in src/ModelAnalyzer.jl

View check run for this annotation

Codecov / codecov/patch

src/ModelAnalyzer.jl#L125-L126

Added lines #L125 - L126 were not covered by tests
end

"""
variable(issue::AbstractIssue)

Return the variable associated to a particular issue.
"""
function variable(issue::AbstractIssue, ::Nothing)
return variable(issue)

Check warning on line 135 in src/ModelAnalyzer.jl

View check run for this annotation

Codecov / codecov/patch

src/ModelAnalyzer.jl#L134-L135

Added lines #L134 - L135 were not covered by tests
end
function variable(issue::AbstractIssue, ::MOI.ModelLike)
return variable(issue)

Check warning on line 138 in src/ModelAnalyzer.jl

View check run for this annotation

Codecov / codecov/patch

src/ModelAnalyzer.jl#L137-L138

Added lines #L137 - L138 were not covered by tests
end

"""
variables(issue::AbstractIssue)

Return the variables associated to a particular issue.
"""
function variables(issue::AbstractIssue, ::Nothing)
return variables(issue)

Check warning on line 147 in src/ModelAnalyzer.jl

View check run for this annotation

Codecov / codecov/patch

src/ModelAnalyzer.jl#L146-L147

Added lines #L146 - L147 were not covered by tests
end
function variables(issue::AbstractIssue, ::MOI.ModelLike)
return variables(issue)

Check warning on line 150 in src/ModelAnalyzer.jl

View check run for this annotation

Codecov / codecov/patch

src/ModelAnalyzer.jl#L149-L150

Added lines #L149 - L150 were not covered by tests
end

"""
constraint(issue::AbstractIssue)

Return the constraint associated to a particular issue.
"""
function constraint(issue::AbstractIssue, ::Nothing)
return constraint(issue)

Check warning on line 159 in src/ModelAnalyzer.jl

View check run for this annotation

Codecov / codecov/patch

src/ModelAnalyzer.jl#L158-L159

Added lines #L158 - L159 were not covered by tests
end
function constraint(issue::AbstractIssue, ::MOI.ModelLike)
return constraint(issue)

Check warning on line 162 in src/ModelAnalyzer.jl

View check run for this annotation

Codecov / codecov/patch

src/ModelAnalyzer.jl#L161-L162

Added lines #L161 - L162 were not covered by tests
end

function _verbose_summarize end
function _summarize end

function _name(ref::MOI.VariableIndex, model::MOI.ModelLike)
name = MOI.get(model, MOI.VariableName(), ref)
if !isempty(name)
return name

Check warning on line 171 in src/ModelAnalyzer.jl

View check run for this annotation

Codecov / codecov/patch

src/ModelAnalyzer.jl#L168-L171

Added lines #L168 - L171 were not covered by tests
end
return "$ref"

Check warning on line 173 in src/ModelAnalyzer.jl

View check run for this annotation

Codecov / codecov/patch

src/ModelAnalyzer.jl#L173

Added line #L173 was not covered by tests
end

function _name(ref::MOI.ConstraintIndex, model::MOI.ModelLike)
name = MOI.get(model, MOI.ConstraintName(), ref)
if !isempty(name)
return name

Check warning on line 179 in src/ModelAnalyzer.jl

View check run for this annotation

Codecov / codecov/patch

src/ModelAnalyzer.jl#L176-L179

Added lines #L176 - L179 were not covered by tests
end
return "$ref"

Check warning on line 181 in src/ModelAnalyzer.jl

View check run for this annotation

Codecov / codecov/patch

src/ModelAnalyzer.jl#L181

Added line #L181 was not covered by tests
end

function _name(ref, ::Nothing)
return "$ref"
end

include("numerical.jl")
include("feasibility.jl")
include("infeasibility.jl")

include("jump.jl")
end
79 changes: 79 additions & 0 deletions src/jump.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import JuMP

# struct JuMPData{T<:AbstractData} <: ModelAnalyzer.AbstractData
# data::T
# model::JuMP.Model
# end

# struct JuMPIssue{T<:AbstractIssue} <: ModelAnalyzer.AbstractIssue
# issue::T
# model::JuMP.Model
# end

function ModelAnalyzer.analyze(
analyzer::T,
model::JuMP.Model;
kwargs...,
) where {T<:ModelAnalyzer.AbstractAnalyzer}
moi_model = JuMP.backend(model)
result = ModelAnalyzer.analyze(analyzer, moi_model; kwargs...)
# return JuMPData(result, model)
return result
end

function ModelAnalyzer._name(ref::MOI.VariableIndex, model::JuMP.Model)
jump_ref = JuMP.VariableRef(model, ref)
name = JuMP.name(jump_ref)
if !isempty(name)
return name

Check warning on line 28 in src/jump.jl

View check run for this annotation

Codecov / codecov/patch

src/jump.jl#L24-L28

Added lines #L24 - L28 were not covered by tests
end
return "$jump_ref"

Check warning on line 30 in src/jump.jl

View check run for this annotation

Codecov / codecov/patch

src/jump.jl#L30

Added line #L30 was not covered by tests
end

function ModelAnalyzer._name(ref::MOI.ConstraintIndex, model::JuMP.Model)
jump_ref = JuMP.constraint_ref_with_index(model, ref)
name = JuMP.name(jump_ref)
if !isempty(name)
return name

Check warning on line 37 in src/jump.jl

View check run for this annotation

Codecov / codecov/patch

src/jump.jl#L33-L37

Added lines #L33 - L37 were not covered by tests
end
return "$jump_ref"

Check warning on line 39 in src/jump.jl

View check run for this annotation

Codecov / codecov/patch

src/jump.jl#L39

Added line #L39 was not covered by tests
end

"""
variable(issue::ModelAnalyzer.AbstractIssue, model::JuMP.Model)

Return the **JuMP** variable reference associated to a particular issue.
"""
function ModelAnalyzer.variable(

Check warning on line 47 in src/jump.jl

View check run for this annotation

Codecov / codecov/patch

src/jump.jl#L47

Added line #L47 was not covered by tests
issue::ModelAnalyzer.AbstractIssue,
model::JuMP.Model,
)
ref = ModelAnalyzer.variable(issue)
return JuMP.VariableRef(model, ref)

Check warning on line 52 in src/jump.jl

View check run for this annotation

Codecov / codecov/patch

src/jump.jl#L51-L52

Added lines #L51 - L52 were not covered by tests
end

"""
variables(issue::ModelAnalyzer.AbstractIssue, model::JuMP.Model)

Return the **JuMP** variable references associated to a particular issue.
"""
function ModelAnalyzer.variables(

Check warning on line 60 in src/jump.jl

View check run for this annotation

Codecov / codecov/patch

src/jump.jl#L60

Added line #L60 was not covered by tests
issue::ModelAnalyzer.AbstractIssue,
model::JuMP.Model,
)
refs = ModelAnalyzer.variables(issue)
return JuMP.VariableRef.(model, refs)

Check warning on line 65 in src/jump.jl

View check run for this annotation

Codecov / codecov/patch

src/jump.jl#L64-L65

Added lines #L64 - L65 were not covered by tests
end

"""
constraint(issue::ModelAnalyzer.AbstractIssue, model::JuMP.Model)

Return the **JuMP** constraint reference associated to a particular issue.
"""
function ModelAnalyzer.constraint(

Check warning on line 73 in src/jump.jl

View check run for this annotation

Codecov / codecov/patch

src/jump.jl#L73

Added line #L73 was not covered by tests
issue::ModelAnalyzer.AbstractIssue,
model::JuMP.Model,
)
ref = ModelAnalyzer.constraint(issue)
return JuMP.constraint_ref_with_index(model, ref)

Check warning on line 78 in src/jump.jl

View check run for this annotation

Codecov / codecov/patch

src/jump.jl#L77-L78

Added lines #L77 - L78 were not covered by tests
end
Loading
Loading