Skip to content

Commit 8bfa2e5

Browse files
committed
Improve MIP print formatting, etc.
1 parent 32d441a commit 8bfa2e5

File tree

1 file changed

+59
-43
lines changed

1 file changed

+59
-43
lines changed

src/sage/numerical/mip.pyx

Lines changed: 59 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ A mixed integer linear program can give you an answer:
6565
The following example shows all these steps::
6666
6767
sage: p = MixedIntegerLinearProgram(maximization=False, solver='GLPK')
68-
sage: w = p.new_variable(integer=True, nonnegative=True)
68+
sage: w = p.new_variable(integer=True, nonnegative=True, name='w')
6969
sage: p.add_constraint(w[0] + w[1] + w[2] - 14*w[3] == 0)
7070
sage: p.add_constraint(w[1] + 2*w[2] - 8*w[3] == 0)
7171
sage: p.add_constraint(2*w[2] - 3*w[3] == 0)
@@ -74,18 +74,18 @@ The following example shows all these steps::
7474
sage: p.set_objective(w[3])
7575
sage: p.show()
7676
Minimization:
77-
x_3
77+
w[3]
7878
Constraints:
79-
0.0 <= x_0 + x_1 + x_2 - 14.0 x_3 <= 0.0
80-
0.0 <= x_1 + 2.0 x_2 - 8.0 x_3 <= 0.0
81-
0.0 <= 2.0 x_2 - 3.0 x_3 <= 0.0
82-
- x_0 + x_1 + x_2 <= 0.0
83-
- x_3 <= -1.0
79+
0.0 <= w[0] + w[1] + w[2] - 14.0 w[3] <= 0.0
80+
0.0 <= w[1] + 2.0 w[2] - 8.0 w[3] <= 0.0
81+
0.0 <= 2.0 w[2] - 3.0 w[3] <= 0.0
82+
- w[0] + w[1] + w[2] <= 0.0
83+
- w[3] <= -1.0
8484
Variables:
85-
x_0 is an integer variable (min=0.0, max=+oo)
86-
x_1 is an integer variable (min=0.0, max=+oo)
87-
x_2 is an integer variable (min=0.0, max=+oo)
88-
x_3 is an integer variable (min=0.0, max=+oo)
85+
w[0] = x_0 is an integer variable (min=0.0, max=+oo)
86+
w[1] = x_1 is an integer variable (min=0.0, max=+oo)
87+
w[2] = x_2 is an integer variable (min=0.0, max=+oo)
88+
w[3] = x_3 is an integer variable (min=0.0, max=+oo)
8989
sage: print('Objective Value: {}'.format(p.solve()))
9090
Objective Value: 2.0
9191
sage: for i, v in sorted(p.get_values(w, convert=ZZ, tolerance=1e-3).items()):
@@ -95,6 +95,34 @@ The following example shows all these steps::
9595
w_2 = 3
9696
w_3 = 2
9797
98+
If your problem is already in the standard form, for example::
99+
100+
sage: A = matrix([[1, 2], [3, 5]])
101+
sage: b = vector([7, 11])
102+
sage: c = vector([5, 9])
103+
104+
You can add the constraint by treating the variable dictionary as a vector::
105+
106+
sage: p = MixedIntegerLinearProgram(maximization=True, solver='GLPK')
107+
sage: w = p.new_variable(integer=True, name='w')
108+
sage: p.add_constraint(A * w <= b)
109+
sage: p.set_objective((c.row() * w)[0])
110+
sage: p.show()
111+
Maximization:
112+
5.0 w[0] + 9.0 w[1]
113+
Constraints:
114+
w[0] + 2.0 w[1] <= 7.0
115+
3.0 w[0] + 5.0 w[1] <= 11.0
116+
Variables:
117+
w[0] = x_0 is an integer variable (min=-oo, max=+oo)
118+
w[1] = x_1 is an integer variable (min=-oo, max=+oo)
119+
sage: print('Objective Value: {}'.format(p.solve()))
120+
Objective Value: 25.0
121+
sage: for i, v in sorted(p.get_values(w, convert=ZZ, tolerance=1e-3).items()):
122+
....: print(f'w_{i} = {v}')
123+
w_0 = -13
124+
w_1 = 10
125+
98126
Different backends compute with different base fields, for example::
99127
100128
sage: p = MixedIntegerLinearProgram(solver='GLPK')
@@ -144,8 +172,6 @@ also allowed::
144172
sage: a[4, 'string', QQ] - 7*b[2]
145173
x_2 - 7*x_3
146174
sage: mip.show()
147-
Maximization:
148-
<BLANKLINE>
149175
Constraints:
150176
Variables:
151177
a[1] = x_0 is a continuous variable (min=-oo, max=+oo)
@@ -778,8 +804,6 @@ cdef class MixedIntegerLinearProgram(SageObject):
778804
sage: p.add_constraint(x[0] + x[3] <= 8)
779805
sage: p.add_constraint(y[0] >= y[1])
780806
sage: p.show()
781-
Maximization:
782-
<BLANKLINE>
783807
Constraints:
784808
x_0 + x_1 <= 8.0
785809
- x_2 + x_3 <= 0.0
@@ -795,8 +819,6 @@ cdef class MixedIntegerLinearProgram(SageObject):
795819
sage: mip.<x, y, z> = MixedIntegerLinearProgram(solver='GLPK')
796820
sage: mip.add_constraint(x[0] + y[1] + z[2] <= 10)
797821
sage: mip.show()
798-
Maximization:
799-
<BLANKLINE>
800822
Constraints:
801823
x[0] + y[1] + z[2] <= 10.0
802824
Variables:
@@ -860,8 +882,6 @@ cdef class MixedIntegerLinearProgram(SageObject):
860882
sage: a[0] + b[2]
861883
x_0 + x_1
862884
sage: mip.show()
863-
Maximization:
864-
<BLANKLINE>
865885
Constraints:
866886
Variables:
867887
a[0] = x_0 is a continuous variable (min=-oo, max=+oo)
@@ -1251,23 +1271,24 @@ cdef class MixedIntegerLinearProgram(SageObject):
12511271
varid_explainer[i] = varid_name[i] = default_name
12521272

