Search code examples
algorithmequation-solvinginteger-programming

how to find all integer solutions to sum(xi) =b, with linear constraints


Suppose sum(xi) = 10, 0<= xi <= 2, i = 1, 2, ..., 10. How to find all integer solutions for xi. thank you. I have read about Euclidean algorithm, but it looks like just for two unknown variables. What algorithms can be used here.


Solution

  • Recursion is best. Here is the natural Python solution with generators:

    def solutions(variables, sum_left, max_value):
        if 0 == variables:
            if 0 == sum_left:
                yield []
        else:
            for i in range(0, max_value + 1):
                if sum_left < i:
                    break
                else:
                    for partial_solution in solutions(variables - 1, sum_left - i,
                                                      max_value):
                        yield [i] + partial_solution
    
    for x in solutions(10, 10, 2):
        print(x)
    

    The benefit of generators being that you don't have to build a long list in memory first. Here is an alternate solution which does not use generators and also avoids building up the list.

    def do_something_for_solutions(variables, sum_left, max_value, known=None):
        if known is None:
            known = []
        if 0 == variables:
            if 0 == sum_left:
                do_something(known)
        else:
            for i in range(0, max_value + 1):
                if sum_left < i:
                    break
                else:
                    do_something_for_solutions(variables - 1, sum_left - i,
                                               max_value, known + [i])
    
    def do_something(solution):
        print(solution)
    
    do_something_for_solutions(10, 10, 2)
    

    If you choose to return solutions, that is possible as follows:

    def solutions(variables, sum_left, max_value):
        if 0 == variables:
            if 0 == sum_left:
                return [[]]
            else:
                return []
        else:
            answer = []
            for i in range(0, max_value + 1):
                if sum_left < i:
                    break
                else:
                    for partial_solution in solutions(variables - 1, sum_left - i,
                                                      max_value):
                        answer.append([i] + partial_solution)
            return answer
    
    for x in solutions(10, 10, 2):
        print(x)
    

    (Be warned that if you change the parameters, that list can easily become huge...)