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.

HTTP API

The FastAPI layer exposes JSON endpoints at /api/*. All POST endpoints accept application/json and return application/json. The response shape mirrors the CLI --json output exactly, so the same result struct is usable from a browser, a script, or a CI pipeline.

Compute requests execute one at a time in submission order (a server-side FIFO queue), so a heavy exact solve cannot starve other requests. By default a POST simply waits its turn and returns the result, exactly as before. Add "queue": true to the body to get a job ticket ({"job", "position"}, HTTP 202) back immediately instead, then poll GET /api/jobs/<id> for the live queue position and, finally, the result (kept for 10 minutes). When more than 100 jobs are waiting, submissions return HTTP 429.

Every job carries a wall-clock limit set by the caller's access level: 10 s for anonymous calls (including plain curl), 120 s for registered accounts, unlimited for admins. A job that overruns is killed and reports the limit in its error message. Anonymous callers may keep 1 job waiting at a time; registered accounts 3. Scripts authenticate exactly like the browser: POST /api/auth/login returns a session cookie to send with subsequent requests (curl -c jar … ; curl -b jar …). Accounts are created on the register page. GET /api/me reports your tier and effective limits.

Submissions are also capped per source IP address, independent of job length: 20 per hour anonymous, 100 per hour registered, unlimited for admins — abuse protection against scripted submission floods, separate from the per-job time limit above. Exceeding it returns HTTP 429.

Method Endpoint Purpose
GET /api/solvers Return the list of solver names and descriptions available in this build.
POST /api/solve { instance, solver?, opts? } → schedule with full Gantt timing and lower bound.
POST /api/pareto { instance, opts? } → time-energy Pareto front (requires an energy model).
POST /api/map { opts } → isoefficiency or isoenergy 2-D parameter sweep.
POST /api/bench { solvers?, opts? } → portfolio comparison over random instances.
POST /api/topology { klass, text } → chain / tree / graph / mapreduce / multilayer load distribution.
POST /api/mlsd { text, solver? } → multiple-loads (MLSD) schedule.
POST /api/mapreduce-bwidth { text } → MapReduce under a bisection-width read-channel limit (exact LP, HiGHS build only).
POST /api/skew-static { text } → reducer partitioning-skew mitigation, fine partitioning + LPT bin-packing.
POST /api/skew-dynamic { text } → reducer partitioning-skew mitigation, single-shot post-sort rebalancing.
POST /api/reducer-read { text } → heterogeneous multi-channel reducer read schedule (branch-and-price, HiGHS build only).
POST /api/multisource { text } → multi-source map-phase schedule, bipartite storage-nodes-to-mappers LP (HiGHS build only).
GET /api/jobs/{id} Poll a queued job: { status, position } while waiting, then { status: "done", result }.
POST /api/jobs/{id}/cancel Stop a queued or running job. Owner (same session or IP) or admin only.
GET /api/queue Queue snapshot: { running, waiting } counts across all compute endpoints.

POST /api/solve — request

The instance field uses the same JSON schema as the Python dls.solve() dict. The solver field defaults to "auto" when omitted. The opts object is optional; all keys are shown below.

// POST /api/solve
{
  "instance": {
    "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 }
    ]
  },
  "solver": "best-rate",
  "opts": {}
}

POST /api/solve — response

// 200 OK — response body
{
  "solver":     "best-rate",
  "lowerBound": 298.51,
  "solution": {
    "status":   "Feasible",
    "makespan":  302.14,
    "energy":   0.0,
    "sequence":  [0, 1, 2],
    "fragments": [
      { "processorId": 0, "loadSize": 417.31,
        "commStart": 0.10,   "commFinish": 46.10,
        "computeStart": 46.10, "computeFinish": 302.14 },
      { "processorId": 1, "loadSize": 332.84,
        "commStart": 46.10,  "commFinish": 116.82,
        "computeStart": 116.82, "computeFinish": 302.14 },
      { "processorId": 2, "loadSize": 249.85,
        "commStart": 116.82, "commFinish": 193.57,
        "computeStart": 193.57, "computeFinish": 302.14 }
    ],
    "wallTimeSec": 0.000312
  }
}

Available opts keys

// opts keys accepted by /api/solve (all optional)
{
  "maxInstallments": 5,        // search depth / GA installments
  "deadline":        300.0,     // time deadline T (OptV / FPTAS only)
  "epsilon":         0.05,      // FPTAS approximation ε
  "seed":            42,        // RNG seed for GA reproducibility
  "costLimit":       500.0,     // bi-criteria cost cap G
  "backend":         "highs",   // LP evaluator: "simplex" | "highs"
  "allowRepeats":    true,      // allow a processor to appear more than once
  "chunk":           "gss"      // online chunk rule: "gss" | "ssc"
}