A set of system tests for the SMS++ core library and several other modules.
Since most of the tests we devised for the SMS++ project require multiple modules, shipping them with a single module would add unnecessary requirements to that module. For this reason, we ship them in a separate repository.
The following tests are provided:
Each directory is named after the module the tests inside it are posed on,
since a suite lives here when the module cannot run it by itself: either it
needs the cross-check machinery of common_utils, which
solves a Block with every :Solver a BlockSolverConfig attaches and
compares what they return, or it needs a module that is not among that
module's dependencies. The testers of the objects of the core library are
therefore grouped under SMS++, and those posed on a Block under the
name of its module; the unit tests of a module, which need neither, live in
the test directory of the module itself.
The core library (SMS++)
-
AbstractBlock, the four testers posed on anAbstractBlock: the box-structured Block ofksub-AbstractBlockwith box constraints and a separableObjectivewhose Lagrangian dual is computed by aLagrangianDualSolver(withLagBFunctionandBoxSolver) and cross-checked against a:MILPSolver(LagrangianDualSolver_Box_test);AbstractBlock::mirror(), i.e., the copy of the abstract representation that every Block has without a line written for it, checked to be the same problem as the original, to take the solution back to it and to follow it when it changes; andAbstractBlock::read_lp()/AbstractBlock::read_mps(), a random linear program being written to file by the:MILPSolverattached to it, read back into a secondAbstractBlockand solved again, the two optima having to agree; all three then change the instance at random and re-solve many times. The fourth solves a small two-stage linear program byBendersDecompositionSolver, in every way it has of writing a cut, against the optimum a:MILPSolvergives of the monolithic model. -
BoxSolver, a tester which provides very comprehensive tests forBoxSolver(a very simpleCDASolverfor extremely simple problems where eachColVariablecan be dealt with separately subject only to bound and integrality constraints and a linear or quadraticObjective, ignoring any other kind ofConstraintif they are there) as well as to anyCDASolverable to handle Linear Programs (such asMILPSolverand its derived classesCPXMILPSolverandSCIPMILPSolver), and for some of the mechanics of the SMS++ core library. -
LagBFunction, a tester which provides very comprehensive tests forLagBFunction,PolyhedralFunctionBlock,PolyhedralFunction, anyCDASolverable to handleC05Functionin the objective (such asBundleSolver, for which some specific provisions are made), anyCDASolverable to handle Linear Programs (such asMILPSolverand its derived classesCPXMILPSolverandSCIPMILPSolver), as well as for quite a lot of the mechanics of the SMS++ core library. -
BendersBFunction: a test of theBendersBFunctioncomponent on a "hand-made"Blockfor Capacitated Facility Location (CFL) problems, andBendersBFunction_linearization_test, which checks the linearizations theBendersBFunctionproduces on small linear programs whose value is known. -
PolyhedralFunction, a tester which provides very comprehensive tests forPolyhedralFunctionand some tests for anyCDASolverable to handleC05Functionin the objective (such asBundleSolver) and anyCDASolverable to handle Linear Programs (such asMILPSolverand its derived classesCPXMILPSolverandSCIPMILPSolver), as well as for some of the mechanics of the SMS++ core library, plusPolyhedralFunction_prune_test, the unit test of the geometric pruning of the rows. -
PolyhedralFunctionBlock, a tester which provides very comprehensive tests forPolyhedralFunctionand especiallyPolyhedralFunctionBlock, plus quite a few tests for anyCDASolverable to handle multipleC05Functionin the objective (such asBundleSolver) and anyCDASolverable to handle Linear Programs (such asMILPSolverand its derived classesCPXMILPSolverandSCIPMILPSolver), as well as for some of the mechanics of the SMS++ core library, plusPolyhedralFunctionBlock_prune_test, the unit test of the LP-based pruning of the rows.
-
QuadFunction, a tester which provides very comprehensive tests for anyCDASolverable to handle Quadratic Programs (such asMILPSolverand its derived classesCPXMILPSolver,SCIPMILPSolver,GRBMILPSolverandHiGHSMILPSolver). -
BundleSolver/ML, the benchmark of the machine-learning drivenBundleSolveragainst the plain one, over a split of the instances ofMMCFBlockand ofUCBlock: it is here, and not in thetestof its module, because those two Block are not among the dependencies ofBundleSolver.
-
BinaryKnapsackBlock: a tester of the eponymousBlockfor (mixed-integer) binary knapsack problems that cross-checks all its equivalentSolver(the core DP, theBranchAndXSolverin each exploration mode, with the greedy relaxation bracketing) against a standardMILPSolver, both on random instances and against the published optima of the curated Pisinger benchmark.batch-pisingeralso runs the generic Frank-Wolfe tester onKcopies of a knapsack, each with its dynamic programme as the Linear Minimization Oracle: no compact formulation describes the convex hull of a knapsack, so what the decomposition computes is a lower bound on the monolithic optimum and not the same number, which is what that battery checks. -
CapacitatedFacilityLocationBlock, a tester that can be used to test several things together within a slope scaling approach to the Capacitated Facility Location (CFL) problem where the continuous relaxation can be solved with either standard LP tools (aMILPSolver), or via a Min-Cost Flow relaxation cast as aMCFBlockand using customMCFSolver, or, finally, via a Lagrange-friendly reformulation as a bunch ofBinaryKnapsackBlock, so that aLagrangianDualSolvercan be used to compute a stronger bound, and a second one that puts the ad hoc Benders decomposition the Block carries against the generic one ofBendersDecompositionSolveron the same instance. -
MCFBlock: solve aMCFBlockwith both aMILPSolverand aMCFSolverand compare the results. This is a test forMCFBlock,MCFSolver,MILPSolverand its derived classes (CPXMILPSolverandSCIPMILPSolver), as well as for some of the mechanics of the SMS++ core library. The same suite hosts the generic Frank-Wolfe tester (fw_test.cpp): a "leaf"Blockis readKtimes into a fatherAbstractBlockwith a randomFRealObjective, which is then solved both by aFrankWolfeSolver(using the:Solverregistered to each sub-Blockas a Linear Minimization Oracle) and by a monolithic:MILPSolver, cross-checking the two optima; here the leaves areMCFBlockand their oracle aMCFSolver, and a second tester runs the same comparison while the feasible region of a sub-Blockchanges. Their configurations are theFather*ones of the suite, flat beside those of every other:Solver, and their runs are in the batteries of the instances they are posed on,batch-smallbeing the fast one, which walks every code path of the decomposition on the small instances ofMCFClassSolver. A run attaches the reference and oneFrankWolfeSolverper variant of the decomposition at once, and cross-checks the variants against one another as well. -
MMCFBlock, a tester which provides initial tests forLagrangianDualSolver,LagBFunction, anyCDASolverable to handleC05Functionin theObjective(such asBundleSolver), anyCDASolverable to handle Linear Programs (such asMILPSolverand its derived classesCPXMILPSolverandSCIPMILPSolver),MMCFBlockandMCFBlock, as well as for quite a lot of the mechanics of the SMS++ core library. The suite holds a second tester, which provides initial tests forMMCFBlock(in particular, a way to retrieve/generate some sets of Multicommodity Min-Cost Flow instances) and anySolverable to handle Linear Programs, as well as for a few of the mechanics of the SMS++ core library. -
UCBlock, a tester which provides initial tests forLagrangianDualSolver,LagBFunction, anyCDASolverable to handleC05Functionin theObjective(such asBundleSolver), anyCDASolverable to handle Linear Programs (such asCPXMILPSolverandSCIPMILPSolver), theUCBlockset ofBlockfor Unit-Commitment problems (including the pollutant budget constraints, both against PyPSA and on small instances with known optima), as well as for quite a lot of the mechanics of the SMS++ core library. The same suite runsTUDPS_test, which compares theThermalUnitExtDPSolverspecialised Dynamic Programming:Solverwith a:MILPSolveron some of the (many) different formulationsThermalUnitBlocksupports; its batches are inbatches-tub, the batteries that walk the instances carrying one unit alone, thermal or nuclear. Each of them runs that family with every:Solverthat applies to it: besides the dynamic programme against the:MILPSolver, the generic Frank-Wolfe tester (fw_test.cpp) onKcopies of the unit, each with its Dynamic Programming:Solveras the Linear Minimization Oracle, against the perspective bound a:MILPSolvercomputes on the monolithic relaxation, with the same set of configurations, named the same way, as the other two suites this tester is built in. The same suite holds the generator of the scenarios of a unit commitment and the battery that reduces them,batches-scenred/batch, which runs it together withTSSB_scenred_testof theTwoStageStochasticBlocksuite. -
InvestmentBlock, a tester that solves the investment problem defined by anInvestmentBlock(loaded from a netCDF file) with the configured:Solver;batch-stochasticandbatch-pypsaalso solve the inner Block of the modular instances by the recursiveLagrangianDualSolver(InnerBCfg-LD.txt), i.e., an ad hoc Benders decomposition with a Lagrangian dual inside. -
TwoStageStochasticBlock, a tester that loads aTwoStageStochasticBlockfrom a netCDF file, attaches one or two:Solverthrough aBlockSolverConfigand compares their results, and a second one that puts the three ways of solving the same two-stage stochastic investment problem one against the other, i.e., the extensive form, the generic Benders decomposition ofBendersDecompositionSolverand the ad hoc one anInvestmentBlockover the wholeTwoStageStochasticBlockcarries, on instances of growing size. A third one measures what a scenario reduction costs: the instance is solved on the whole scenario set and on theKrepresentatives each method ofScenarioReductionSolverpicks, and the first-stage decision the reduced problem finds is put back into the whole set, so that what is reported is both the gap of the reduced problem and the implementation error of its decision. The last one,TSSB_scenred_test, reads whateverTwoStageStochasticBlocka file holds, reduces its scenarios with a method ofScenarioReductionSolveror withCSSCScenarioReductionSolverand reports the gap of the reduced problem; it registers no test of its own, being run by thebatches-scenredbatteries of theUCBlockandCapacitatedFacilityLocationBlocksuites on the instances their generators write. -
MultiStageStochasticBlock, a tester that loads aMultiStageStochasticBlockfrom a netCDF file, attaches a:Solverthrough aBlockSolverConfigand compares its result against a reference objective value. -
LukFiBlock: a very simple main for running tests with LukFiBlock. It just creates one and loads it from a stream; little more than a compilation check. -
SVMBlock, a tester that cross-checks every:Solverthat can train a Support Vector Machine on the sameSVMBlock: the ad hocSMOSolver,LIBSVMSolver, a:MILPSolveron either formulation the abstract representation can encode, andLagrangianDualSolveron the consensus structure, whose chunks it relaxes into one independent SVM each. It also changes the training problem under theSolverand checks that they keep agreeing after each change. -
SingleFlowDCRBlock, a tester of the eponymousBlockfor single-flow Delay-Constrained Routing problems: a random instance is built around a source-sink path whose delay the deadline is set from, so that the instance is always feasible and the deadline as tight as one wants it, and it is then solved by everySolvertheBlockSolverConfigregisters, typically a:MILPSolveron either of the two formulations of the problem and theSingleFlowDCRBendersSolver, cross-checking what they answer and theSolutioneach of them produces.
compare_formulations, very simple tester for testing different formulations of some problem obtained byBlockConfig-uring in two different ways two copies of the same:Blockand solving them with two copies of the same:Solver.
The tests run as traditional command line executables. Most of the tests can also run as a CTest suite.
These instructions will let you build and run the SMS++ System Tests on your system.
- See each test for its requirements.
Configure and build all the tests using CMake:
mkdir build
cd build
cmake ..
cmake --build .Carefully hand-crafted makefiles have also been developed for those unwilling to use CMake. Makefiles build the executable in-source (in the same directory tree where the code is) as opposed to out-of-source (in the copy of the directory tree constructed in the build/ folder) and therefore it is more convenient when having to recompile often, such as when developing/debugging a new module, as opposed to the compile-and-forget usage envisioned by CMake.
Each of the executables in the individual folders has its own makefile which
includes the "main makefile" of the concerned modules, typically either
makefile-c including all necessary libraries comprised the "core SMS++" one,
or makefile-s including all necessary libraries but not the "core SMS++"
one (for the common case in which this is used together with other modules
that already include them). The makefiles in turn recursively include all the
required other makefiles, hence one should only need to edit the makefile
of each executable for compilation type (C++ compiler and its options) and it
all should be good to go. In case some of the external libraries are not at
their default location, it should only be necessary to create the
../extlib/makefile-paths out of the extlib/makefile-default-paths-* for
your OS * and edit the relevant bits (commenting out all the rest).
Check the SMS++ installation wiki for further details.
Each tester has an executable built in the corresponding directory (or in the
corresponding directory in the copy of the directory tree in the build/ folder
if you use CMake); look at the README.md in the folder and/or run it for
instructions. In several cases a (bash) batch is available to run
a default sequence of tests (this may take a while).
In case you use CMake, you can see all the (bash) batch tests available by running:
ctest -Nand run them all at one with:
ctest -V -C Releaseor you can choose a specific one from the batch test list and run it with:
ctest -V -R <batch-test-name> -C ReleaseEach test is also tagged, via CTest labels, with the modules it exercises, so you can run all and only the tests relevant to one module with:
ctest -V -C Release -L <module>This is what each module's continuous integration uses to run its own tests
(and only those) without referring to any test path. The map from each test to
its modules is kept in a single place, cmake/TestLabels.cmake;
extend it when adding a test.
If you need support, you want to submit bugs or propose a new feature, you can open a new issue.
Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting merge requests to us.
-
Antonio Frangioni
Dipartimento di Informatica
Università di Pisa -
Enrico Calandrini
Dipartimento di Informatica
Universita' di Pisa -
Rafael Durbano Lobato
Dipartimento di Informatica
Università di Pisa -
Donato Meoli
Dipartimento di Informatica
Università di Pisa
-
Federica Di Pasquale
Dipartimento di Informatica
Università di Pisa -
Ali Ghezelsoflu
Dipartimento di Informatica
Università di Pisa -
Enrico Gorgone
Dipartimento di Matematica ed Informatica
Università di Cagliari -
Niccolò Iardella
Dipartimento di Informatica
Università di Pisa
This code is provided free of charge under the GNU Lesser General Public License version 3.0 - see the LICENSE file for details.
The code is currently provided free of charge under an open-source license. As such, it is provided "as is", without any explicit or implicit warranty that it will properly behave or it will suit your needs. The Authors of the code cannot be considered liable, either directly or indirectly, for any damage or loss that anybody could suffer for having used it. More details about the non-warranty attached to this code are available in the license description file.