12531273
##### Sense and objective function
1254-
print("Maximization:" if b.is_maximization() else "Minimization:")
1255-
print(" ", end=" ")
1274+
formula_parts = []
12561275
first = True
12571276
for 0<= i< b.ncols():
12581277
c = b.objective_coefficient(i)
12591278
if c == 0:
12601279
continue
1261-
print((("+ " if (not first and c>0) else "") +
1262-
("" if c == 1 else ("- " if c == -1 else str(c)+" "))+varid_name[i]
1263-
), end=" ")
1280+
formula_parts.append(("+ " if (not first and c>0) else "") +
1281+
("" if c == 1 else ("- " if c == -1 else str(c)+" "))+varid_name[i]
1282+
)
12641283
first = False
12651284
d = b.objective_constant_term()
12661285
if d > self._backend.zero():
1267-
print("+ {} ".format(d))
1286+
formula_parts.append("+ {}".format(d))
12681287
elif d < self._backend.zero():
1269-
print("- {} ".format(-d))
1270-
print("\n")
1288+
formula_parts.append("- {}".format(-d))
1289+
if formula_parts:
1290+
print("Maximization:" if b.is_maximization() else "Minimization:")
1291+
print(" " + " ".join(formula_parts))
12711292

12721293
##### Constraints
12731294
print("Constraints:")
@@ -2001,8 +2022,6 @@ cdef class MixedIntegerLinearProgram(SageObject):
20012022
sage: b = p.new_variable(nonnegative=True)
20022023
sage: p.add_constraint(b[8] - b[15] <= 3*b[8] + 9)
20032024
sage: p.show()
2004-
Maximization:
2005-
<BLANKLINE>
20062025
Constraints:
20072026
-2.0 x_0 - x_1 <= 9.0
20082027
Variables:
@@ -2043,8 +2062,6 @@ cdef class MixedIntegerLinearProgram(SageObject):
20432062
sage: for each in range(10):
20442063
....: lp.add_constraint(lp[0]-lp[1], min=1)
20452064
sage: lp.show()
2046-
Maximization:
2047-
<BLANKLINE>
20482065
Constraints:
20492066
1.0 <= x_0 - x_1
20502067
Variables:
@@ -2056,8 +2073,6 @@ cdef class MixedIntegerLinearProgram(SageObject):
20562073
sage: for each in range(10):
20572074
....: lp.add_constraint(2*lp[0] - 2*lp[1], min=2)
20582075
sage: lp.show()
2059-
Maximization:
2060-
<BLANKLINE>
20612076
Constraints:
20622077
1.0 <= x_0 - x_1
20632078
Variables:
@@ -2069,8 +2084,6 @@ cdef class MixedIntegerLinearProgram(SageObject):
20692084
sage: for each in range(10):
20702085
....: lp.add_constraint(-2*lp[0] + 2*lp[1], min=-2)
20712086
sage: lp.show()
2072-
Maximization:
2073-
<BLANKLINE>
20742087
Constraints:
20752088
1.0 <= x_0 - x_1
20762089
-2.0 <= -2.0 x_0 + 2.0 x_1
@@ -2268,17 +2281,13 @@ cdef class MixedIntegerLinearProgram(SageObject):
22682281
sage: p.add_constraint(x - y, max=0)
22692282
sage: p.add_constraint(x, max=4)
22702283
sage: p.show()
2271-
Maximization:
2272-
<BLANKLINE>
22732284
Constraints:
22742285
x_0 + x_1 <= 10.0
22752286
x_0 - x_1 <= 0.0
22762287
x_0 <= 4.0
22772288
...
22782289
sage: p.remove_constraint(1)
22792290
sage: p.show()
2280-
Maximization:
2281-
<BLANKLINE>
22822291
Constraints:
22832292
x_0 + x_1 <= 10.0
22842293
x_0 <= 4.0
@@ -2306,17 +2315,13 @@ cdef class MixedIntegerLinearProgram(SageObject):
23062315
sage: p.add_constraint(x - y, max=0)
23072316
sage: p.add_constraint(x, max=4)
23082317
sage: p.show()
2309-
Maximization:
2310-
<BLANKLINE>
23112318
Constraints:
23122319
x_0 + x_1 <= 10.0
23132320
x_0 - x_1 <= 0.0
23142321
x_0 <= 4.0
23152322
...
23162323
sage: p.remove_constraints([0, 1])
23172324
sage: p.show()
2318-
Maximization:
2319-
<BLANKLINE>
23202325
Constraints:
23212326
x_0 <= 4.0
23222327
...
@@ -3627,8 +3632,19 @@ cdef class MIPVariable(FiniteFamily):
36273632
(1, 1/2)*x_0 + (2/3, 3/4)*x_1
36283633
sage: m * v
36293634
(1, 2/3)*x_0 + (1/2, 3/4)*x_1
3635+
3636+
sage: c = vector([1, 2])
3637+
sage: v * c
3638+
x_0 + 2*x_1
3639+
sage: c * v
3640+
x_0 + 2*x_1
36303641
"""
3642+
from sage.structure.element import Vector
3643+
if isinstance(left, Vector):
3644+
left, right = right, left
36313645
if isinstance(left, MIPVariable):
3646+
if isinstance(right, Vector):
3647+
return (<MIPVariable> left)._matrix_rmul_impl(right.column())[0]
36323648
if not isinstance(right, Matrix):
36333649
return NotImplemented
36343650
return (<MIPVariable> left)._matrix_rmul_impl(right)

0 commit comments

Comments
 (0)