sarl
sarl

Reputation: 23

add_modulo_equality not working with python OR-Tools CP-SAT

I'm trying to solve a problem which relies on the sum of the row entries being 0 mod (n). I have tried to write a simplified version, but cannot figure out to use model.AddModuloEquality. For example, the following code, (adapted from Google's Suduko example), should give me the array [[10,14][11,13]]. It works. if I add the constraint, should it to 24, but not if I try and make it equal 0 mod 12, when should it be the same answer? First day using ORtools and beign away from Python for a while.

from ortools.sat.python import cp_model

def basic_mod(rows,columns, mod=None):
    # Create the model.
    model = cp_model.CpModel()
    ay=[]
    rows = rows
    cols=columns
    row = list(range(0, rows))
    col= list(range(0,cols))
    mod=mod
    
#create vars
    grid = {}
    for i in row:
        for j in col:
            grid[(i, j)] = model.new_int_var(10,14, "grid %i %i" % (i, j))
            
#constraints    
    # no repeats in row
    for i in row:
        model.add_all_different(grid[(i, j)] for j in col)

    # # no repeats in column
    for j in col:
        model.add_all_different(grid[(i, j)] for i in row)
    
    #sum of row
    for i in row:
        sum_of_row_vars = sum(grid[(i, j)] for j in col)            
        #model.Add(sum_of_row_vars == 24)
        model.AddModuloEquality(sum_of_row_vars, 0,12)
        

   # No repeats in  whole array.
   #add a variable to each cell
    array = []
    for i in row:
        for j in col:
            array.append(grid[(i, j)])

    model.add_all_different(array)

    # Solves and prints out the FIRST solution.
    solver = cp_model.CpSolver()
    status = solver.solve(model)
    if status == cp_model.OPTIMAL:
        for i in row:
            print([int(solver.value(grid[(i, j)])) for j in col])
            ay.append([int(solver.value(grid[(i, j)])) for j in col])
    
    else:
        print("no solution")


    return ay 
rows=2
cols=2
mod=12
basic_mod(rows,cols,mod)

Upvotes: 0

Views: 103

Answers (1)

Laurent Perron
Laurent Perron

Reputation: 11034

it is target = var % mod for add_modulo_equality(target, var, mod)

so add_modulo_equality(0, var, 12)

Here is a working code:

from ortools.sat.python import cp_model


def basic_mod(rows,columns, mod=None):
    # Create the model.
    model = cp_model.CpModel()
    ay=[]
    rows = rows
    cols=columns
    row = list(range(0, rows))
    col= list(range(0,cols))
    mod=mod
    
#create vars
    grid = {}
    for i in row:
        for j in col:
            grid[(i, j)] = model.new_int_var(10,14, "grid %i %i" % (i, j))
            
#constraints    
    # no repeats in row
    for i in row:
        model.add_all_different(grid[(i, j)] for j in col)

    # # no repeats in column
    for j in col:
        model.add_all_different(grid[(i, j)] for i in row)
    
    #sum of row
    for i in row:
        sum_of_col: cp_model.IntVar = model.new_int_var(0, cols * 14, f'sum_{i}')
        model.add(sum_of_col == sum(grid[(i, j)] for j in col)            )
        model.add_modulo_equality(0, sum_of_col, 12)
        

   # No repeats in  whole array.
   #add a variable to each cell
    array = []
    for i in row:
        for j in col:
            array.append(grid[(i, j)])

    model.add_all_different(array)

    # Solves and prints out the FIRST solution.
    solver = cp_model.CpSolver()
    solver.parameters.log_search_progress = True
    status = solver.solve(model)
    if status == cp_model.OPTIMAL:
        for i in row:
            print([int(solver.value(grid[(i, j)])) for j in col])
            ay.append([int(solver.value(grid[(i, j)])) for j in col])
    
    else:
        print("no solution")


    return ay 
rows=2
cols=2
mod=12
basic_mod(rows,cols,mod)

it displays

[14, 10]
[13, 11]

Upvotes: 0

Related Questions