From 72aebcf7ccf4f9f68c7be9ca0de220d21888f135 Mon Sep 17 00:00:00 2001 From: Gennesaret Tjusila Date: Sat, 1 Jun 2024 19:45:31 +0200 Subject: [PATCH 1/9] Event Handler --- src/MOI_wrapper.jl | 2 ++ src/SCIP.jl | 2 ++ src/event_handler.jl | 64 ++++++++++++++++++++++++++++++++++++++++++++ src/scip_data.jl | 6 +++++ 4 files changed, 74 insertions(+) create mode 100644 src/event_handler.jl diff --git a/src/MOI_wrapper.jl b/src/MOI_wrapper.jl index 951ab2d..3f4e0d3 100644 --- a/src/MOI_wrapper.jl +++ b/src/MOI_wrapper.jl @@ -47,6 +47,7 @@ mutable struct Optimizer <: MOI.AbstractOptimizer Dict(), Dict(), Dict(), + Dict(), [], ) @@ -285,6 +286,7 @@ function MOI.empty!(o::Optimizer) Dict(), Dict(), Dict(), + Dict(), [], ) # reapply parameters diff --git a/src/SCIP.jl b/src/SCIP.jl index b0b8070..5a77f7a 100644 --- a/src/SCIP.jl +++ b/src/SCIP.jl @@ -43,4 +43,6 @@ include("convenience.jl") # warn about rewrite include("compat.jl") +# Event handler +include("event_handler.jl") end diff --git a/src/event_handler.jl b/src/event_handler.jl new file mode 100644 index 0000000..9cc1cd5 --- /dev/null +++ b/src/event_handler.jl @@ -0,0 +1,64 @@ +#= +User have to implement +- A struct that inherit AbstractEventHandler +- An eventexec function +=# +""" +Abstract eventhander +""" +abstract type AbstractEventHandler end + +function eventexec end; + +function _eventexec( + scip::Ptr{SCIP_}, + eventhdlr::Ptr{SCIP_Eventhdlr}, + event::Ptr{SCIP_Event}, + eventdata::Ptr{SCIP_EventData} +) + # Get Julia object out of eventhandler data + data::Ptr{SCIP_EventData} = SCIPeventhdlrGetData(eventhdlr) + event = unsafe_pointer_to_objref(data) + #call user method + eventexec(event) + return SCIP_OKAY +end +function include_event_handler( + scip::Ptr{SCIP_}, + eventhdlrs::Dict{Any,Ptr{SCIP_Eventhdlr}}, + event_handler::EVENTHDLR; + name = "", + desc = "" + ) where {EVENTHDLR <: AbstractEventHandler} + _eventexec = @cfunction( + _eventexec, + SCIP_RETCODE, + ( + Ptr{SCIP_}, + Ptr{SCIP_Eventhdlr}, + Ptr{SCIP_Event}, + Ptr{SCIP_EventData} + ) + ) + c_handler = Ref{Ptr{SCIP_Eventhdlr}}(C_NULL) + event_handler_data = pointer_from_objref(event_handler) + + if name == "" + name = "__eventhdlr__$(length(eventhdlrs))" + end + + @SCIP_CALL SCIPincludeEventhdlrBasic( + scip, + c_handler, + name, + desc, + _eventexec, + event_handler_data + ) + println("hello"*string(c_handler[])) + @assert c_handler[] != C_NULL + + #Persist in scip store against GC + eventhdlrs[event_handler] = c_handler[] + +end diff --git a/src/scip_data.jl b/src/scip_data.jl index 1f21204..6b9a022 100644 --- a/src/scip_data.jl +++ b/src/scip_data.jl @@ -34,6 +34,7 @@ mutable struct SCIPData scip::Ref{Ptr{SCIP_}} vars::Dict{VarRef,Ref{Ptr{SCIP_VAR}}} conss::Dict{ConsRef,Ref{Ptr{SCIP_CONS}}} + var_count::Int64 cons_count::Int64 @@ -47,7 +48,12 @@ mutable struct SCIPData # Map from user-defined types (keys are <: AbstractSeparator) to the # corresponding SCIP objects. sepas::Dict{Any,Ptr{SCIP_SEPA}} + + # Map from user-defined types (keys are <: AbstractEventHandler) + # to the corresponding SCIP objects. + eventhdlrs::Dict{Any,Ptr{SCIP_Eventhdlr}} + # User-defined cut selectors and branching rules cutsel_storage::Dict{Any,Ptr{SCIP_CUTSEL}} branchrule_storage::Dict{Any,Ptr{SCIP_BRANCHRULE}} From d5be642599dd90c86d92b9c09faa4475552c27ed Mon Sep 17 00:00:00 2001 From: Gennesaret Tjusila Date: Sat, 1 Jun 2024 19:47:53 +0200 Subject: [PATCH 2/9] Remove println left by mistake --- src/event_handler.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/event_handler.jl b/src/event_handler.jl index 9cc1cd5..02dc422 100644 --- a/src/event_handler.jl +++ b/src/event_handler.jl @@ -55,7 +55,7 @@ function include_event_handler( _eventexec, event_handler_data ) - println("hello"*string(c_handler[])) + @assert c_handler[] != C_NULL #Persist in scip store against GC From b259353ff01b15608577049ec3da21e6b47899c3 Mon Sep 17 00:00:00 2001 From: Gennesaret Tjusila Date: Thu, 25 Jul 2024 16:50:47 +0200 Subject: [PATCH 3/9] Added TestCases --- src/event_handler.jl | 50 ++++++++++++++++------------ test/eventhdlr_support.jl | 70 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 21 deletions(-) create mode 100644 test/eventhdlr_support.jl diff --git a/src/event_handler.jl b/src/event_handler.jl index 02dc422..ed1cbf2 100644 --- a/src/event_handler.jl +++ b/src/event_handler.jl @@ -3,10 +3,8 @@ User have to implement - A struct that inherit AbstractEventHandler - An eventexec function =# -""" -Abstract eventhander -""" -abstract type AbstractEventHandler end + +abstract type AbstractEventhdlr end function eventexec end; @@ -14,34 +12,32 @@ function _eventexec( scip::Ptr{SCIP_}, eventhdlr::Ptr{SCIP_Eventhdlr}, event::Ptr{SCIP_Event}, - eventdata::Ptr{SCIP_EventData} + eventdata::Ptr{SCIP_EventData}, ) # Get Julia object out of eventhandler data data::Ptr{SCIP_EventData} = SCIPeventhdlrGetData(eventhdlr) event = unsafe_pointer_to_objref(data) + #call user method eventexec(event) return SCIP_OKAY end + function include_event_handler( scip::Ptr{SCIP_}, eventhdlrs::Dict{Any,Ptr{SCIP_Eventhdlr}}, event_handler::EVENTHDLR; - name = "", - desc = "" - ) where {EVENTHDLR <: AbstractEventHandler} + name="", + desc="", +) where {EVENTHDLR<:AbstractEventhdlr} _eventexec = @cfunction( _eventexec, SCIP_RETCODE, - ( - Ptr{SCIP_}, - Ptr{SCIP_Eventhdlr}, - Ptr{SCIP_Event}, - Ptr{SCIP_EventData} - ) + (Ptr{SCIP_}, Ptr{SCIP_Eventhdlr}, Ptr{SCIP_Event}, Ptr{SCIP_EventData}) ) - c_handler = Ref{Ptr{SCIP_Eventhdlr}}(C_NULL) - event_handler_data = pointer_from_objref(event_handler) + + eventhdlrptr = Ref{Ptr{SCIP_Eventhdlr}}(C_NULL) + eventhdlr = pointer_from_objref(event_handler) if name == "" name = "__eventhdlr__$(length(eventhdlrs))" @@ -49,16 +45,28 @@ function include_event_handler( @SCIP_CALL SCIPincludeEventhdlrBasic( scip, - c_handler, + eventhdlrptr, name, desc, _eventexec, - event_handler_data + eventhdlr, ) - - @assert c_handler[] != C_NULL + @assert eventhdlrptr[] != C_NULL + println("EventhdlrPtr", eventhdlrptr[]) #Persist in scip store against GC - eventhdlrs[event_handler] = c_handler[] + eventhdlrs[event_handler] = eventhdlrptr[] +end +function catch_event( + scip::Ptr{SCIP_}, + eventtype::SCIP_EVENTTYPE, + eventhdlrs::Dict{Any,Ptr{SCIP_Eventhdlr}}, + eventhdlr::EVENTHDLR, +) where {EVENTHDLR<:AbstractEventhdlr} + eventhdlrptr = eventhdlrs[eventhdlr] + println(scip) + println("NewPointer", eventhdlrptr) + @SCIP_CALL SCIPcatchEvent(scip, eventtype, eventhdlrptr, C_NULL, C_NULL) + println("Event_caught") end diff --git a/test/eventhdlr_support.jl b/test/eventhdlr_support.jl new file mode 100644 index 0000000..5bd36b8 --- /dev/null +++ b/test/eventhdlr_support.jl @@ -0,0 +1,70 @@ +using SCIP +import MathOptInterface as MOI + +module FirstLPEventTest + +using SCIP + +mutable struct FirstLPEvent <: SCIP.AbstractEventhdlr + scip::SCIP.SCIPData + firstlpobj::Float64 +end + +function SCIP.eventexec(event::FirstLPEvent) + scip = event.scip + event.firstlpobj = SCIP.SCIPgetLPObjval(scip) +end + +end + +@testset "Try To Listen To First LP Solve" begin + # create an empty problem + optimizer = SCIP.Optimizer() + inner = optimizer.inner + sepa_set_scip_parameters((par, val) -> SCIP.set_parameter(inner, par, val)) + + # add variables + x, y = MOI.add_variables(optimizer, 2) + MOI.add_constraint(optimizer, x, MOI.ZeroOne()) + MOI.add_constraint(optimizer, y, MOI.ZeroOne()) + + # add constraint: x + y ≤ 1.5 + MOI.add_constraint( + optimizer, + MOI.ScalarAffineFunction( + MOI.ScalarAffineTerm.([1.0, 1.0], [x, y]), + 0.0, + ), + MOI.LessThan(1.5), + ) + + # maximize x + y + MOI.set( + optimizer, + MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(), + MOI.ScalarAffineFunction( + MOI.ScalarAffineTerm.([1.0, 1.0], [x, y]), + 0.0, + ), + ) + MOI.set(optimizer, MOI.ObjectiveSense(), MOI.MAX_SENSE) + print(inner.scip[]) + # add the separator + eventhdlr = FirstLPEventTest.FirstLPEvent(inner, -1.0) + SCIP.include_event_handler(inner.scip[], inner.eventhdlrs, eventhdlr) + SCIP.catch_event( + inner.scip[], + SCIP.SCIP_EVENTTYPE_FIRSTLPSOLVED, + inner.eventhdlrs, + eventhdlr, + ) + + # solve the problem + SCIP.@SCIP_CALL SCIP.SCIPsolve(inner.scip[]) + + # test if the event handler worked + @test eventhdlr.firstlpobj == 1.5 + + # free the problem + finalize(inner) +end \ No newline at end of file From acd3d89cd17e8e3eec777c1fb76a4585c5f05726 Mon Sep 17 00:00:00 2001 From: Gennesaret Tjusila Date: Thu, 25 Jul 2024 17:44:20 +0200 Subject: [PATCH 4/9] Added Feature Event Handler --- src/event_handler.jl | 5 ++--- test/{eventhdlr_support.jl => eventhdlr.jl} | 24 +++++++++++++-------- test/runtests.jl | 5 +++++ 3 files changed, 22 insertions(+), 12 deletions(-) rename test/{eventhdlr_support.jl => eventhdlr.jl} (73%) diff --git a/src/event_handler.jl b/src/event_handler.jl index ed1cbf2..a03fd31 100644 --- a/src/event_handler.jl +++ b/src/event_handler.jl @@ -64,9 +64,8 @@ function catch_event( eventhdlrs::Dict{Any,Ptr{SCIP_Eventhdlr}}, eventhdlr::EVENTHDLR, ) where {EVENTHDLR<:AbstractEventhdlr} + @assert SCIPgetStage(scip) != SCIP_STAGE_INIT + @assert SCIPgetStage(scip) != SCIP_STAGE_PROBLEM eventhdlrptr = eventhdlrs[eventhdlr] - println(scip) - println("NewPointer", eventhdlrptr) @SCIP_CALL SCIPcatchEvent(scip, eventtype, eventhdlrptr, C_NULL, C_NULL) - println("Event_caught") end diff --git a/test/eventhdlr_support.jl b/test/eventhdlr.jl similarity index 73% rename from test/eventhdlr_support.jl rename to test/eventhdlr.jl index 5bd36b8..adc44c1 100644 --- a/test/eventhdlr_support.jl +++ b/test/eventhdlr.jl @@ -11,12 +11,15 @@ mutable struct FirstLPEvent <: SCIP.AbstractEventhdlr end function SCIP.eventexec(event::FirstLPEvent) - scip = event.scip - event.firstlpobj = SCIP.SCIPgetLPObjval(scip) + # Only consider the root node + current_node = SCIP.SCIPgetFocusNode(event.scip) + depth = SCIP.SCIPnodeGetDepth(current_node) + if depth == 0 + scip = event.scip + event.firstlpobj = SCIP.SCIPgetLPObjval(scip) + end end - end - @testset "Try To Listen To First LP Solve" begin # create an empty problem optimizer = SCIP.Optimizer() @@ -38,20 +41,23 @@ end MOI.LessThan(1.5), ) - # maximize x + y + # minimize -x - y MOI.set( optimizer, MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(), MOI.ScalarAffineFunction( - MOI.ScalarAffineTerm.([1.0, 1.0], [x, y]), + MOI.ScalarAffineTerm.([-1.0, -1.0], [x, y]), 0.0, ), ) - MOI.set(optimizer, MOI.ObjectiveSense(), MOI.MAX_SENSE) + MOI.set(optimizer, MOI.ObjectiveSense(), MOI.MIN_SENSE) print(inner.scip[]) # add the separator - eventhdlr = FirstLPEventTest.FirstLPEvent(inner, -1.0) + eventhdlr = FirstLPEventTest.FirstLPEvent(inner, 10) SCIP.include_event_handler(inner.scip[], inner.eventhdlrs, eventhdlr) + + SCIP.@SCIP_CALL SCIP.SCIPtransformProb(inner) + SCIP.catch_event( inner.scip[], SCIP.SCIP_EVENTTYPE_FIRSTLPSOLVED, @@ -63,7 +69,7 @@ end SCIP.@SCIP_CALL SCIP.SCIPsolve(inner.scip[]) # test if the event handler worked - @test eventhdlr.firstlpobj == 1.5 + @test eventhdlr.firstlpobj != 10 # free the problem finalize(inner) diff --git a/test/runtests.jl b/test/runtests.jl index 06db0bd..ff5ad40 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -43,6 +43,11 @@ include("sepa_support.jl") @testset "separators" begin include("sepa.jl") end + +@testset "event handlers" begin + include("eventhdlr.jl") +end + @testset "cut callbacks" begin include("cutcallback.jl") end From b1c7eddc81a9e686db27cdf593ccdf43a5f9a62b Mon Sep 17 00:00:00 2001 From: Gennesaret Tjusila Date: Thu, 25 Jul 2024 17:53:13 +0200 Subject: [PATCH 5/9] Removed Unnessecary print statement --- src/event_handler.jl | 1 - test/eventhdlr.jl | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/event_handler.jl b/src/event_handler.jl index a03fd31..373a37a 100644 --- a/src/event_handler.jl +++ b/src/event_handler.jl @@ -53,7 +53,6 @@ function include_event_handler( ) @assert eventhdlrptr[] != C_NULL - println("EventhdlrPtr", eventhdlrptr[]) #Persist in scip store against GC eventhdlrs[event_handler] = eventhdlrptr[] end diff --git a/test/eventhdlr.jl b/test/eventhdlr.jl index adc44c1..02de875 100644 --- a/test/eventhdlr.jl +++ b/test/eventhdlr.jl @@ -51,7 +51,7 @@ end ), ) MOI.set(optimizer, MOI.ObjectiveSense(), MOI.MIN_SENSE) - print(inner.scip[]) + # add the separator eventhdlr = FirstLPEventTest.FirstLPEvent(inner, 10) SCIP.include_event_handler(inner.scip[], inner.eventhdlrs, eventhdlr) From 38b8a6272d48bede5ae9862a308ee40476abd18a Mon Sep 17 00:00:00 2001 From: Gennesaret Tjusila Date: Thu, 25 Jul 2024 23:20:15 +0200 Subject: [PATCH 6/9] Format Code and added comments --- src/event_handler.jl | 68 +++++++++++++++++++++++++++++++++----------- src/scip_data.jl | 3 +- test/eventhdlr.jl | 22 ++++++++------ 3 files changed, 65 insertions(+), 28 deletions(-) diff --git a/src/event_handler.jl b/src/event_handler.jl index 373a37a..ac16992 100644 --- a/src/event_handler.jl +++ b/src/event_handler.jl @@ -1,13 +1,30 @@ -#= -User have to implement -- A struct that inherit AbstractEventHandler -- An eventexec function -=# - +# Wrapper for implementing event handlers in SCIP. +# Before using please familiaze yourself with https://scipopt.org/doc/html/EVENT.php +# +# The basic idea here is the same as with the separator wrappers. First, you need +# to define a structure that implements the abstract type `AbstractEventhdlr`. +# Second you should implement the function `eventexec` where the argument is an +# instance of your event handler structure. Third, you should at runtime instantiate +# the structure and call `include_event_handler` to register the event handler with SCIP. +# +# See eventhdlr.jl in the test folder for an example. +# abstract type AbstractEventhdlr end -function eventexec end; +""" +This is a virtual function that must be implemented by the user. Its Only +argument is the event handler object. +""" +function eventexec(event::T) where {T<:AbstractEventhdlr} + error("eventexec not implemented for type $(T)") +end + +""" +This is the function that will be converted to a C function. It signature +matches the one given in the SCIP documentation for SCIP_DECL_EVENTEXEC. +Only the eventhdlr object is passed to the function which is user defined. +""" function _eventexec( scip::Ptr{SCIP_}, eventhdlr::Ptr{SCIP_Eventhdlr}, @@ -20,12 +37,24 @@ function _eventexec( #call user method eventexec(event) + return SCIP_OKAY end +""" + include_event_handler(scipd::SCIP.SCIPData, event_handler::EVENTHDLR; name="", desc="") + +Include the event handler in SCIP. WARNING! In contrast to the separator wrapper you only need to +pass the SCIPData rather than the SCIP pointer and dictionary. + +# Arguments +- scipd::SCIP.SCIPData: The SCIPData object +- event_handler::EVENTHDLR: The event handler object +- name::String: The name of the event handler +- desc::String: The description of the event handler +""" function include_event_handler( - scip::Ptr{SCIP_}, - eventhdlrs::Dict{Any,Ptr{SCIP_Eventhdlr}}, + scipd::SCIP.SCIPData, event_handler::EVENTHDLR; name="", desc="", @@ -44,7 +73,7 @@ function include_event_handler( end @SCIP_CALL SCIPincludeEventhdlrBasic( - scip, + scipd.scip[], eventhdlrptr, name, desc, @@ -54,17 +83,22 @@ function include_event_handler( @assert eventhdlrptr[] != C_NULL #Persist in scip store against GC - eventhdlrs[event_handler] = eventhdlrptr[] + scipd.eventhdlrs[event_handler] = eventhdlrptr[] end +""" + catch_event(scipd::SCIP.SCIPData, eventtype::SCIP_EVENTTYPE, eventhdlr::EVENTHDLR) + +Catch an event in SCIP. This function is a wrapper around the SCIPcatchEvent function. +Warning! This function should only be called after the SCIP has been transformed. +""" function catch_event( - scip::Ptr{SCIP_}, + scipd::SCIP.SCIPData, eventtype::SCIP_EVENTTYPE, - eventhdlrs::Dict{Any,Ptr{SCIP_Eventhdlr}}, eventhdlr::EVENTHDLR, ) where {EVENTHDLR<:AbstractEventhdlr} - @assert SCIPgetStage(scip) != SCIP_STAGE_INIT - @assert SCIPgetStage(scip) != SCIP_STAGE_PROBLEM - eventhdlrptr = eventhdlrs[eventhdlr] - @SCIP_CALL SCIPcatchEvent(scip, eventtype, eventhdlrptr, C_NULL, C_NULL) + @assert SCIPgetStage(scipd) != SCIP_STAGE_INIT + @assert SCIPgetStage(scipd) != SCIP_STAGE_PROBLEM + eventhdlrptr = scipd.eventhdlrs[eventhdlr] + @SCIP_CALL SCIPcatchEvent(scipd, eventtype, eventhdlrptr, C_NULL, C_NULL) end diff --git a/src/scip_data.jl b/src/scip_data.jl index 6b9a022..e7c9e85 100644 --- a/src/scip_data.jl +++ b/src/scip_data.jl @@ -48,12 +48,11 @@ mutable struct SCIPData # Map from user-defined types (keys are <: AbstractSeparator) to the # corresponding SCIP objects. sepas::Dict{Any,Ptr{SCIP_SEPA}} - # Map from user-defined types (keys are <: AbstractEventHandler) # to the corresponding SCIP objects. eventhdlrs::Dict{Any,Ptr{SCIP_Eventhdlr}} - + # User-defined cut selectors and branching rules cutsel_storage::Dict{Any,Ptr{SCIP_CUTSEL}} branchrule_storage::Dict{Any,Ptr{SCIP_BRANCHRULE}} diff --git a/test/eventhdlr.jl b/test/eventhdlr.jl index 02de875..9cd6a72 100644 --- a/test/eventhdlr.jl +++ b/test/eventhdlr.jl @@ -1,8 +1,10 @@ +# A simple testcase to test the event handler functionality. +# It is assumed that test/sepa_support.jl is already included using SCIP import MathOptInterface as MOI module FirstLPEventTest - +# A simple event handler that stores the objective value of the first LP solve at the root node using SCIP mutable struct FirstLPEvent <: SCIP.AbstractEventhdlr @@ -52,18 +54,20 @@ end ) MOI.set(optimizer, MOI.ObjectiveSense(), MOI.MIN_SENSE) - # add the separator + # add eventhandler eventhdlr = FirstLPEventTest.FirstLPEvent(inner, 10) - SCIP.include_event_handler(inner.scip[], inner.eventhdlrs, eventhdlr) + SCIP.include_event_handler( + inner, + eventhdlr; + name="firstlp", + desc="Store the objective value of the first LP solve at the root node", + ) + # transform the problem into SCIP SCIP.@SCIP_CALL SCIP.SCIPtransformProb(inner) - SCIP.catch_event( - inner.scip[], - SCIP.SCIP_EVENTTYPE_FIRSTLPSOLVED, - inner.eventhdlrs, - eventhdlr, - ) + # catch the event. Again this can only be done after the problem is transformed + SCIP.catch_event(inner, SCIP.SCIP_EVENTTYPE_FIRSTLPSOLVED, eventhdlr) # solve the problem SCIP.@SCIP_CALL SCIP.SCIPsolve(inner.scip[]) From 56e1736fb7b22d3c872e7af15b4a443ecfd054fb Mon Sep 17 00:00:00 2001 From: Gennesaret Tjusila Date: Thu, 25 Jul 2024 23:26:37 +0200 Subject: [PATCH 7/9] RUn Formatter Again --- test/eventhdlr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/eventhdlr.jl b/test/eventhdlr.jl index 9cd6a72..aa2b764 100644 --- a/test/eventhdlr.jl +++ b/test/eventhdlr.jl @@ -77,4 +77,4 @@ end # free the problem finalize(inner) -end \ No newline at end of file +end From 67ad1693b5df67aa4eb535cf1de3304807854784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Fri, 26 Jul 2024 10:53:11 +0200 Subject: [PATCH 8/9] Update test/eventhdlr.jl --- test/eventhdlr.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/eventhdlr.jl b/test/eventhdlr.jl index aa2b764..c10d6e7 100644 --- a/test/eventhdlr.jl +++ b/test/eventhdlr.jl @@ -22,6 +22,7 @@ function SCIP.eventexec(event::FirstLPEvent) end end end + @testset "Try To Listen To First LP Solve" begin # create an empty problem optimizer = SCIP.Optimizer() From 2a468a51660d9192dcf3d002b37404d2381b3461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Fri, 26 Jul 2024 10:53:43 +0200 Subject: [PATCH 9/9] Apply suggestions from code review --- test/eventhdlr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/eventhdlr.jl b/test/eventhdlr.jl index c10d6e7..df5868d 100644 --- a/test/eventhdlr.jl +++ b/test/eventhdlr.jl @@ -23,7 +23,7 @@ function SCIP.eventexec(event::FirstLPEvent) end end -@testset "Try To Listen To First LP Solve" begin +@testset "Listen to first LP solve" begin # create an empty problem optimizer = SCIP.Optimizer() inner = optimizer.inner