Skip to content

Commit 69b67f8

Browse files
committed
Merge branch 'master' into rs/conshdlr
2 parents f86c15c + 670d761 commit 69b67f8

15 files changed

+285
-172
lines changed

.appveyor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ notifications:
1818

1919
install:
2020
- ps: iex ((new-object net.webclient).DownloadString("https://raw.githubusercontent.com/JuliaCI/Appveyor.jl/version-1/bin/install.ps1"))
21-
- ps: wget http://scip.zib.de/download/release/SCIPOptSuite-6.0.1-win64-VS15.exe -outfile scipopt-installer.exe
21+
- ps: wget http://scip.zib.de/download/release/SCIPOptSuite-6.0.2-win64-VS15.exe -outfile scipopt-installer.exe
2222
- scipopt-installer.exe /S /D=%SCIPOPTDIR%
2323

2424
build_script:

.travis.yml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ addons:
2525
- libstdc++6
2626
- zlib1g
2727
before_install:
28-
- export VERSION=6.0.1
29-
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then wget http://scip.zib.de/download/release/SCIPOptSuite-$VERSION-Linux.deb; fi
30-
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo dpkg -i SCIPOptSuite-$VERSION-Linux.deb; fi
28+
- export VERSION=6.0.2
29+
- export DEBFILE=SCIPOptSuite-$VERSION-Linux-Ub1604.deb
30+
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then wget http://scip.zib.de/download/release/$DEBFILE; fi
31+
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo dpkg -i $DEBFILE ; fi
3132
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then wget http://scip.zib.de/download/release/scipoptsuite-$VERSION.tgz; fi
3233
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then tar -xf scipoptsuite-$VERSION.tgz && cd scipoptsuite-$VERSION; fi
3334
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then mkdir build && cd build && cmake -D CMAKE_BUILD_TYPE=Release -D ZIMPL=OFF -D GCG=OFF -D BUILD_TESTING=OFF -D CMAKE_INSTALL_PREFIX=../install ..; fi
@@ -37,6 +38,8 @@ before_install:
3738
# script:
3839
# - julia -e 'using Pkg; Pkg.clone(pwd()); Pkg.build("SCIP"); Pkg.test("SCIP"; coverage=true)'
3940
jobs:
41+
allow_failures:
42+
- stage: "MINLPTests"
4043
include:
4144
- stage: "MINLPTests"
4245
julia: 1.0

NEWS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# News
22

