Overview
Dippy is actually two python modules, a pure Python module called dippy
and a binary extension module named _dippy. This is a common technique
which allows parts of the module to be written in pure Python.
The C++ code compiles to _dippy.so or _dippy.pyd, depending on the
platform. At the top of the pure python module, dippy.py, is the following line:
which means that all names exported by _dippy will now also be accessible
from the dippy module. dippy.py also includes Python code which
wraps some of the functions from _dippy, as well as the definition of DipProblem.
The code should be fairly well commented so this section gives a general overview
of the different pieces of code.
dippy.py
This module is the pure Python component of the Dippy module. Where possible, we
do things here that would be hard (or very verbose) using the C API. An overview
of the contents follow. Details are provided in the code comments.
- DipError
- Our custom exception class
- Solve
- This function wraps the solve function defined in the extension module and
is responsible for some argument pre-processing and solution post-processing.
- DipProblem
- This class extends pulp.LpProblem. It contains a lot of convenience
functions for transforming the problem data into data structures that
are easier to handle in C++. It also provides wrapper functions for
the user-defined callbacks that can be attached to a DipProblem.
- RelaxationCollection
- Basically implements a dictionary with default values. Used for
DipProblem.relaxations.
dipapi.py
This module is the API that defines how to communicate between Python and DIP. It is a virtual API and needs to be implemented to be used. The implementation is within DipProblem in dippy.py.
- DipAPIError
- Our custom exception class
- DipAPI
The API which must be used as a base class and then the functions overwritten
- getObjective
- This function returns the objective as a Python dictionary with variables as keys
and (non-zero) coefficients as values
- getRows
- This function returns constraints as a list of Python dictionaries with variables
- as keys and (non-zero) coefficients as values. Constraints also have
getName, getLb and getUb methods
- getCols
- This function returns a list of variables. Variables have getName, getLb,
getUb and isInteger methods
- getMasterAsTuple
- This function returns all the master problem data as a tuple of other
“data gathering” functions
- getRelaxAsTuple
- This function returns all the subproblem constraints and variables
- chooseBranchSet
- This function finds the best branch for a fractional solution
- solveRelaxed
- This function returns solutions to a relaxed subproblem
- isUserFeasible
- This function lets the user decide if an integer solution is really feasible
- generateCuts
- This function lets the user generate cuts to remove fractional “pieces” of xhat
- solveHeuristics
- This function lets the user generate (heuristic) solutions from a fractional solution
- generateInitVars
- This function returns initial solutions to relaxed subproblems
_dippy C++ extension module
- DippyModule.cpp
- This module defines contains the module initialization function that is called by Python,
along with a list of methods exposed.
- DippySolve.cpp
- The main Solve function exposed by the module.
- DippyDecompAlgo.(cpp|h)
- Extended versions of DecompAlgo classes which have support for interfacing with
Python. We use Mixin classes to reduce the amount of code that has to be duplicated.
- DippyDecompApp.(cpp|h)
- The Decomp Application. All of the main stuff happens here - creating the core and
relaxed models, the solveRelaxed, generateCuts and APPIsUserFeasible callbacks.
- DippyDecompCut.h
- Really basic class that extends DecompCut.
- DippyPythonUtils.(cpp|h)
- Utilities for communicating between dippy.py, dipapi.py and DIP.
Coding Conventions
A few common coding conventions have been used in the C++ code:
- Python object pointers are prefixed with p.
- Class members begin with m_.