Skip to content

Commit d8a5c0e

Browse files
committed
Export variable and constraints names in LP files
1 parent 30ef9ea commit d8a5c0e

File tree

1 file changed

+44
-13
lines changed

1 file changed

+44
-13
lines changed

linopy/io.py

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from linopy import solvers
2727
from linopy.constants import CONCAT_DIM
2828
from linopy.objective import Objective
29+
from linopy.variables import Variables
2930

3031
if TYPE_CHECKING:
3132
from highspy.highs import Highs
@@ -51,9 +52,29 @@ def handle_batch(batch: list[str], f: TextIOWrapper, batch_size: int) -> list[st
5152
batch = [] # reset batch
5253
return batch
5354

55+
name_sanitizer = str.maketrans('-+*^[] ', '_______')
56+
def clean_name(name):
57+
return name.translate(name_sanitizer)
58+
59+
coord_sanitizer = str.maketrans('[,]', '(,)', ' ')
60+
def print_coord(coord):
61+
from linopy.common import print_coord
62+
coord = print_coord(coord).translate(coord_sanitizer)
63+
return coord
64+
65+
def print_variable(variables, var):
66+
name, coord = variables.get_label_position(var)
67+
name = clean_name(name)
68+
return f'{name}{print_coord(coord)}'
69+
70+
def print_constraint(constraints, var):
71+
name, coord = constraints.get_label_position(var)
72+
name = clean_name(name)
73+
return f'{name}{print_coord(coord)}'
74+
5475

5576
def objective_write_linear_terms(
56-
df: DataFrame, f: TextIOWrapper, batch: list[Any], batch_size: int
77+
df: DataFrame, f: TextIOWrapper, batch: list[Any], batch_size: int, variables: Variables
5778
) -> list[str | Any]:
5879
"""
5980
Write the linear terms of the objective to a file.
@@ -63,13 +84,14 @@ def objective_write_linear_terms(
6384
for idx in range(len(coeffs)):
6485
coeff = coeffs[idx]
6586
var = vars[idx]
66-
batch.append(f"{coeff:+.12g} x{var}\n")
87+
name = print_variable(variables, var)
88+
batch.append(f"{coeff:+.12g} {name}\n")
6789
batch = handle_batch(batch, f, batch_size)
6890
return batch
6991

7092

7193
def objective_write_quad_terms(
72-
quadratic: DataFrame, f: TextIOWrapper, batch: list[str], batch_size: int
94+
quadratic: DataFrame, f: TextIOWrapper, batch: list[str], batch_size: int, variables: Variables
7395
) -> list[str]:
7496
"""
7597
Write the cross terms of the objective to a file.
@@ -81,7 +103,9 @@ def objective_write_quad_terms(
81103
coeff = coeffs[idx]
82104
var1 = vars1[idx]
83105
var2 = vars2[idx]
84-
batch.append(f"{coeff:+.12g} x{var1} * x{var2}\n")
106+
name1 = print_variable(variables, var1)
107+
name2 = print_variable(variables, var2)
108+
batch.append(f"{coeff:+.12g} {name1} * {name2}\n")
85109
batch = handle_batch(batch, f, batch_size)
86110
return batch
87111

@@ -105,21 +129,21 @@ def objective_to_file(
105129
)
106130

107131
if m.is_linear:
108-
batch = objective_write_linear_terms(df, f, [], batch_size)
132+
batch = objective_write_linear_terms(df, f, [], batch_size, m.variables)
109133

110134
elif m.is_quadratic:
111135
is_linear = (df.vars1 == -1) | (df.vars2 == -1)
112136
linear = df[is_linear]
113137
linear = linear.assign(
114138
vars=linear.vars1.where(linear.vars1 != -1, linear.vars2)
115139
)
116-
batch = objective_write_linear_terms(linear, f, [], batch_size)
140+
batch = objective_write_linear_terms(linear, f, [], batch_size, m.variables)
117141

118142
if not is_linear.all():
119143
batch.append("+ [\n")
120144
quadratic = df[~is_linear]
121145
quadratic = quadratic.assign(coeffs=2 * quadratic.coeffs)
122-
batch = objective_write_quad_terms(quadratic, f, batch, batch_size)
146+
batch = objective_write_quad_terms(quadratic, f, batch, batch_size, m.variables)
123147
batch.append("] / 2\n")
124148

125149
if batch: # write the remaining lines
@@ -166,7 +190,9 @@ def constraints_to_file(
166190
label = labels[idx]
167191
coeff = coeffs[idx]
168192
var = vars[idx]
169-
batch.append(f"c{label}:\n{coeff:+.12g} x{var}\n")
193+
name = print_variable(m.variables, var)
194+
cname = print_variable(m.constraints, label)
195+
batch.append(f"{cname}:\n{coeff:+.12g} {name}\n")
170196
prev_label = label
171197
prev_sign = sign[idx]
172198
prev_rhs = rhs[idx]
@@ -175,15 +201,17 @@ def constraints_to_file(
175201
label = labels[idx]
176202
coeff = coeffs[idx]
177203
var = vars[idx]
204+
name = print_variable(m.variables, var)
178205

179206
if label != prev_label:
207+
cname = print_variable(m.constraints, label)
180208
batch.append(
181-
f"{prev_sign} {prev_rhs:+.12g}\n\nc{label}:\n{coeff:+.12g} x{var}\n"
209+
f"{prev_sign} {prev_rhs:+.12g}\n\n{cname}:\n{coeff:+.12g} {name}\n"
182210
)
183211
prev_sign = sign[idx]
184212
prev_rhs = rhs[idx]
185213
else:
186-
batch.append(f"{coeff:+.12g} x{var}\n")
214+
batch.append(f"{coeff:+.12g} {name}\n")
187215

188216
batch = handle_batch(batch, f, batch_size)
189217

@@ -231,7 +259,8 @@ def bounds_to_file(
231259
label = labels[idx]
232260
lower = lowers[idx]
233261
upper = uppers[idx]
234-
batch.append(f"{lower:+.12g} <= x{label} <= {upper:+.12g}\n")
262+
name = print_variable(m.variables, label)
263+
batch.append(f"{lower:+.12g} <= {name} <= {upper:+.12g}\n")
235264
batch = handle_batch(batch, f, batch_size)
236265

237266
if batch: # write the remaining lines
@@ -267,7 +296,8 @@ def binaries_to_file(
267296
df = var_slice.flat
268297

269298
for label in df.labels.values:
270-
batch.append(f"x{label}\n")
299+
name = print_variable(m.variables, label)
300+
batch.append(f"{name}\n")
271301
batch = handle_batch(batch, f, batch_size)
272302

273303
if batch: # write the remaining lines
@@ -304,7 +334,8 @@ def integers_to_file(
304334
df = var_slice.flat
305335

306336
for label in df.labels.values:
307-
batch.append(f"x{label}\n")
337+
name = print_variable(m.variables, label)
338+
batch.append(f"{name}\n")
308339
batch = handle_batch(batch, f, batch_size)
309340

310341
if batch: # write the remaining lines

0 commit comments

Comments
 (0)