3+
## v0.9.0
4+
5+
- support MOI v0.9 [#126](https://github.com/SCIP-Interfaces/SCIP.jl/pull/126)
6+
- SCIP-specific MOI indicator constraint replaced by the new MOI definition [#121](https://github.com/SCIP-Interfaces/SCIP.jl/pull/121)
7+
38
## v0.8.0
49

510
- support Windows [#122](https://github.com/SCIP-Interfaces/SCIP.jl/pull/122)

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "SCIP"
22
uuid = "82193955-e24f-5292-bf16-6f2c5261a85f"
3-
version = "0.8.0"
3+
version = "0.9.0"
44

55
[deps]
66
CEnum = "fa961155-64e5-5f13-b03f-caf6b980ea82"
@@ -9,7 +9,7 @@ MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee"
99

1010
[compat]
1111
CEnum = "^0.1.0"
12-
MathOptInterface = "^0.8.4"
12+
MathOptInterface = "^0.9.0"
1313
julia = "^1.0.0"
1414

1515
[extras]

src/MOI_wrapper.jl

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,53 @@ MOI.get(::Optimizer, ::MOI.SolverName) = "SCIP"
103103

104104
MOIU.supports_default_copy_to(model::Optimizer, copy_names::Bool) = !copy_names
105105

106-
struct Param <: MOI.AbstractOptimizerAttribute
107-
name::String
106+
# Keep SCIP-specific alias for backwards-compatibility.
107+
const Param = MOI.RawParameter
108+
109+
function MOI.get(o::Optimizer, param::MOI.RawParameter)
110+
return get_parameter(o.mscip, param.name)
108111
end
109-
function MOI.set(o::Optimizer, param::Param, value)
112+
113+
function MOI.set(o::Optimizer, param::MOI.RawParameter, value)
110114
o.params[param.name] = value
111115
set_parameter(o.mscip, param.name, value)
112116
return nothing
113117
end
114118

119+
MOI.supports(o::Optimizer, ::MOI.Silent) = true
120+
121+
function MOI.get(o::Optimizer, ::MOI.Silent)
122+
return MOI.get(o, MOI.RawParameter("display/verblevel")) == 0
123+
end
124+
125+
function MOI.set(o::Optimizer, ::MOI.Silent, value)
126+
param = MOI.RawParameter("display/verblevel")
127+
if value
128+
MOI.set(o, param, 0) # no output at all
129+
else
130+
MOI.set(o, param, 4) # default level
131+
end
132+
end
133+
134+
MOI.supports(o::Optimizer, ::MOI.TimeLimitSec) = true
135+
136+
function MOI.get(o::Optimizer, ::MOI.TimeLimitSec)
137+
raw_value = MOI.get(o, MOI.RawParameter("limits/time"))
138+
if raw_value == SCIPinfinity(o)
139+
return nothing
140+
else
141+
return raw_value
142+
end
143+
end
144+
145+
function MOI.set(o::Optimizer, ::MOI.TimeLimitSec, value)
146+
if value == nothing
147+
MOI.set(o, MOI.RawParameter("limits/time"), SCIPinfinity(o))
148+
else
149+
MOI.set(o, MOI.RawParameter("limits/time"), value)
150+
end
151+
end
152+
115153
## model creation, query and modification
116154

117155
function MOI.is_empty(o::Optimizer)

src/MOI_wrapper/indicator_constraints.jl

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,26 @@
11
# Indicator constraints
22

3-
"""
4-
Set of (x,y) that satisfy the indicator constraint:
3+
MOI.supports_constraint(::Optimizer, ::Type{<:MOI.VectorAffineFunction}, ::Type{<:MOI.IndicatorSet{MOI.ACTIVATE_ON_ONE, <:MOI.LessThan}}) = true
54

6-
y ∈ 𝔹, y = 1 ==> a^T x ≤ rhs
7-
8-
"""
9-
struct IndicatorSet{T <: Real} <: MOI.AbstractVectorSet
10-
a::Vector{T}
11-
rhs::T
12-
end
13-
14-
MOI.dimension(idset::IndicatorSet) = length(idset.a) + 1
15-
16-
MOI.supports_constraint(::Optimizer, ::Type{VECTOR}, ::Type{IS}) where {IS <: IndicatorSet{<:AbstractFloat}} = true
17-
18-
function MOI.add_constraint(o::Optimizer, func::VECTOR, set::IndicatorSet{Float64})
19-
length(func.variables) == length(set.a) + 1 || throw(DimensionMismatch("Indicator set and VectorOfVariables length mismatch"))
5+
function MOI.add_constraint(o::Optimizer, func::MOI.VectorAffineFunction{T}, set::MOI.IndicatorSet{MOI.ACTIVATE_ON_ONE, LT}) where {T<:Real, LT<:MOI.LessThan}
206
allow_modification(o)
21-
y = VarRef(func.variables[1].value)
22-
x = [VarRef(vi.value) for vi in func.variables[2:end]]
23-
24-
cr = add_indicator_constraint(o.mscip, y, x, set.a, set.rhs)
25-
ci = CI{VECTOR, IndicatorSet{Float64}}(cr.val)
7+
first_index_terms = [v.scalar_term for v in func.terms if v.output_index == 1]
8+
scalar_index_terms = [v.scalar_term for v in func.terms if v.output_index != 1]
9+
length(first_index_terms) == 1 || error("There should be exactly one term in output_index 1, found $(length(first_index_terms))")
10+
y = VarRef(first_index_terms[1].variable_index.value)
11+
x = [VarRef(vi.variable_index.value) for vi in scalar_index_terms]
12+
a = [vi.coefficient for vi in scalar_index_terms]
13+
14+
cr = add_indicator_constraint(o.mscip, y, x, a, MOI.constant(set.set))
15+
ci = CI{MOI.VectorAffineFunction{T}, MOI.IndicatorSet{MOI.ACTIVATE_ON_ONE, LT}}(cr.val)
2616
register!(o, ci)
2717
register!(o, cons(o, ci), cr)
2818
return ci
2919
end
3020

31-
function MOI.delete(o::Optimizer, ci::CI{VECTOR, IndicatorSet{Float64}})
21+
function MOI.delete(o::Optimizer, ci::CI{MOI.VectorAffineFunction{T}, MOI.IndicatorSet{MOI.ACTIVATE_ON_ONE, LT}}) where {T<:Real, LT<:MOI.LessThan}
3222
allow_modification(o)
33-
delete!(o.constypes[VECTOR, IndicatorSet{Float64}], ConsRef(ci.value))
23+
delete!(o.constypes[MOI.VectorAffineFunction{T}, MOI.IndicatorSet{MOI.ACTIVATE_ON_ONE, LT}], ConsRef(ci.value))
3424
delete!(o.reference, cons(o, ci))
3525
delete(o.mscip, ConsRef(ci.value))
3626
return nothing

src/MOI_wrapper/results.jl

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ function MOI.get(o::Optimizer, ::MOI.ResultCount)
3535
return SCIPgetNSols(o)
3636
end
3737

38+
function MOI.get(o::Optimizer, ::MOI.RawStatusString)
39+
return String(CEnum.enum_name(SCIPgetStatus(o)))
40+
end
41+
3842
"Make sure that SCIP is currently in one of the allowed stages."
3943
function assert_stage(o::Optimizer, stages)
4044
stage = SCIPgetStage(o)
@@ -60,24 +64,28 @@ end
6064
"Make sure that: TRANSFORMED ≤ stage ≤ SOLVED."
6165
assert_after_prob(o::Optimizer) = assert_stage(o, SCIP_Stage.(3:10))
6266

63-
function MOI.get(o::Optimizer, ::MOI.ObjectiveValue)
67+
function MOI.get(o::Optimizer, attr::MOI.ObjectiveValue)
6468
assert_solved(o)
65-
return SCIPgetSolOrigObj(o, SCIPgetBestSol(o))
69+
sols = unsafe_wrap(Array{Ptr{SCIP_SOL}}, SCIPgetSols(o), SCIPgetNSols(o))
70+
return SCIPgetSolOrigObj(o, sols[attr.result_index])
6671
end
6772

68-
function MOI.get(o::Optimizer, ::MOI.VariablePrimal, vi::VI)
73+
function MOI.get(o::Optimizer, attr::MOI.VariablePrimal, vi::VI)
6974
assert_solved(o)
70-
return SCIPgetSolVal(o, SCIPgetBestSol(o), var(o, vi))
75+
sols = unsafe_wrap(Array{Ptr{SCIP_SOL}}, SCIPgetSols(o), SCIPgetNSols(o))
76+
return SCIPgetSolVal(o, sols[attr.N], var(o, vi))
7177
end
7278

73-
function MOI.get(o::Optimizer, ::MOI.ConstraintPrimal, ci::CI{SVF,<:BOUNDS})
79+
function MOI.get(o::Optimizer, attr::MOI.ConstraintPrimal, ci::CI{SVF,<:BOUNDS})
7480
assert_solved(o)
75-
return SCIPgetSolVal(o, SCIPgetBestSol(o), var(o, VI(ci.value)))
81+
sols = unsafe_wrap(Array{Ptr{SCIP_SOL}}, SCIPgetSols(o), SCIPgetNSols(o))
82+
return SCIPgetSolVal(o, sols[attr.N], var(o, VI(ci.value)))
7683
end
7784

78-
function MOI.get(o::Optimizer, ::MOI.ConstraintPrimal, ci::CI{SAF,<:BOUNDS})
85+
function MOI.get(o::Optimizer, attr::MOI.ConstraintPrimal, ci::CI{SAF,<:BOUNDS})
7986
assert_solved(o)
80-
return SCIPgetActivityLinear(o, cons(o, ci), SCIPgetBestSol(o))
87+
sols = unsafe_wrap(Array{Ptr{SCIP_SOL}}, SCIPgetSols(o), SCIPgetNSols(o))
88+
return SCIPgetActivityLinear(o, cons(o, ci), sols[attr.N])
8189
end
8290

8391
function MOI.get(o::Optimizer, ::MOI.ObjectiveBound)

src/MOI_wrapper/variable.jl

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -56,21 +56,21 @@ function MOI.add_constraint(o::Optimizer, func::SVF, set::S) where {S <: VAR_TYP
5656
# Need to adjust bounds for SCIP, which fails with an error otherwise.
5757
# Check for conflicts with existing bounds first:
5858
lb, ub = SCIPvarGetLbOriginal(v), SCIPvarGetUbOriginal(v)
59-
if lb >= 0.0 && ub <= 1.0
60-
# Store old bounds for later recovery.
61-
o.binbounds[vi] = MOI.Interval(lb, ub)
62-
elseif lb == -SCIPinfinity(o) && ub == SCIPinfinity(o)
59+
if lb == -SCIPinfinity(o) && ub == SCIPinfinity(o)
6360
@debug "Implicitly setting bounds [0,1] for binary variable at $(vi.value)!"
6461
@SC SCIPchgVarLb(o, v, 0.0)
6562
@SC SCIPchgVarUb(o, v, 1.0)
66-
elseif lb <= 0.0 && ub >= 1.0
67-
@debug "Tightening bounds [$lb,$ub] to [0,1] for binary variable at $(vi.value)!"
68-
@SC SCIPchgVarLb(o, v, 0.0)
69-
@SC SCIPchgVarUb(o, v, 1.0)
63+
else
7064
# Store old bounds for later recovery.
7165
o.binbounds[vi] = MOI.Interval(lb, ub)
72-
else
73-
error("Existing bounds [$lb,$ub] conflict for binary variable at $(vi.value)!")
66+
if ub > 1.0
67+
@debug "Tightening upper bound $ub to 1 for binary variable at $(vi.value)!"
68+
@SC SCIPchgVarUb(o, v, 1.0)
69+
end
70+
if lb < 0.0
71+
@debug "Tightening lower bound $lb to 0 for binary variable at $(vi.value)!"
72+
@SC SCIPchgVarLb(o, v, 0.0)
73+
end
7474
end
7575
end
7676
# use var index for cons index of this type
@@ -126,13 +126,19 @@ function MOI.add_constraint(o::Optimizer, func::SVF, set::S) where S <: BOUNDS
126126
if SCIPvarGetType(v) == SCIP_VARTYPE_BINARY
127127
# Store new bounds
128128
o.binbounds[vi] = MOI.Interval(newlb, newub)
129-
if newlb >= 0.0 && newlb <= newub && newub <= 1.0
129+
130+
if newlb < 0.0
131+
@debug "Ignoring relaxed lower bound $newlb for binary variable at $(vi.value)!"
132+
newlb = oldlb
133+
end
134+
135+
if newub > 1.0
136+
@debug "Ignoring relaxed upper bounds $newub for binary variable at $(vi.value)!"
137+
newub = oldub
138+
end
139+
140+
if newlb != oldlb || newub != oldub
130141
@debug "Overwriting existing bounds [0.0,1.0] with [$newlb,$newub] for binary variable at $(vi.value)!"
131-
elseif newlb <= oldlb && newub >= oldub
132-
@debug "Ignoring wider bounds [$newlb,$newub] for binary variable at $(vi.value)!"
133-
newlb, newub = oldlb, oldub
134-
else
135-
error("Invalid bounds [$newlb,$newub] for binary variable at $(vi.value)!")
136142
end
137143
else # general case (non-binary variable)
138144
error("Already have bounds [$oldlb,$oldub] for variable at $(vi.value)!")

src/managed_scip.jl

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,48 @@ function free_scip(mscip::ManagedSCIP)
5656
@assert mscip.scip[] == C_NULL
5757
end
5858

59+
"Set a parameter's current value."
60+
function get_parameter(mscip::ManagedSCIP, name::AbstractString)
61+
param = SCIPgetParam(mscip, name)
62+
if param == C_NULL
63+
error("Unrecognized parameter: $name")
64+
end
65+
paramtype = SCIPparamGetType(param)
66+
if paramtype === SCIP_PARAMTYPE_BOOL
67+
value = Ref{SCIP_Bool}()
68+
@SC SCIPgetBoolParam(mscip, name, value)
69+
if value[] == TRUE
70+
return true
71+
elseif value[] == FALSE
72+
return false
73+
else
74+
error("encountered invalid value for a boolean: $(value[])")
75+
end
76+
elseif paramtype === SCIP_PARAMTYPE_INT
77+
value = Ref{Cint}()
78+
@SC SCIPgetIntParam(mscip, name, value)
79+
return value[]
80+
elseif paramtype === SCIP_PARAMTYPE_LONGINT
81+
value = Ref{Clonglong}()
82+
@SC SCIPgetLongintParam(mscip, name, value)
83+
return value[]
84+
elseif paramtype === SCIP_PARAMTYPE_REAL
85+
value = Ref{Cdouble}()
86+
@SC SCIPgetRealParam(mscip, name, value)
87+
return value[]
88+
elseif paramtype === SCIP_PARAMTYPE_CHAR
89+
value = Ref{Cchar}()
90+
@SC SCIPgetCharParam(mscip, name, value)
91+
return Char(value[])
92+
elseif paramtype === SCIP_PARAMTYPE_STRING
93+
value = Ref{Cstring}()
94+
@SC SCIPgetStringParam(mscip, name, value)
95+
return unsafe_string(value[])
96+
else
97+
error("Unexpected parameter type: $paramtype")
98+
end
99+
end
100+
59101
"Set a parameter."
60102
function set_parameter(mscip::ManagedSCIP, name::AbstractString, value)
61103
param = SCIPgetParam(mscip, name)

src/wrapper/scip_param.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ function SCIPgetRealParam(scip, name, value)
5151
end
5252

5353
function SCIPgetCharParam(scip, name, value)
54-
ccall((:SCIPgetCharParam, libscip), SCIP_RETCODE, (Ptr{SCIP_}, Cstring, Cstring), scip, name, value)
54+
ccall((:SCIPgetCharParam, libscip), SCIP_RETCODE, (Ptr{SCIP_}, Cstring, Ptr{Cchar}), scip, name, value)
5555
end
5656

5757
function SCIPgetStringParam(scip, name, value)
@@ -123,7 +123,7 @@ function SCIPchgCharParam(scip, param, value)
123123
end
124124

125125
function SCIPsetCharParam(scip, name, value)
126-
ccall((:SCIPsetCharParam, libscip), SCIP_RETCODE, (Ptr{SCIP_}, Cstring, UInt8), scip, name, value)
126+
ccall((:SCIPsetCharParam, libscip), SCIP_RETCODE, (Ptr{SCIP_}, Ptr{Cchar}, UInt8), scip, name, value)
127127
end
128128

129129
function SCIPisCharParamValid(scip, param, value)

0 commit comments

Comments
 (0)