Skip to content

Commit bb9d8fc

Browse files
authored
[FileFormats.SDPA] fix reading files with {} punctuation (#2759)
1 parent 1d5ee59 commit bb9d8fc

File tree

3 files changed

+25
-34
lines changed

3 files changed

+25
-34
lines changed

src/FileFormats/SDPA/SDPA.jl

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -302,18 +302,15 @@ function _dim_to_set(s::AbstractString)
302302
end
303303
end
304304

305-
function _parse_dimensions(dims::AbstractString)
306-
isvalid(char) = isdigit(char) || char == '-'
307-
is_delimiter(char) = isspace(char) || char == ','
308-
start = findfirst(isvalid, dims)
309-
if start === nothing
310-
return Union{MOI.PositiveSemidefiniteConeTriangle,MOI.Nonnegatives}[]
311-
end
312-
stop = findlast(isvalid, dims)::Int
313-
s = split(dims[start:stop], is_delimiter)
314-
return Union{MOI.PositiveSemidefiniteConeTriangle,MOI.Nonnegatives}[
315-
_dim_to_set(dim) for dim in filter!(!isempty, s)
316-
]
305+
function _split(line)
306+
# In some variations of SDPA, there is the comment:
307+
#
308+
# The special characters `,`, `(`, `)`, `{`, and `}` can be used as
309+
# punctuation and are ignored.
310+
#
311+
# As one example, see https://github.com/vsdp/SDPLIB
312+
line = replace(line, r"[,{}\(\)]"=>' ')
313+
return split(line)
317314
end
318315

319316
"""
@@ -365,19 +362,20 @@ function Base.read!(io::IO, model::Model{T}) where {T<:Real}
365362
num_variables_read = true
366363
# According to http://plato.asu.edu/ftp/sdpa_format.txt,
367364
# additional text after the number of variables should be ignored.
368-
scalar_vars = MOI.add_variables(model, parse(Int, split(line)[1]))
365+
scalar_vars =
366+
MOI.add_variables(model, parse(Int, first(_split(line))))
369367
elseif num_blocks === nothing
370368
if isempty(line)
371369
continue
372370
end
373371
# According to http://plato.asu.edu/ftp/sdpa_format.txt,
374372
# additional text after the number of blocks should be ignored.
375-
num_blocks = parse(Int, split(line)[1])
373+
num_blocks = parse(Int, first(_split(line)))
376374
elseif !block_sets_read
377375
if isempty(line) && !iszero(num_blocks)
378376
continue
379377
end
380-
block_sets = _parse_dimensions(line)
378+
block_sets = _dim_to_set.(_split(line))
381379
block_sets_read = true
382380
if length(block_sets) != num_blocks
383381
error(
@@ -399,7 +397,7 @@ function Base.read!(io::IO, model::Model{T}) where {T<:Real}
399397
continue
400398
end
401399
objective_read = true
402-
c = parse.(T, split(line))
400+
c = parse.(T, _split(line))
403401
if length(c) != num_vars
404402
error(
405403
"The number of variables ($num_vars) does not match the length of the list of coefficients for the objective function vector of coefficients ($(length(c))).",
@@ -416,7 +414,7 @@ function Base.read!(io::IO, model::Model{T}) where {T<:Real}
416414
if isempty(line)
417415
continue
418416
end
419-
values = split(line)
417+
values = _split(line)
420418
if length(values) != 5
421419
error(
422420
"Invalid line specifying entry: $line. There are $(length(values)) values instead of 5.",

test/FileFormats/SDPA/SDPA.jl

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -323,26 +323,19 @@ function test_examples()
323323
end
324324

325325
# See https://github.com/jump-dev/MathOptInterface.jl/issues/1541
326-
function _spacer(char)
327-
return [" ", "$char", " $char", "$char ", " $char "]
328-
end
326+
_spacer(char) = [" ", "$char", " $char", "$char ", " $char "]
329327

330328
function test_dim_reader()
331-
for before in _spacer('{')
332-
for sep in _spacer(',')
333-
for after in _spacer('}')
334-
line = string(before, "-4", sep, "2", after)
335-
exp = [
336-
MOI.Nonnegatives(4),
337-
MOI.PositiveSemidefiniteConeTriangle(2),
338-
]
339-
@test MOI.FileFormats.SDPA._parse_dimensions(line) == exp
340-
line = string(before, "2", sep, "-4", after)
341-
@test MOI.FileFormats.SDPA._parse_dimensions(line) ==
342-
exp[2:-1:1]
343-
end
329+
fn(line) = SDPA._dim_to_set.(SDPA._split(line))
330+
for (a, b) in ['{' => '}', '(' => ')']
331+
for pre in _spacer(a), sep in _spacer(','), suf in _spacer(b)
332+
@test fn("$(pre)-4$(sep)2$suf") ==
333+
[MOI.Nonnegatives(4), MOI.PositiveSemidefiniteConeTriangle(2)]
334+
@test fn("$(pre)2$(sep)-4$suf") ==
335+
[MOI.PositiveSemidefiniteConeTriangle(2), MOI.Nonnegatives(4)]
344336
end
345337
end
338+
return
346339
end
347340

348341
function test_integer_before_variables()

test/FileFormats/SDPA/models/issue_1541.dat-s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
3 =mdim
22
2 =nblocks
33
{-4, 2}
4-
-0.0 -1 -2
4+
{-0.0,-1e+0, -2}
55
0 1 1 1 -1
66
1 1 1 1 -1
77
1 1 2 2 1

0 commit comments

Comments
 (0)