0

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.

daydayup
  • 2,049
  • 5
  • 22
  • 47
  • 2
    There are so many solutions to your example that listing them all is probably not interesting. What are you really trying to solve? – Henry Apr 22 '16 at 11:53
  • 1
    E.g., do you want to *find* the solutions or, perhaps, just *count* them? – Gareth McCaughan Apr 22 '16 at 11:56
  • I really need to find all combinations of the solutions. I am solving an optimization problem where the objective is hard to model and the constraints are hidden so I am getting all possible combinations and bruteforcefullly find the best. – daydayup Apr 22 '16 at 12:08
  • I just edited the question to make it a less scary case... thank you – daydayup Apr 22 '16 at 12:10

3 Answers3

2

If you really want to have all solutions: recursively enumerate all possible variable assignments with some optimizations:

  1. The value of the last variable can be calculated from the sum constraint
  2. The search can be pruned, when you see that the partial assignment can no longer lead to a valid solution (e.g if the sum is already larger than 10 or if there are too few variables left to reach a sum of 10)
Henry
  • 42,982
  • 7
  • 68
  • 84
1

You are looking for the permutations of the integer partitions of the number 100, where each integer partition has

  • at most 10 parts; and
  • each part is at most 15.

There are certainly a lot of cases, but 10! of them are still manageable by computers.

Edit: OP has edited the question, so: the number 10 should be broken up into integer partitions with at most 10 parts, where each part is at most 2.

Matsmath
  • 1,164
  • 2
  • 21
  • 40
1

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...)

btilly
  • 43,296
  • 3
  • 59
  • 88