question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Simple boolean problem has no solution when it should

See original GitHub issue

Describe the bug I have an optimization problem with boolean variables that appears to produce no solution when it should. It’s not overconstrained. If I run the problem with PuLP, it finds a solution.

To Reproduce Here’s a unittest that runs the same problem through pulp and mip. The mip test fails.

Maybe I am not setting up the constraints right for mip? In particular I am thinking there could be something wrong with the constrain_equal_sums since it’s setting two sums equal to each other?

In any case the PuLP version works though.

from unittest import TestCase

import mip
import pulp


class IpModelTestCase(TestCase):
    def setUp(self):
        self.count = 20 # how many boolean variables we will have

        self.constrain_sums = [[0, 2, 4, 6, 8, 10, 12, 14, 16, 18],
                               [1, 3, 5, 7, 9, 11, 13, 15, 17, 19],
                               [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 0],
                               [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 19, 2],
                               [5, 7, 9, 11, 13, 15, 17, 19, 3],
                               [6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 19, 4],
                               [7, 9, 11, 13, 15, 17, 19, 5],
                               [8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 6],
                               [9, 11, 13, 15, 17, 19, 7],
                               [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 8],
                               [11, 13, 15, 17, 19, 9],
                               [12, 13, 14, 15, 16, 17, 18, 19, 10],
                               [13, 15, 17, 19, 11],
                               [14, 15, 16, 17, 18, 19, 12],
                               [15, 17, 19, 13],
                               [16, 17, 18, 19, 14],
                               [17, 19, 15],
                               [18, 19, 16],
                               [19, 17]]
        self.constrain_equal_sums = [([1], [0]),
                                     ([3], [2]),
                                     ([5], [4]),
                                     ([7], [6]),
                                     ([9], [8]),
                                     ([11], [10]),
                                     ([13], [12]),
                                     ([15], [14]),
                                     ([17], [16]),
                                     ([19], [18])]

    def test_mip(self):
        model = mip.Model('mip')
        rewards = [3] * self.count
        variables = [model.add_var(var_type=mip.BINARY) for _ in range(self.count)]

        # set the objective function
        mip.maximize(mip.xsum(rewards[i] * variables[i] for i in range(self.count)))

        # constraints
        for indexes in self.constrain_sums:
            model.add_constr(mip.xsum(variables[i] for i in indexes) <= 1)

        for indexes_1, indexes_2 in self.constrain_equal_sums:
            model.add_constr(mip.xsum(variables[i] for i in indexes_1) == mip.xsum(variables[i] for i in indexes_2))

        # solve it
        model.optimize()
        selected = [i for i, var in enumerate(variables) if var.x > 0.99]

        # this fails because selected is empty
        self.assertEqual(2, len(selected))

    def test_pulp(self):
        model = pulp.LpProblem('pulp', pulp.LpMaximize)
        rewards = [3] * self.count

        variables = pulp.LpVariable.dicts('option', indexs=[str(i) for i in range(self.count)], cat=pulp.LpBinary)

        # set the objective function
        model += pulp.lpSum([rewards[i] * variables[str(i)] for i in range(self.count)])

        # constraints
        for indexes in self.constrain_sums:
            model += pulp.lpSum(variables[str(i)] for i in indexes) <= 1

        for indexes_1, indexes_2 in self.constrain_equal_sums:
            model += pulp.lpSum(variables[str(i)] for i in indexes_1) == pulp.lpSum(variables[str(i)] for i in indexes_2)

        # solve it
        model.solve(pulp.PULP_CBC_CMD())
        selected = [int(i) for i, var in variables.items() if var.varValue > 0.99]

        # this works because selected = [0, 1]
        self.assertEqual(2, len(selected))
        self.assertEqual([0, 1], selected)

Expected behavior I expect the boolean problem to have a solution

Versions

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.3 LTS
Release:        20.04
Codename:       focal

$ python --version
Python 3.6.9

$ pip freeze | grep mip
mip==1.13.0

Additional context can’t think of anything. The repro above should be straightforward.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
jesseherschcommented, Oct 1, 2021

ok so I am not setting the objective function correctly? I guess it should be this:

model.objective = mip.maximize(mip.xsum(rewards[i] * variables[i] for i in range(self.count)))
0reactions
tuliotoffolocommented, Oct 1, 2021

No problem. Issue closed. 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

Example Problems Boolean Expression Simplification
Boolean Expression Simplification using AND, OR, ABSORPTION and DEMORGANs THEOREM.
Read more >
Boolean algebra #2: Basic problems - YouTube
visit http://www.keleshev.com/ for structured list of tutorials on Boolean algebra and digital hardware design!
Read more >
Boolean Algebra and Reduction Techniques
The first step to reducing a logic circuit is to write the Boolean Equation for the logic function. The next step is to...
Read more >
Laws of Boolean Algebra - Electronics Tutorials
Electronics Tutorial about the Laws of Boolean Algebra and Boolean Algebra Rules including de Morgans Theorem and Boolean Circuit Equivalents.
Read more >
5-1 Boolean expressions
In this chapter, I will show how to use a variable in a boolean ... While using if statements is a perfectly valid...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found