问题
I would like to build a Google OR Tools model to use linear_solver
for a CBC_MIXED_INTEGER_PROGRAMMING
.
Following Google tutorial I learned hot to build the constraints but I have a question...is it necessary to hand write every constraint?
I mean, I have the following DataFrame df_constraint
which contain the coefficient of the constraints in the form of ax+by<=c
.
+---+---+---+
| A | B | C |
+---+---+---+
| 1 | 5 | 7 |
| 2 | 9 | 3 |
| 3 | 0 | 4 |
+---+---+---+
the table could be translated into the following contraints
# 1x+5y<=7
constraint1 = solver.Constraint(-solver.infinity(), 7)
constraint1.SetCoefficient(x, 1)
constraint1.SetCoefficient(y, 5)
# 2x+9y<=3
constraint2 = solver.Constraint(-solver.infinity(), 3)
constraint2.SetCoefficient(x, 2)
constraint2.SetCoefficient(y, 9)
# 3x<=4
constraint3 = solver.Constraint(-solver.infinity(), 4)
constraint3.SetCoefficient(x, 3)
Instead of write every rows I would like something like this:
for index, row in df.iterrows():
constraint = solver.Constraint(-solver.infinity(), row['C'])
constraint.SetCoefficient(x, row['A'])
constraint.SetCoefficient(y, row['B'])
My snippet won't work, as every constraint must have a different name (like constraint1
, constraint2
, ...).
回答1:
does this, solve your issue ?
df_constraints = pd.DataFrame({
'A': pd.Series([1, 2, 3]),
'B': pd.Series([5, 9, 0]),
'C': pd.Series([7, 3, 4]),
})
for row in df_constraints.itertuples():
#print("row {}".format(row))
#print("A {}".format(row[0]))
#print("B {}".format(row[1]))
#print("C {}".format(row[2]))
constraint = solver.Constraint(-solver.infinity(), row[2])
constraint.SetCoefficient(x, row[0])
constraint.SetCoefficient(y, row[1])
回答2:
In fact, OR-Tools doesn't require each constraint to have a unique name. But the following gives them unique names anyway. As mentioned above, if you need to store the constraints, you can do so in an array as follows. Here I'm using the more common notation (A is the constraint coefficients, B is the constraint right-hand sides, c is the objective coefficients). But it will adapt to your Pandas setup.
from ortools.linear_solver import pywraplp # adapted from one of the examples
inf = float("inf")
AB = [
[1, 0, 1], # x <= 1
[0, 1, 2], # y <= 2
[1, 1, 2], # x + y <= 2
[-1, -1, 0] # x + y >= 0
]
c = [3, 1]
def main():
solver = pywraplp.Solver('simple_lp_program',
pywraplp.Solver.GLOP_LINEAR_PROGRAMMING)
x = solver.NumVar(-inf, inf, 'x') # no UB or LB on x, y
y = solver.NumVar(-inf, inf, 'y')
cts = []
for i, (*a, b) in enumerate(AB):
ct = solver.Constraint(-inf, b, 'ct' + str(i))
ct.SetCoefficient(x, a[0])
ct.SetCoefficient(y, a[1])
cts.append(ct)
print('Number of constraints =', solver.NumConstraints())
objective = solver.Objective()
objective.SetCoefficient(x, c[0])
objective.SetCoefficient(y, c[1])
objective.SetMaximization()
solver.Solve()
print('Solution:')
print('Objective value =', objective.Value())
print('x =', x.solution_value())
print('y =', y.solution_value())
if __name__ == '__main__':
main()
来源:https://stackoverflow.com/questions/54519478/google-or-tools-constraints-from-dataframe