Question

For a given n and m I iterate over all n by m partial circulant matrices with entries that are either 0 or 1. I want to find if there is a matrix such that there are no two subsets of the columns that have the same sum. Here when we add columns we just do it elementwise. My current code uses constraint programming via ortools. Here is my code.

from scipy.linalg import circulant
import numpy as np
import itertools
from ortools.constraint_solver import pywrapcp as cs

n = 4
m = 6

def isdetecting(matrix):
    solver = cs.Solver("scip")
    X = np.array([solver.IntVar(values) for i in range(matrix.shape[1])])
    X1 = X.tolist()
    for row in matrix:
        x = X[row].tolist()
        solver.Add(solver.Sum(x) == 0)
    db = solver.Phase(X1, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_CENTER_VALUE)
    solver.NewSearch(db)
    count = 0
#Find just one non-zero solution if there is one
    while (solver.NextSolution() and count < 2):
        solution = [x.Value() for x in X1]
        count += 1
    solver.EndSearch()
    if (count == 1):
        return True

values = [-1,0,1]
nosols = 0
for row in itertools.product([0,1],repeat = m):
    M = np.array(circulant(row)[0:n], dtype=bool)
    if isdetecting(M):
        nosols += 1
        print M.astype(int)

The line values = [-1,0,1] allows any number of zeros in the solutions. How can I specify an exact number of zeros that are permitted in a solution instead?

Was it helpful?

Solution

In or-tools/Python there is a global constraint solver.Count() which might be used. Example:

 the_count = 1 # number of 0's allowed
 solver.Add(solver.Count(X1, 0,the_count))

Where "the_count" is the number of 0's to allow in the (flat) array "X1". the_count can be either a constant or a decision variable (so you can constrain that value with further constraints, or just letting the domains do the work of constraining the count, e.g. the domain 1..4 constrain the count to between 1 and 4 occurrences).

"X1" is the array of decision variables which are checked. The second parameter, "0", is the value to count in X.

An example of the usage of solver.Count(): http://hakank.org/or-tools/young_tableaux.py .

There is also a generalization of solver.Count(), namely solver.Distribute (a.k.a. Global Cardinality Count, GCC) where you can count/constrain more than one value at the same time. See my deBruijn sequence model for an example how it's used: http://hakank.org/or-tools/debruijn_binary.py .

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top