# Copyright 2010 Hakan Kjellerstrand hakank@bonetmail.com # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Set covering in Google CP Solver. Problem from Katta G. Murty: 'Optimization Models for Decision Making', page 302f http://ioe.engin.umich.edu/people/fac/books/murty/opti_model/junior-7.pdf 10 senators making a committee, where there must at least be one representative from each group: group: senators: southern 1 2 3 4 5 northern 6 7 8 9 10 liberals 2 3 8 9 10 conservative 1 5 6 7 democrats 3 4 5 6 7 9 republicans 1 2 8 10 The objective is to minimize the number of senators. Compare with the following models: * MiniZinc: http://www.hakank.org/minizinc/set_covering3_model.mzn (model) http://www.hakank.org/minizinc/set_covering3.mzn (data) * Comet : http://www.hakank.org/comet/set_covering3.co * ECLiPSe : http://www.hakank.org/eclipse/set_covering3.ecl * SICStus : http://hakank.org/sicstus/set_covering3.pl * Gecode : http://hakank.org/gecode/set_covering3.cpp This model was created by Hakan Kjellerstrand (hakank@bonetmail.com) Also see my other Google CP Solver models: http://www.hakank.org/google_or_tools/ """ from constraint_solver import pywrapcp def main(unused_argv): # Create the solver. solver = pywrapcp.Solver('Set covering') # # data # num_groups = 6 num_senators = 10 # which group does a senator belong to? belongs = [ [1, 1, 1, 1, 1, 0, 0, 0, 0, 0], # 1 southern [0, 0, 0, 0, 0, 1, 1, 1, 1, 1], # 2 northern [0, 1, 1, 0, 0, 0, 0, 1, 1, 1], # 3 liberals [1, 0, 0, 0, 1, 1, 1, 0, 0, 0], # 4 conservative [0, 0, 1, 1, 1, 1, 1, 0, 1, 0], # 5 democrats [1, 1, 0, 0, 0, 0, 0, 1, 0, 1] # 6 republicans ] # # declare variables # x = [solver.IntVar(0, 1, 'x[%i]' % i) for i in range(num_senators)] # # constraints # # number of assigned senators (to minimize) z = solver.Sum(x) # ensure that each group is covered by at least # one senator for i in range(num_groups): solver.Add( solver.SumGreaterOrEqual([x[j]*belongs[i][j] for j in range(num_senators)], 1)) objective = solver.Minimize(z, 1) # # solution and search # solution = solver.Assignment() solution.Add(x) solution.AddObjective(z) collector = solver.LastSolutionCollector(solution) solver.Solve(solver.Phase(x, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT), [collector, objective]) print "z:", collector.ObjectiveValue(0) print "x:", [collector.Value(0, x[i]) for i in range(num_senators)] for j in range(num_senators): if collector.Value(0, x[j]) == 1: print "Senator", j+1, "belongs to these groups:", for i in range(num_groups): if belongs[i][j] == 1: print i + 1, print print print "failures:", solver.Failures() print "branches:", solver.Branches() print "WallTime:", solver.WallTime() if __name__ == '__main__': main("cp sample")