Search code examples
pythonconstraintsmathematical-optimization

Issue with For Loop in Constraint Using PyMProg Package


I'm using the PyMathProg package. Documentation can be found here: http://pymprog.sourceforge.net/.

I've created a basic MIP program, but I'm running into a syntax issue with my constraints. I followed the dive-in tutorial in the documentation above and then modified.

from pymprog import * 

a = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
b = (10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
c = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
d = (5, 10, 15, 20, 25, 30, 35, 40, 45, 50)
s = (2, 8, 5, 4, 6, 1, 4, 3, 8, 10)

begin('example')

verbose(True)

x = var('x', 10, kind=bool)

maximize(sum(s[i]*x[i] for i in range(10)))

for i in range(10):
    sum(x[i]) == 5
    sum(a[i]*x[i]) >= 5
    sum(b[i]*x[i]) >= 250
    sum(c[i]*x[i]) >= 15
    sum(d[i]*x[i]) >= 90

solve()

I'm not sure why I'm getting the error below.

sum(x[i]) == 5
TypeError: '_var' object is not iterable

Solution

  • You're using sum, which is fine. It takes a list and adds them up

    sum([1,2,3])
    6
    

    The problem is, you're passing into it something that isn't a list, x[i] and the others, they are single elements.

    This is why it says TypeError: '_var' object is not iterable. Because you are passing in elements from the list x, that is created by using var.

    I thing what you're trying to do is something like this:

    from pymprog import *
    
    a = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
    b = (10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
    c = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    d = (5, 10, 15, 20, 25, 30, 35, 40, 45, 50)
    s = (2, 8, 5, 4, 6, 1, 4, 3, 8, 10)
    
    begin('example')
    
    verbose(True)
    
    x = var('x', 10, kind=bool)
    
    maximize(sum(s[i]*x[i] for i in range(10)))
    
    for i in range(10):
        sum(x[j+i] for j in range(3)) == 5
        sum(a[i]*x[j] for j in range(3)) >= 5
        sum(b[i]*x[j] for j in range(3)) >= 250
        sum(c[i]*x[j] for j in range(3)) >= 15
        sum(d[i]*x[j] for j in range(3)) >= 90
    
    solve()
    

    You can see where I've changed the second [i] to a [j] and added a for j in range (3). That means a list will be created inside that sum call.

    You can run that and see how close it is to what you're trying to do, as I'm not completely sure myself.