Documentation
Library manual
Reference for the self-contained C++20 divisible-load scheduling library that powers this portal: what it is for, what it covers, how to build and use it, and how it is licensed. Concepts and notation are defined in the Knowledge base. This manual is a living document and will grow as new problem classes and solvers are added.
Embedding
The library can be embedded in three ways: directly from C++ (include the headers, link the archive),
via the C-ABI shared library from any language that can call a shared library, or through the bundled
Python ctypes wrapper which requires no compiled extension.
The JSON contract (the dict shape returned by dls.solve() and the
HTTP API) is the stable surface that front-ends should depend on; the C++ types are internal.
C++ embedding
Include core/dls_instance.hpp and
core/solver_registry.hpp, construct a
DLSInstance, choose a solver with
makeSolver(name), and call
solver->solve(inst, cfg).
The returned DLSSolution carries the status, makespan, energy,
cost, activation sequence, and the full LoadFragment vector with Gantt timing.
// embed the library in a C++20 project #include "core/dls_instance.hpp" #include "core/solver_registry.hpp" #include <iostream> int main() { // build the instance dls::DLSInstance inst; inst.setTotalLoad(1000.0); dls::Processor p1, p2, p3; p1.commStartup = 0.1; p1.commRate = 0.11; p1.computeRate = 0.52; p2.commStartup = 0.2; p2.commRate = 0.21; p2.computeRate = 0.22; p3.commStartup = 0.3; p3.commRate = 0.31; p3.computeRate = 0.32; p3.memoryLimit = 1500.0; // B: caps this worker at 1500 units/installment inst.processors() = {p1, p2, p3}; // pick a solver and run it auto solver = dls::makeSolver("best-rate"); dls::SolverConfig cfg; cfg.seed = 42; // optional: set for reproducible GA runs cfg.timeLimitSeconds = 5.0; // optional: wall-clock budget dls::DLSSolution sol = solver->solve(inst, cfg); // read back the result if (!sol.feasible()) { std::cerr << "no feasible schedule\n"; return 1; } std::cout << "makespan: " << sol.makespan << "\n"; for (const auto& f : sol.fragments) std::cout << " P" << f.processorId << " load=" << f.loadSize << " [comm " << f.commStart << "→" << f.commFinish << " comp " << f.computeStart << "→" << f.computeFinish << "]\n"; }
Python embedding
The bundled frontend/dls/__init__.py locates
libdls_c.so automatically (first via
DLS_LIB, then by searching build*/bin/)
and exposes solve(), pareto(),
iso_map(), benchmark(), and
topology(). Instances are plain dicts; all results are dicts
matching the HTTP API response shapes exactly. No pip install, no compiled extension, no pybind11.
import dls # list solvers registered in this build print(dls.available_solvers()) # ['auto', 'ga', 'best-rate', 'online', 'single-round', 'exact', ...] # solve — instance is a plain dict; result is a dict (the JSON contract) inst = { "totalLoad": 1000, "processors": [ {"S": 0.1, "C": 0.11, "A": 0.52, "B": 4000}, {"S": 0.2, "C": 0.21, "A": 0.22, "B": 5000}, {"S": 0.3, "C": 0.31, "A": 0.32, "B": 1500}, ] } sol = dls.solve(inst, solver="best-rate") print(sol["solution"]["makespan"]) # → 302.14 print(sol["lowerBound"]) # → 298.51 # time-energy Pareto sweep (requires an energy model in the instance) front = dls.pareto(inst, solver="best-rate", points=20) # returns {"solver", "points": [{"makespan": ..., "energy": ...}, ...]} # isoefficiency map: sweep processors (x) vs comm rate (y), measure makespan grid = dls.iso_map(x="procs", y="comm", metric="makespan", xmin=2, xmax=16, xsteps=8, ymin=0.01, ymax=0.5, ysteps=10) # returns {"xs", "ys", "grid": [[makespan, ...], ...]} (grid[yi][xi]) # portfolio benchmark over 20 random instances bench = dls.benchmark( solvers="single-round,best-rate,ga,exact", instances=20, procs=6, load=1000, seed=99 ) # returns {"instances", "provenOptimal", "solvers": [{"name", "avgRelGap", ...}, ...]} for s in bench["solvers"]: print(f"{s['name']:15s} gap={s['avgRelGap']:.3f} t={s['avgTimeSec']:.4f}s") # non-star topology (chain example) chain_txt = """V 100 node 0.20 0 node 0.30 0.10 node 0.25 0.12""" result = dls.topology("chain", chain_txt) # returns {"status", "feasible", "makespan", "loads": [0, α₁, α₂]}