Skip to content

Commit fe76b33

Browse files
authored
Add new attribute NodeLimit (#2552)
1 parent 3c10947 commit fe76b33

File tree

5 files changed

+53
-0
lines changed

5 files changed

+53
-0
lines changed

docs/src/manual/models.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,5 @@ The following attributes are available:
105105
* [`TimeLimitSec`](@ref)
106106
* [`ObjectiveLimit`](@ref)
107107
* [`SolutionLimit`](@ref)
108+
* [`NodeLimit`](@ref)
108109
* [`AutomaticDifferentiationBackend`](@ref)

docs/src/reference/models.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ Silent
8181
TimeLimitSec
8282
ObjectiveLimit
8383
SolutionLimit
84+
NodeLimit
8485
RawOptimizerAttribute
8586
NumberOfThreads
8687
RawSolver

docs/src/tutorials/implementing.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@ method for each attribute.
335335
| [`TimeLimitSec`](@ref) | Yes | Yes | Yes |
336336
| [`ObjectiveLimit`](@ref) | Yes | Yes | Yes |
337337
| [`SolutionLimit`](@ref) | Yes | Yes | Yes |
338+
| [`NodeLimit`](@ref) | Yes | Yes | Yes |
338339
| [`RawOptimizerAttribute`](@ref) | Yes | Yes | Yes |
339340
| [`NumberOfThreads`](@ref) | Yes | Yes | Yes |
340341
| [`AbsoluteGapTolerance`](@ref) | Yes | Yes | Yes |

src/Test/test_attribute.jl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,32 @@ function setup_test(
252252
return
253253
end
254254

255+
function test_attribute_NodeLimit(model::MOI.AbstractOptimizer, ::Config)
256+
@requires MOI.supports(model, MOI.NodeLimit())
257+
# Get the current value to restore it at the end of the test
258+
value = MOI.get(model, MOI.NodeLimit())
259+
MOI.set(model, MOI.NodeLimit(), 3)
260+
@test MOI.get(model, MOI.NodeLimit()) == 3
261+
MOI.set(model, MOI.NodeLimit(), nothing)
262+
@test MOI.get(model, MOI.NodeLimit()) === nothing
263+
MOI.set(model, MOI.NodeLimit(), 1)
264+
@test MOI.get(model, MOI.NodeLimit()) == 1
265+
MOI.set(model, MOI.NodeLimit(), value)
266+
_test_attribute_value_type(model, MOI.NodeLimit())
267+
return
268+
end
269+
270+
test_attribute_NodeLimit(::MOI.ModelLike, ::Config) = nothing
271+
272+
function setup_test(
273+
::typeof(test_attribute_NodeLimit),
274+
model::MOIU.MockOptimizer,
275+
::Config,
276+
)
277+
MOI.set(model, MOI.NodeLimit(), nothing)
278+
return
279+
end
280+
255281
"""
256282
test_attribute_AbsoluteGapTolerance(model::MOI.AbstractOptimizer, config::Config)
257283

src/attributes.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,30 @@ struct SolutionLimit <: AbstractOptimizerAttribute end
899899

900900
attribute_value_type(::SolutionLimit) = Union{Nothing,Int}
901901

902+
"""
903+
NodeLimit()
904+
905+
An optimizer attribute for setting a limit on the number of branch-and-bound
906+
nodes explored by a mixed-integer program (MIP) solver.
907+
908+
## Default values
909+
910+
The provided limit must be a `Union{Nothing,Int}`.
911+
912+
When `set` to `nothing`, the limit reverts to the solver's default.
913+
914+
The default value is `nothing`.
915+
916+
## Termination criteria
917+
918+
The solver may stop when the [`NodeCount`](@ref) is larger than or equal to
919+
the `NodeLimit`. If stopped because of this attribute, the
920+
[`TerminationStatus`](@ref) must be `NODE_LIMIT`.
921+
"""
922+
struct NodeLimit <: AbstractOptimizerAttribute end
923+
924+
attribute_value_type(::NodeLimit) = Union{Nothing,Int}
925+
902926
"""
903927
RawOptimizerAttribute(name::String)
904928

0 commit comments

Comments
 (0)