Skip to content

Commit

Permalink
use given names in writeLP (#848)
Browse files Browse the repository at this point in the history
* add option `generic` to writeLP

 - if true: same behaviour as before with "VAR%d" names
 - else: try to use given names, replacing some chars with `_`

* add test for writeLP(generic=false)

* writeLP: rename generic -> genericnames

* update doc wrt `writeLP`
  • Loading branch information
rschwarz authored and mlubin committed Sep 25, 2016
1 parent 167f349 commit 9865cd3
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 13 deletions.
2 changes: 1 addition & 1 deletion doc/refmodel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Methods

**Output**

* ``writeLP(m::Model, filename::AbstractString)`` - write the model to ``filename`` in the LP file format.
* ``writeLP(m::Model, filename::AbstractString; genericnames=true)`` - write the model to ``filename`` in the LP file format. Set ``genericnames=false`` for user-defined variable names.
* ``writeMPS(m::Model, filename::AbstractString)`` - write the model to ``filename`` in the MPS file format.

.. _solvestatus:
Expand Down
33 changes: 23 additions & 10 deletions src/writers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,20 @@ end
# LP File Writer
# We use the formatting defined at:
# http://lpsolve.sourceforge.net/5.0/CPLEX-format.htm
function writeLP(m::Model, fname::AbstractString)

varname_generic(m::Model, col::Integer) = "VAR$(col)"

function varname_given(m::Model, col::Integer)
# TODO: deal with non-ascii characters?
name = getname(m, col)
for (pat, sub) in [("[", "_"), ("]", ""), (",", "_")]
name = replace(name, pat, sub)
end
name
end

function writeLP(m::Model, fname::AbstractString; genericnames=true)
varname = genericnames ? varname_generic : varname_given

f = open(fname, "w")

Expand All @@ -198,15 +211,15 @@ function writeLP(m::Model, fname::AbstractString)
else
print_shortest(f, abs(objaff.coeffs[ind]))
end
@printf(f, " VAR%d %s ", objaff.vars[ind].col, (objaff.coeffs[ind+1] < 0)? "-" : "+")
@printf(f, " %s %s ", varname(m, objaff.vars[ind].col), (objaff.coeffs[ind+1] < 0)? "-" : "+")
end
if nnz >= 1
if nnz == 1
print_shortest(f, objaff.coeffs[nnz])
else
print_shortest(f, abs(objaff.coeffs[nnz]))
end
@printf(f, " VAR%d\n", objaff.vars[nnz].col)
@printf(f, " %s\n", varname(m, objaff.vars[nnz].col))
end

# Constraints
Expand All @@ -218,15 +231,15 @@ function writeLP(m::Model, fname::AbstractString)
else
print_shortest(f, abs(c.terms.coeffs[ind]))
end
@printf(f, " VAR%d %s ", c.terms.vars[ind].col, (c.terms.coeffs[ind+1] < 0)? "-" : "+")
@printf(f, " %s %s ", varname(m, c.terms.vars[ind].col), (c.terms.coeffs[ind+1] < 0)? "-" : "+")
end
if nnz >= 1
if nnz == 1
print_shortest(f, c.terms.coeffs[nnz])
else
print_shortest(f, abs(c.terms.coeffs[nnz]))
end
@printf(f, " VAR%d", c.terms.vars[nnz].col)
@printf(f, " %s", varname(m, c.terms.vars[nnz].col))
end
end
write(f,"Subject To\n")
Expand Down Expand Up @@ -274,10 +287,10 @@ function writeLP(m::Model, fname::AbstractString)
# No low bound
if m.colUpper[i] == +Inf
# Free
@printf(f, " VAR%d free\n", i)
@printf(f, " %s free\n", varname(m, i))
else
# x <= finite
@printf(f, " -inf <= VAR%d <= ", i)
@printf(f, " -inf <= %s <= ", varname(m, i))
print_shortest(f, m.colUpper[i])
println(f)
end
Expand All @@ -287,12 +300,12 @@ function writeLP(m::Model, fname::AbstractString)
# x >= finite
@printf(f, " ")
print_shortest(f, m.colLower[i])
@printf(f," <= VAR%d <= +inf\n", i)
@printf(f," <= %s <= +inf\n", varname(m, i))
else
# finite <= x <= finite
@printf(f, " ")
print_shortest(f, m.colLower[i])
@printf(f, " <= VAR%d <= ", i)
@printf(f, " <= %s <= ", varname(m, i))
print_shortest(f, m.colUpper[i])
println(f)
end
Expand All @@ -305,7 +318,7 @@ function writeLP(m::Model, fname::AbstractString)
t = m.colCat[i]
(t == :SemiCont || t == :SemiInt) && error("The LP file writer does not currently support semicontinuous or semi-integer variables")
if t == :Bin || t == :Int
@printf(f, " VAR%d\n", i)
@printf(f, " %s\n", varname(m, i))
end
end

Expand Down
56 changes: 54 additions & 2 deletions test/model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,60 @@ facts("[model] Test printing a model") do
constraints[2] = @constraint(modA, sum{r[i],i=3:5} <= (2 - x)/2.0)
constraints[3] = @constraint(modA, 6y + y <= z + r[6]/1.9)
#####################################################################
# Test LP writer
writeLP(modA, modPath * "A.lp")
# Test LP writer (given names)
writeLP(modA, modPath * "A.lp", genericnames=false)
modALP = if VERSION >= v"0.5.0-dev+1866" # leading zero, base Julia PR #14377
String[
"Maximize",
"obj: 0.16666666666666666 col_1 + 0.16666666666666666 y + 1 z + 1 r_3",
"Subject To",
"c1: 1 col_1 + 1 y >= 2",
"c2: 1 col_1 + 1 y <= 4",
"c3: 1 r_3 + 1 r_4 + 1 r_5 + 0.5 col_1 <= 1",
"c4: 6 y + 1 y - 1 z - 0.5263157894736842 r_6 <= 0",
"Bounds",
"0 <= col_1 <= +inf",
"-inf <= y <= 5",
"2 <= z <= 4",
"0 <= r_3 <= 3",
"0 <= r_4 <= 4",
"0 <= r_5 <= 5",
"0 <= r_6 <= 6",
"General",
"y",
"End"]
else
String[
"Maximize",
"obj: .16666666666666666 col_1 + .16666666666666666 y + 1 z + 1 r_3",
"Subject To",
"c1: 1 col_1 + 1 y >= 2",
"c2: 1 col_1 + 1 y <= 4",
"c3: 1 r_3 + 1 r_4 + 1 r_5 + .5 col_1 <= 1",
"c4: 6 y + 1 y - 1 z - .5263157894736842 r_6 <= 0",
"Bounds",
"0 <= col_1 <= +inf",
"-inf <= y <= 5",
"2 <= z <= 4",
"0 <= r_3 <= 3",
"0 <= r_4 <= 4",
"0 <= r_5 <= 5",
"0 <= r_6 <= 6",
"General",
"y",
"End"]
end
modAfp = open(modPath * "A.lp")
lineInd = 1
while !eof(modAfp)
line = readline(modAfp)
@fact strip(line) --> strip(modALP[lineInd])
lineInd += 1
end
close(modAfp)
#####################################################################
# Test LP writer (generic names)
writeLP(modA, modPath * "A.lp", genericnames=true)
modALP = if VERSION >= v"0.5.0-dev+1866" # leading zero, base Julia PR #14377
String[
"Maximize",
Expand Down

0 comments on commit 9865cd3

Please sign in to comment.