Skip to content

Commit 7f26868

Browse files
authored
[FileFormats.MOF] fix reading type of PrimalStart and DualStart (#2652)
1 parent b6e9719 commit 7f26868

File tree

2 files changed

+61
-91
lines changed

2 files changed

+61
-91
lines changed

src/FileFormats/MOF/read.jl

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ function read_variables(model::Model, object::Dict)
9191
model,
9292
MOI.VariablePrimalStart(),
9393
index,
94-
variable["primal_start"],
94+
convert(Float64, variable["primal_start"]),
9595
)
9696
end
9797
end
@@ -114,6 +114,9 @@ function read_objective(
114114
return
115115
end
116116

117+
_to_float64(x::Number) = convert(Float64, x)
118+
_to_float64(x::AbstractVector) = convert(Vector{Float64}, x)
119+
117120
function _add_constraint(
118121
model::Model,
119122
object::Dict,
@@ -126,14 +129,19 @@ function _add_constraint(
126129
MOI.set(model, MOI.ConstraintName(), index, object["name"]::String)
127130
end
128131
if haskey(object, "dual_start")
129-
MOI.set(model, MOI.ConstraintDualStart(), index, object["dual_start"])
132+
MOI.set(
133+
model,
134+
MOI.ConstraintDualStart(),
135+
index,
136+
_to_float64(object["dual_start"]),
137+
)
130138
end
131139
if haskey(object, "primal_start")
132140
MOI.set(
133141
model,
134142
MOI.ConstraintPrimalStart(),
135143
index,
136-
object["primal_start"],
144+
_to_float64(object["primal_start"]),
137145
)
138146
end
139147
return

test/FileFormats/MOF/MOF.jl

Lines changed: 50 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,117 +1217,79 @@ c1: [x, y] in Reified(GreaterThan(1.0))
12171217
end
12181218

12191219
function test_VariablePrimalStart()
1220+
target = ("x" => nothing, "y" => 1.0, "z" => 1.23)
12201221
model_w = MOF.Model()
1221-
x = MOI.add_variable(model_w)
1222-
MOI.set(model_w, MOI.VariableName(), x, "x")
1223-
y = MOI.add_variable(model_w)
1224-
MOI.set(model_w, MOI.VariableName(), y, "y")
1225-
MOI.set(model_w, MOI.VariablePrimalStart(), y, 1e+3)
1226-
f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0)
1227-
c1 = MOI.add_constraint(model_w, f, MOI.LessThan(1.0))
1228-
c2 = MOI.add_constraint(model_w, f, MOI.GreaterThan(0.0))
1222+
for (name, value) in target
1223+
xi = MOI.add_variable(model_w)
1224+
MOI.set(model_w, MOI.VariableName(), xi, name)
1225+
MOI.set(model_w, MOI.VariablePrimalStart(), xi, value)
1226+
end
12291227
MOI.write_to_file(model_w, TEST_MOF_FILE)
12301228
_validate(TEST_MOF_FILE)
12311229
model_r = MOF.Model()
12321230
MOI.read_from_file(model_r, TEST_MOF_FILE)
1233-
start_x = MOI.get(
1234-
model_r,
1235-
MOI.VariablePrimalStart(),
1236-
MOI.get(model_r, MOI.VariableIndex, "x"),
1237-
)
1238-
start_y = MOI.get(
1239-
model_r,
1240-
MOI.VariablePrimalStart(),
1241-
MOI.get(model_r, MOI.VariableIndex, "y"),
1242-
)
1243-
@test isnothing(start_x)
1244-
@test start_y == 1e+3
1231+
for (name, value) in target
1232+
xi = MOI.get(model_r, MOI.VariableIndex, name)
1233+
@test MOI.get(model_r, MOI.VariablePrimalStart(), xi) === value
1234+
end
1235+
return
12451236
end
12461237

12471238
function test_constraint_start_scalar()
1239+
target = Dict(
1240+
"c1" => (nothing, nothing),
1241+
"c2" => (1.23, 1.0),
1242+
"c3" => (1.0, 1.23),
1243+
)
12481244
model_w = MOF.Model()
12491245
x = MOI.add_variable(model_w)
12501246
MOI.set(model_w, MOI.VariableName(), x, "x")
1251-
y = MOI.add_variable(model_w)
1252-
MOI.set(model_w, MOI.VariableName(), y, "y")
1253-
f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0)
1254-
c1 = MOI.add_constraint(model_w, f, MOI.LessThan(1.0))
1255-
MOI.set(model_w, MOI.ConstraintName(), c1, "c1")
1256-
c2 = MOI.add_constraint(model_w, f, MOI.GreaterThan(0.0))
1257-
MOI.set(model_w, MOI.ConstraintName(), c2, "c2")
1258-
MOI.set(model_w, MOI.ConstraintDualStart(), c2, 1e+3)
1259-
MOI.set(model_w, MOI.ConstraintPrimalStart(), c2, 1e+4)
1247+
for (name, (primal, dual)) in target
1248+
c = MOI.add_constraint(model_w, 1.0 * x, MOI.LessThan(1.0))
1249+
MOI.set(model_w, MOI.ConstraintName(), c, name)
1250+
MOI.set(model_w, MOI.ConstraintPrimalStart(), c, primal)
1251+
MOI.set(model_w, MOI.ConstraintDualStart(), c, dual)
1252+
end
12601253
MOI.write_to_file(model_w, TEST_MOF_FILE)
12611254
_validate(TEST_MOF_FILE)
12621255
model_r = MOF.Model()
12631256
MOI.read_from_file(model_r, TEST_MOF_FILE)
1264-
dual_start_c1 = MOI.get(
1265-
model_r,
1266-
MOI.ConstraintDualStart(),
1267-
MOI.get(model_r, MOI.ConstraintIndex, "c1"),
1268-
)
1269-
dual_start_c2 = MOI.get(
1270-
model_r,
1271-
MOI.ConstraintDualStart(),
1272-
MOI.get(model_r, MOI.ConstraintIndex, "c2"),
1273-
)
1274-
primal_start_c1 = MOI.get(
1275-
model_r,
1276-
MOI.ConstraintPrimalStart(),
1277-
MOI.get(model_r, MOI.ConstraintIndex, "c1"),
1278-
)
1279-
primal_start_c2 = MOI.get(
1280-
model_r,
1281-
MOI.ConstraintPrimalStart(),
1282-
MOI.get(model_r, MOI.ConstraintIndex, "c2"),
1283-
)
1284-
@test isnothing(dual_start_c1)
1285-
@test dual_start_c2 == 1e+3
1286-
@test isnothing(primal_start_c1)
1287-
@test primal_start_c2 == 1e+4
1257+
for (name, (primal, dual)) in target
1258+
ci = MOI.get(model_r, MOI.ConstraintIndex, name)
1259+
@test MOI.get(model_r, MOI.ConstraintPrimalStart(), ci) === primal
1260+
@test MOI.get(model_r, MOI.ConstraintDualStart(), ci) === dual
1261+
end
1262+
return
12881263
end
12891264

1290-
function test_constraint_start_conic()
1265+
function test_constraint_start_vector()
1266+
target = Dict(
1267+
"c1" => (nothing, nothing),
1268+
"c2" => ([1.23, 4.56], [1.0, 2.0]),
1269+
"c3" => ([3.0, 4.0], [7.89, -1.23]),
1270+
)
12911271
model_w = MOF.Model()
1292-
x = MOI.add_variables(model_w, 4)
1293-
for (index, variable) in enumerate(x)
1294-
MOI.set(model_w, MOI.VariableName(), variable, "var_$(index)")
1272+
x = MOI.add_variables(model_w, 2)
1273+
MOI.set.(model_w, MOI.VariableName(), x, ["x", "y"])
1274+
f = MOI.VectorOfVariables(x)
1275+
for (name, (primal, dual)) in target
1276+
c = MOI.add_constraint(model_w, f, MOI.Nonnegatives(2))
1277+
MOI.set(model_w, MOI.ConstraintName(), c, name)
1278+
MOI.set(model_w, MOI.ConstraintPrimalStart(), c, primal)
1279+
MOI.set(model_w, MOI.ConstraintDualStart(), c, dual)
12951280
end
1296-
c1 = MOI.add_constraint(model_w, [i for i in x], MOI.SecondOrderCone(4))
1297-
MOI.set(model_w, MOI.ConstraintName(), c1, "c1")
1298-
MOI.set(model_w, MOI.ConstraintDualStart(), c1, [1, 0, 0, 0])
1299-
MOI.set(model_w, MOI.ConstraintPrimalStart(), c1, [1, 1, 1, 1])
1300-
c2 = MOI.add_constraint(model_w, [i for i in x], MOI.SecondOrderCone(4))
1301-
MOI.set(model_w, MOI.ConstraintName(), c2, "c2")
13021281
MOI.write_to_file(model_w, TEST_MOF_FILE)
13031282
_validate(TEST_MOF_FILE)
13041283
model_r = MOF.Model()
13051284
MOI.read_from_file(model_r, TEST_MOF_FILE)
1306-
dual_start_c1 = MOI.get(
1307-
model_r,
1308-
MOI.ConstraintDualStart(),
1309-
MOI.get(model_r, MOI.ConstraintIndex, "c1"),
1310-
)
1311-
dual_start_c2 = MOI.get(
1312-
model_r,
1313-
MOI.ConstraintDualStart(),
1314-
MOI.get(model_r, MOI.ConstraintIndex, "c2"),
1315-
)
1316-
primal_start_c1 = MOI.get(
1317-
model_r,
1318-
MOI.ConstraintPrimalStart(),
1319-
MOI.get(model_r, MOI.ConstraintIndex, "c1"),
1320-
)
1321-
primal_start_c2 = MOI.get(
1322-
model_r,
1323-
MOI.ConstraintPrimalStart(),
1324-
MOI.get(model_r, MOI.ConstraintIndex, "c2"),
1325-
)
1326-
1327-
@test dual_start_c1 == [1, 0, 0, 0]
1328-
@test isnothing(dual_start_c2)
1329-
@test primal_start_c1 == [1, 1, 1, 1]
1330-
@test isnothing(primal_start_c2)
1285+
_cmp(::Nothing, ::Nothing) = true
1286+
_cmp(x::Vector{Float64}, y::Vector{Float64}) = x == y
1287+
for (name, (primal, dual)) in target
1288+
ci = MOI.get(model_r, MOI.ConstraintIndex, name)
1289+
@test _cmp(MOI.get(model_r, MOI.ConstraintPrimalStart(), ci), primal)
1290+
@test _cmp(MOI.get(model_r, MOI.ConstraintDualStart(), ci), dual)
1291+
end
1292+
return
13311293
end
13321294

13331295
function test_parse_int_coefficient_scalaraffineterm()

0 commit comments

Comments
 (0)