A parallel branch-and-bound engine for Python.

Overview

pybnb

PyPI-Status PyPI-Versions PyPI-Downloads

Testing-Status Coverage-Status Documentation-Status

Codacy-Grade Mypy Black

A parallel branch-and-bound engine for Python. (https://pybnb.readthedocs.io)

This software is copyright (c) by Gabriel A. Hackebeil ([email protected]).

This software is released under the MIT software license. This license, including disclaimer, is available in the 'LICENSE' file.

Quick Start

Define a problem:

# simple.py

import pybnb
class Simple(pybnb.Problem):
    def __init__(self):
        self.bounds = [0.0,1.0]
    def sense(self):
        return pybnb.minimize
    def objective(self):
        return round(self.bounds[1] - self.bounds[0], 3)
    def bound(self):
        return -(self.bounds[1] - self.bounds[0])**2
    def save_state(self, node):
        node.state = self.bounds
    def load_state(self, node):
        self.bounds = node.state
    def branch(self):
        L, U = self.bounds
        mid = 0.5 * (L + U)
        for l,u in [(L,mid), (mid,U)]:
            child = pybnb.Node()
            child.state = (l,u)
            yield child

Write a solve script:

# solve_simple.py

import simple
problem = simple.Simple()
results = pybnb.solve(problem,
                      absolute_gap=1e-9)

Run the script:

$ mpirun -np 4 python solve_simple.py

Using non-default solver options:
 - absolute_gap: 1e-09 (default: 0)

Starting branch & bound solve:
 - dispatcher pid: 34902 (Ozymandias.local)
 - worker processes: 3
---------------------------------------------------------------------------------------------------------------------------
         Nodes        |                      Objective Bounds                        |              Work
      Expl    Unexpl  |      Incumbent           Bound     Rel. Gap         Abs. Gap | Time (s)  Nodes/Sec Imbalance   Idle
         0         1  |            inf            -inf          inf%             inf |      0.0       0.00     0.00%      0
*        1         2  |              1              -1  200.0000000%               2 |      0.0    1226.99   300.00%      1
*        2         3  |            0.5              -1  150.0000000%             1.5 |      0.0    2966.04   150.00%      0
*        4         5  |           0.25           -0.25   50.0000000%             0.5 |      0.0    8081.95    75.00%      0
*        8         9  |          0.125         -0.0625   18.7500000%          0.1875 |      0.0   12566.90    37.50%      0
      Expl    Unexpl  |      Incumbent           Bound     Rel. Gap         Abs. Gap | Time (s)  Nodes/Sec Imbalance   Idle
*       16        17  |          0.062       -0.015625    7.7625000%        0.077625 |      0.0   15352.74    18.75%      0
*       32        33  |          0.031     -0.00390625    3.4906250%      0.03490625 |      0.0   15981.49    18.75%      0
*       64        65  |          0.016   -0.0009765625    1.6976563%    0.0169765625 |      0.0   18740.68    18.75%      0
*      128       129  |          0.008   -0.0002441406    0.8244141%  0.008244140625 |      0.0   21573.51    11.72%      0
*      256       257  |          0.004   -6.103516e-05    0.4061035%  0.004061035156 |      0.0   22166.96     8.20%      0
      Expl    Unexpl  |      Incumbent           Bound     Rel. Gap         Abs. Gap | Time (s)  Nodes/Sec Imbalance   Idle
*      512       513  |          0.002   -1.525879e-05    0.2015259%  0.002015258789 |      0.0   21177.00     5.86%      0
*     1024      1025  |          0.001   -3.814697e-06    0.1003815%  0.001003814697 |      0.1   19978.42     9.38%      0
*     2048      2049  |              0   -9.536743e-07    0.0000954% 9.536743164e-07 |      0.1   21606.45     5.42%      0
     24029     24030  |              0   -1.490116e-08    0.0000015% 1.490116119e-08 |      1.1   21961.03     5.98%      0
     46159     46160  |              0    -3.72529e-09    0.0000004% 3.725290298e-09 |      2.1   22120.75     5.73%      0
      Expl    Unexpl  |      Incumbent           Bound     Rel. Gap         Abs. Gap | Time (s)  Nodes/Sec Imbalance   Idle
     65537     65538  |              0   -9.313226e-10    0.0000001% 9.313225746e-10 |      3.0   22459.50     6.20%      0
---------------------------------------------------------------------------------------------------------------------------

Absolute optimality tolerance met
Optimal solution found!

solver results:
 - solution_status: optimal
 - termination_condition: optimality
 - objective: 0
 - bound: -9.313226e-10
 - absolute_gap: 9.313226e-10
 - relative_gap: 9.313226e-10
 - nodes: 65537
 - wall_time: 2.96 s
 - best_node: Node(objective=0)

Number of Workers:        3
Load Imbalance:       6.20%
 - min: 21355 (proc rank=3)
 - max: 22710 (proc rank=1)
Average Worker Timing:
 - queue:      80.78% [avg time: 109.6 us, count: 65537]
 - load_state:  0.44% [avg time: 596.1 ns, count: 65537]
 - bound:       0.59% [avg time: 796.1 ns, count: 65537]
 - objective:   3.52% [avg time:   4.7 us, count: 65537]
 - branch:      3.36% [avg time:   4.6 us, count: 65537]
 - other:      11.31% [avg time:  15.3 us, count: 65537]
Comments
  • Redesigning Node Serialization

    Redesigning Node Serialization

    This is a major rewrite of the serialization strategy for nodes.

    Improvements include:

    • much faster serial performance (especially with pypy)
    • removed numpy as a dependency
    • any pickle-able object can be assigned to node.state (no longer needs to be a numpy float array)
      • old way:
      def save_state(self, node):
          node.resize(2)
          node.state[:] = (self.lb, self.ub)
      def load_state(self, node):
          self.lb, self.ub = node.state[:]
      
      • new way:
      def save_state(self, node):
          node.state = (self.lb, self.ub)
      def load_state(self, node):
          self.lb, self.ub = node.state
      
    • lexicographic node priorities can now be used (fixes #4):
      • example: solver.solve(problem, queue_strategy=('bound','objective'))
    • added a config object to allow users to adjust serialization settings (e.g., use dill instead of pickle)
    opened by ghackebeil 6
  • Getting the answers & path out?

    Getting the answers & path out?

    Hey, cool library!

    Maybe I'm missing something here, but it doesn't seem like there's any way to get the answers or the path to the answers out? SolverResults doesn't have the best node and there's no bookeeping to keep the chain of nodes?

    opened by MisterTea 4
  • Access solver attributes within problem

    Access solver attributes within problem

    Hi ! Thank you for the development of this package ! I was wondering if there was a way to call the solver attributes inside the problem methods. For instance, I would like to have access to the best objective within the bound method in the following way :

    class Problem(pybnb.Problem):
        ...
        def bound(self):
            best_objective = self.retrieve_solver_attribute("best_objective")
            return do_bounding_using_best_objective()
        ...
    

    Thank you for your answer, Théo

    opened by TheoGuyard 2
  • Obtain optimal assignment

    Obtain optimal assignment

    Hi Gabriel

    Thanks for a great project!

    I am struggling to find a way to obtain the variables' assignments once I have solved the example knapsack problem and obtained an optimal solution. Somehow I cannot access the decision variables' values leading to the obtained optimal objective value.

    I am assuming there must be a way to obtain the values of each integer variables in the results object, but I cannot figure out how. I have gone through the documentation, but can't seem to find anything. Any help? :)

    opened by alexberndt 2
  • Option to disable queue bound tracking

    Option to disable queue bound tracking

    This PR adds a solver option, track_bound, that allows one to disable functionality that tracks the global queue bound until the solve terminates. This can significantly reduce the overhead for certain queue implementations (except for worst-bound first, which tracks the bound for free).

    opened by ghackebeil 1
  • [WIP] Drop Support for Python 2.x

    [WIP] Drop Support for Python 2.x

    This PR tracks changes that can be made when support for Python 2 is dropped at the end of 2019. So far, changes are almost entirely cosmetic:

    • drop enum34 and six dependency
    • replace class Name(object): with class Name:
    • drop 2 or 3 lines that dealt with bytes <-> str casting
    • use keyword-only arguments

    Type annotations are not included in this PR as they are not entirely supported in Python 3.5. In particular, x: <type> = <value> is only supported outside function declarations in Python 3.6+.

    opened by ghackebeil 1
  • Issue when bound() and objective() methods return numpy types (parallel only)

    Issue when bound() and objective() methods return numpy types (parallel only)

    If the objective/bound computation uses NumPy and happens to return, for instance, a numpy.float64 type, this creates issues when serializing these node attributes through marshal.dumps(...). When the dispatcher receives the node, the call to marshal.loads produces an object of type bytes rather than a number that can be used for computation.

    I think the best fix is to add some code on the worker side that appropriately casts the objective/bound value returned from the problem to an int or float built-in type (possibly do the same with the queue_priority attribute in case the user sets this).

    An alternative would be to use pickle to serialize these node attributes, but I believe this can be noticeable slower than marshal (double check this).

    bug 
    opened by ghackebeil 1
  • Knapsack example

    Knapsack example

    Can you include a knapsack implementation in your examples? I'm struggling a bit with the documentation. It would be helpful for newcomers to familiarize with your library.

    opened by ggaylord 1
  • Formalize nested solver implementation

    Formalize nested solver implementation

    Things to address:

    • [ ] Setting up the communicator tree and listeners could be made easier
    • [ ] Allow load balance and timing statistics to be sent up to the root solver
    TODO 
    opened by ghackebeil 1
  • Allow lexicographic node prioritization in the queue

    Allow lexicographic node prioritization in the queue

    This would require allowing a tuple to be assigned to Node.queue_priority rather than just a number. One could utilize this either by implementing a custom queue strategy, or by setting the queue_strategy option to a tuple of queue strategy names.

    TODO 
    opened by ghackebeil 0
  • Automatically save the best node

    Automatically save the best node

    It can currently be done by the user using optional Problem methods, but it should probably done by the solver.

    Possible implementation:

    • When a worker thinks it has a new best node, send it to the dispatcher on the next update.
    • The dispatcher sends the best node to workers on the final update (or possibly earlier with every update).
    • If load_solution=True (new solver options, default True), load_state will be called with this node rather than the root at the end of the solve. If load_solution=False, the node will be placed on the results object.
    TODO 
    opened by ghackebeil 0
  • Multihreading instead of multiprocessing

    Multihreading instead of multiprocessing

    Hi there, Will there ever be a multithreading support instead of the already implemented multiprocess version? This may be very useful if multiple nodes share a child, and the bound() function makes use of all parents infos.

    opened by DarioSimonato 1
Releases(0.6.2)
  • 0.6.2(Dec 10, 2019)

  • 0.6.1(Mar 30, 2019)

  • 0.6.0(Mar 12, 2019)

    This is a major release that changes default optimality and tolerance settings to make solver behavior more intuitive. It also includes a new option for reducing dispatcher overhead for non-default queue strategies.

    Source code(tar.gz)
    Source code(zip)
  • 0.5.2(Feb 13, 2019)

    This is a minor release that adds a configuration option to enable compression and fixes a serialization issues when the bound or objective Problem methods return NumPy scalar types.

    Source code(tar.gz)
    Source code(zip)
  • 0.5.1(Feb 11, 2019)

    This is a minor release that includes some improvements to the documentation as well as fixes for some edge case behavior for unbounded problems.

    Source code(tar.gz)
    Source code(zip)
  • 0.5.0(Feb 10, 2019)

    This is a major release that includes some backward incompatible changes. Major changes include:

    • automatically saving the best node (rather than just the best objective)
    • changing the signature of the branch method so that it has more clear semantics
    • removing / renaming some of the optional problem callbacks
    • adding built-in support for nested solver implementations
    Source code(tar.gz)
    Source code(zip)
  • 0.4.0(Jan 31, 2019)

  • 0.3.0(Jan 21, 2019)

    This is a major release that includes some backward incompatible changes. Major changes include

    • renaming of a few solver options
    • addition of options for early termination of a solve
    • new queue management strategies
    • improvements to the online documentation
    Source code(tar.gz)
    Source code(zip)
  • 0.2.9(Dec 3, 2018)

  • 0.2.8(Nov 26, 2018)

  • 0.2.7(Nov 26, 2018)

  • 0.2.6(Jul 13, 2018)

    This minor release includes changes that improve dispatcher performance. It also includes an additional queue strategy that prioritizes nodes with the best objective first.

    Source code(tar.gz)
    Source code(zip)
  • 0.2.5(May 30, 2018)

  • 0.2.4(May 26, 2018)

    This release fixes a bug in pyomo_tools that left uncollected messages on the communicator. See the CHANGELOG for additional details about this release.

    Source code(tar.gz)
    Source code(zip)
  • 0.2.3(May 22, 2018)

  • 0.2.2(May 22, 2018)

  • 0.2.0(May 22, 2018)

Owner
Gabriel Hackebeil
Gabriel Hackebeil
This project intends to take the user's CEP (brazilian adress code) and return the local in which the CEP is placed.

This project aims to simply return the CEP's (the brazilian resident adress code) User of the application. The project uses a request and passes on to

Daniel Soares Saldanha 4 Nov 17, 2021
Contains the code of my learning of Python OOP.

OOP Python This repository contains the code of my learning of Python OOP. All the code: is following PEP 8 ✅ has proper concept illustrations and com

Samyak Jain 2 Jan 15, 2022
Learning with Peter Norvig's lis.py interpreter

Learning with lis.py This repository contains variations of Peter Norvig's lis.py interpreter for a subset of Scheme, described in (How to Write a (Li

Fluent Python 170 Dec 15, 2022
Files for QMC Workshop 2021

QMC Workshop 2021 This repository contains the presented slides and example files for the Quantum Monte Carlo (QMC) Workshop 5 October - 23 November,

QMCPACK 39 Nov 04, 2022
Run python scripts and pass data between multiple python and node processes using this npm module

Run python scripts and pass data between multiple python and node processes using this npm module. process-communication has a event based architecture for interacting with python data and errors ins

Tyler Laceby 2 Aug 06, 2021
A replacement of qsreplace, accepts URLs as standard input, replaces all query string values with user-supplied values and stdout.

Bhedak A replacement of qsreplace, accepts URLs as standard input, replaces all query string values with user-supplied values and stdout. Works on eve

Eshan Singh 84 Dec 31, 2022
Chemical equation balancer

Chemical equation balancer Balance your chemical equations with ease! Installation $ git clone

Marijan Smetko 4 Nov 26, 2022
Pyjiting is a experimental Python-JIT compiler, which is the product of my undergraduate thesis

Pyjiting is a experimental Python-JIT compiler, which is the product of my undergraduate thesis. The goal is to implement a light-weight miniature general-purpose Python JIT compiler.

Lance.Moe 10 Apr 17, 2022
Simple kivy project to help new kivy users build android apps with python.

Kivy Calculator A Simple Calculator made with kivy framework.Works on all platforms from Windows/linux to android. Description Simple kivy project to

Oussama Ben Sassi 6 Oct 06, 2022
UF3: a python library for generating ultra-fast interatomic potentials

Ultra-Fast Force Fields (UF3) S. R. Xie, M. Rupp, and R. G. Hennig, "Ultra-fast interpretable machine-learning potentials", preprint arXiv:2110.00624

Ultra-Fast Force Fields 24 Nov 13, 2022
100 Days of Python Programming

100 days of Python Following the initiative of my friend Helber Belmiro, who is almost done with his 100 days of Java, I have decided to start my 100

Henrique Pereira 19 Nov 08, 2021
Goddard A collection of small, simple strategies for Freqtrade

Goddard A collection of small, simple strategies for Freqtrade. Simply add the strategy you choose in your strategies folder and run. ⚠️ General Crypt

Shane Jones 118 Dec 14, 2022
Replit theme sync; Github theme sync but in Replit.

This is a Replit theme sync, basically meaning that it keeps track of the current time (which may need to be edited later on), and if the time passes morning, afternoon, etc, the theme switches. The

Glitch 8 Jun 25, 2022
A docker container (Docker Desktop) for a simple python Web app few unit tested

Short web app using Flask, tested with unittest on making massive requests, responses of the website, containerized

Omar 1 Dec 13, 2021
Tenda D151 & D301 - Unauthenticated configuration download

Exploit Title: Tenda D151 & D301 - Unauthenticated configuration download (login included)

Ayoub 3 Jul 14, 2022
Small scripts to learn about GNOME internals

gnome-hacks This is a collection of APIs that allow programmatic manipulation of the GNOME shell. If you use GNOME (the default graphical shell in Ubu

Alex Nichol 5 Oct 22, 2021
The goal of this program was to find the most common color in my living room.

The goal of this program was to find the most common color in my living room. I found a dataset online with colors names and their corr

1 Nov 09, 2021
Resources for the 2021 offering of COMP 598

comp598-2021 Resources for the 2021 offering of COMP 598 General submission instructions Important Please read these instructions located in the corre

Derek Ruths 23 May 18, 2022
Minterpy - Multidimensional interpolation in Python.

minterpy is an open-source Python package for a multivariate generalization of the classical Newton and Lagrange interpolation schemes as well as related tasks.

Center for Advanced Systems Understanding 18 Jan 06, 2023
SHF TEST BACKEND

➰ SHF TEST BACKEND ➿ 🐙 Goals Dada una matriz de números enteros. Obtenga el elemento máximo en la matriz que produce la suma más pequeña al agregar t

Wilmer Rodríguez S 1 Dec 19, 2021