API reference
Each client has its own full reference, generated from its source. This page says where to find it and describes what all of them share: the result you get back, how to read it, and what an error looks like.
| Language | Package | Reference | Source |
|---|---|---|---|
| Python | quicopt on PyPI | MkDocs ↗ | quicopt-python ↗ |
| Julia | QuicoptClient | Documenter ↗ | QuicoptClient.jl ↗ |
| R | quicopt on r-universe | pkgdown ↗ | quicopt-r ↗ |
| Ruby | quicopt gem | YARD ↗ | quicopt-ruby ↗ |
All four are open source under Apache 2.0. Installation: Client libraries.
Python at a glance
from quicopt import Client
client = Client() # key from QUICOPT_API_KEY
result = client.solve(model) # a MathOpt or Pyomo model
print(result.display)
Client()— reads your key fromQUICOPT_API_KEY(API keys). To pass a key in code, name it:Client(api_key="…"). The first positional argument is the service address, soClient("…")would not set your key.timeout=60.0is the per-request timeout in seconds.client.solve(model, *, gzip=False)— sends the model and returns aResult.gzip=Truecompresses the request body, which helps with large models.client.submit(model)— the same without waiting; see async jobs.
The full Python reference, every argument included, is in the MkDocs documentation ↗.
The Result object
| Field | Type | Meaning |
|---|---|---|
status | str | optimal · feasible · heuristic · time_limit · iteration_limit · infeasible · unbounded |
objective | float or None | objective value; None when there is no solution |
feasible | bool or None | whether the returned solution satisfies all constraints; None where that's undefined (e.g. an unconstrained heuristic) |
solution | dict[str, float] | variable name → value; empty for infeasible/unbounded |
model_class | str or None | how the service classified the model (lp, qp, milp, qubo, …) |
solve_time_seconds | float | solve wall time |
display | str | the framed console report — print it and you get the result view from the examples, shots block included |
With the MathOpt front-end, solution keys are your variable names from the
model — name your variables and you can read the result without bookkeeping.
The Pyomo front-end currently returns generic x1, x2, … keys.
The shots block
result.display opens with a shots block. The service takes several shots at
your model, and the block is one row per shot: the value it reached, how long it
took, and ◀ best on the one that won.
├── shots
│ ├── 1 · primal-dual · global 42 0.0s ◀ best
│ ├── 2 · primal-dual · global 42 0.01s
│ └── 3 · primal 32 0.01s
Each row is labelled method · certificate. A primal shot only ever
holds a solution; a primal-dual shot also maintains a bound on what the
best solution could be, which is what puts it in a position to certify. The
certificate is what the shot ended up proving: global for a proven
optimum, local for a point proven optimal in its own neighbourhood, and no
certificate at all where it proved neither — a good value, not a guarantee.
Read the block when you want to know how much weight the answer carries;
result.status is the one-word summary of it. How many rows you get depends on
the model, so don't count on a fixed number.
Status semantics
optimal— the value is certified, and the shots block shows how far the proof reaches:global, orlocalon a non-convex model where local optimality is what can be proven.feasible: True.heuristic— the best value found across the shots, with nothing in the block certifying it (typical for QUBO);feasibleisNonewhen there are no constraints to check.feasible— the solution satisfies every constraint, but no shot proved it optimal.time_limit— the solve ran out of time and returns the best point found; checkfeasiblebefore you use it.iteration_limit— the solver stopped at its iteration cap and returns the best point found (can happen on hard NLPs); treat it likeheuristic.infeasible— no assignment satisfies the constraints;objectiveisNone,solutionis empty. This is a regular status, not an error — checkresult.statusrather than catching exceptions. There's a worked example.unbounded— the objective can be improved without limit; also a regular status.
Errors: QuicoptError
Anything the service declines raises QuicoptError with three useful fields:
from quicopt import Client, QuicoptError
try:
result = client.solve(model)
except QuicoptError as e:
print(e.reason) # stable code, e.g. "unsupported_model" or "invalid_key"
print(e.display) # the service's readable message
| Field | Meaning |
|---|---|
reason | a stable snake_case code, e.g. unsupported_model for a problem class that isn't solved yet |
display | the framed, human-readable message |
status_code | the HTTP status behind it |
Remember: infeasible and unbounded are results, not errors — you get a
normal Result for those.
Async jobs: client.submit()
For a long solve, don't block — submit the model and poll a job handle:
job = client.submit(model) # returns immediately
job.status() # {"status": "queued" | "running" | "done" | "failed", ...}
result = job.result() # polls until done, returns the same Result as solve()
print(job.log()) # the solver log so far
job.delete() # remove the job and its stored result
| Method | Meaning |
|---|---|
job.status() | the job's state and a tail of its log |
job.result(wait=True, timeout=None, poll=0.5) | the finished Result; it waits up to 120 s by default (longer if the job has a time limit) and then raises; with wait=False it fetches once and raises if the job isn't done yet |
job.log() | the job's full plain-text log |
job.delete() | delete the job and its stored result on the server |
submit() takes the same models and the same gzip option as solve().
Questions
Something unclear in a client, or a model that does not behave as expected? Tell us:
Questions? Talk to us.
Whether something's unclear or you want to try Quicopt on your real models — tell us what you're optimizing.