Creating multidimensional decision variables (Python)

1,368 views
Skip to first unread message

Hendrik B

unread,
Jul 24, 2018, 4:19:10 PM7/24/18
to or-tools-discuss
Hi,

I am implementing a version of the bin packing problem in ortools and I have a problem with initializing a two dimensional decision variable. When running my code, there is no error for this variable, but I believe it has something to do with it:

from __future__ import print_function
import sys
from ortools.linear_solver import pywraplp

def main(sol='hand'):

  solver = pywraplp.Solver('LinearExample',
                           pywraplp.Solver.GLOP_LINEAR_PROGRAMMING)
  #
  # data
  #
  nb_items = 12
  nb_resources = 7
  items = list(range(nb_items))
  resources = list(range(nb_resources))
  capacity = [150, 150, 150, 150, 150, 150, 150]
  value = [96, 76, 56, 11, 86, 10, 66, 86, 83, 12, 9, 81]
  
  ### variables ###
  # Assign variable:
  assign={}
  for r in resources:
      assign = [solver.IntVar(0, 1, 'Assign[%r][%d]' % (r, j)) for j in items]
  
  # objective: minimize number of techs:
  z = solver.Sum((value[i] * assign[r][i]) for i in items for r in resources)
 
  ### constraints ###
  # Assign:
  for j in value:
      solver.Add(solver.Sum(assign[r][j] == 1 for r in resources))
 
  # Bin capacity:
  for r in resources:
      solver.Add(solver.Sum(value[j] * assign[r][j] for j in value) <= capacity[r])
  
  ## Objective:
  objective = solver.Maximize(z)
  #
  # solution and search
  #
  solver.Solve()

  print()
  print('z: ', int(solver.Objective().Value()))

  print()
  print('walltime  :', solver.WallTime(), 'ms')
  if sol == 'CBC':
    print('iterations:', solver.Iterations())

if __name__ == '__main__':
  sol = 'GLPK'
  if len(sys.argv) > 1:
    sol = sys.argv[1]
    if sol != 'GLPK' and sol != 'CBC':
      print('Solver must be either GLPK or CBC')
      sys.exit(1)
  main(sol)


Running the code gives me the following error message:
    z = solver.Sum((value[i] * assign[r][i]) for i in items for r in ressources)
TypeError: 'Variable' object does not support indexing

I assume that the variable 'assign' is not created correctly. Does anybody has a suggestion on how to fix this issue? Thank you in advance.


Laurent Perron

unread,
Jul 24, 2018, 9:11:51 PM7/24/18
to or-tools...@googlegroups.com
 assign = [solver.IntVar(0, 1, 'Assign[%r][%d]' % (r, j)) for j in items]

'assign' is a single dimension array.

--
You received this message because you are subscribed to the Google Groups "or-tools-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to or-tools-discu...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Hendrik B

unread,
Jul 25, 2018, 10:58:19 AM7/25/18
to or-tools-discuss
Thank you Laurent, I was trying a couple of different things and must have missed that part. This is the implementation that works (including two constraints that had a wrong index):

  assign={}
  for r in resources:
      assign[r] = [solver.IntVar(0, 1, 'Assign[%r][%d]' % (r, j)) for j in items]

 
  # objective: minimize number of techs:
  z = solver.Sum((value[i] * assign[r][i]) for i in items for r in resources)

  ### constraints ###
  # Assign:
  for j in items:
      solver.Add(solver.Sum(assign[r][j] for r in resources)  == 1)
  for r in resources:
      solver.Add(solver.Sum(value[j] * assign[r][j] for j in items) <= capacity[r])

Hendrik B

unread,
Jul 27, 2018, 12:05:40 PM7/27/18
to or-tools-discuss
How would I convert this into a 3D variable? If I understand correctly, for the 2D version, I created an empty list and appended a list inside the resources for-loop:
 
  assign = {}
 
for r in resources:
      assign
[r] = [solver.BoolVar('Assign[%r][%d]' % (r, j)) for j in items]

 Now, for the 3D version, what kind of list do I create initially and do I have to append an empty list in-between the for-loops? I tried the following two version, which do not work:

Version 1:
  #3D Variable assign (attempt 1):
  assign
= {}
 
for r in resources:
     
for i in items:
          assign
[r][i] = [solver.IntVar(0, 1, 'Assign[%r][%i][%d]' % (r, i, j)) for j in items]

Version 2:
  #3D Variable assign (attempt 1):
  assign
= defaultdict(list)
 
for r in resources:
     
for i in items:
          assign
[r][i].append(solver.IntVar(0, 1, 'Assign[%r][%i][%d]' % (r, i, j)) for j in items)

 

Laurent Perron

unread,
Jul 27, 2018, 1:15:38 PM7/27/18
to or-tools-discuss
assign[(i, j)] = ...
Laurent Perron | Operations Research | lpe...@google.com | (33) 1 42 68 53 00



--
Reply all
Reply to author
Forward
0 new messages