Skip to main content

g6-optimisation

Use when you are about to propose a schedule, allocation, assignment, route, flow, packing or production plan that must keep stated rules, call a plan the best, cheapest or fastest, or tune a non-linear formula's inputs by trial and error, and the numbers come from your own working rather than a solver.

Source facts

Repository
basicisabc1994/g6solver
Last source activity
October 30, 2026 at 10:47
Detected SKILL.md language
English
Stars
0
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
g6-optimisation
description
Use when you are about to propose a schedule, allocation, assignment, route, flow, packing or production plan that must keep stated rules, call a plan the best, cheapest or fastest, or tune a non-linear formula's inputs by trial and error, and the numbers come from your own working rather than a solver.
# G6 optimisation Solves linear, integer, constraint, routing, flow and scheduling problems with OR-Tools, in process, and checks every answer in pure Python before it is reported. Where optimality can be shown without trusting the solver, it is; where it cannot, the reply says how far the answer may be from the best. A non-linear objective over a box is searched with SciPy: a local method from several starts, or a global search, the answer re-evaluated by G6 and never called optimal. ## When to use it - You are about to hand someone a timetable, a rota, a delivery route or a resource split. - A plan must respect hard limits (capacities, budgets, machine order, time windows) and one broken limit matters. - A draft says "optimal", "cheapest", "minimal" or "the best we can do". - You need shadow prices (duals) or reduced costs from a linear programme. - You need the lowest or highest value of a non-linear formula over bounded inputs, continuous or whole numbers: `minimise` or `global_search`, not a guess from a few tries. ## When not to use it - Whether a set of logical constraints can hold at all, or a counterexample to a rule: use `formal`. - A formula to simplify, differentiate or solve: use `algebra`. - Deciding whether an agent may take an action: use `action_gating`. - Checking a plan of G6 op calls before it runs: use `g6.navigator`'s `check_plan`. ## Ops - `solve_lp`: a linear programme on GLOP; an optimum is shown by its duals, and no optimum is shown infeasible (least-violation duals) or unbounded (a feasible point and an improving ray) when G6 can show it; otherwise the reason says the solver's word is unchecked. - `solve_mip`: a mixed-integer programme on SCIP; the answer checked, with the solver's bound and gap. - `solve_cp`: a constraint model on CP-SAT (integer variables with finite bounds, linear constraints, `all_different` groups, an optional objective), checked exactly. - `solve_knapsack`: the most valuable items that fit, any number of weight dimensions, checked. - `solve_job_shop`: each job's tasks in order, one task at a time per machine, the makespan minimised and checked. - `solve_assignment`: rows paired with columns at least cost (`costs`, `null` for a forbidden pair); optimality shown by the residual network. - `solve_max_flow`: the largest flow from `source` to `sink`, shown maximal by a cut of the same capacity. - `solve_min_cost_flow`: every supply met at least cost; optimality shown by the residual network. - `solve_routing`: routes that visit every node once (`distances`, `vehicles`, `depot`, optional `demands` and `capacities`, `time_windows`, `travel_times`), checked, never called optimal without proof. - `minimise`: a SciPy local method (`method`: `L-BFGS-B`, `Nelder-Mead` or `Powell`) from `starts` starting points (the first at `x0` if given, the rest drawn with `seed`) over continuous `variables`; the answer is a local minimum, with the number of different minima the starts found. - `global_search`: differential evolution over the box, integer variables included (or a `backend` registered in Python); the answer is the best point found. ## Reading the result Inputs are declarative data: a linear expression is `{variable: coefficient}`, a constraint `{"name", "terms", "lb", "ub"}`, a network a list of arcs `{"from", "to", "capacity", "cost"}`. `sense` is `minimise` or `maximise`; `time_limit` is at most 60 seconds. The reply gives `objective`, `solution`, `optimal`, `bound`, `gap`, `certificate` and `check` (what was checked and any failures). - `qualified-draft`, `G6_E_OPTIM_SOLVER_ANSWER`: an answer that passed the check. The best state; nothing here is `verified`. - `qualified-draft`, `G6_E_OPTIM_NOT_PROVEN_OPTIMAL`: feasible and checked, but not proven best; the card names the gap, or says there is no bound. - `blocked-escalated`: `G6_E_OPTIM_INFEASIBLE` and `G6_E_OPTIM_UNBOUNDED` (shown by G6 for a linear programme when it can; otherwise, and for `solve_mip` and `solve_cp`, the reason says it rests on the solver's own proof), `G6_E_OPTIM_TIME_LIMIT` with no answer, `G6_E_OPTIM_CERTIFICATE_REFUTED` (the check contradicted the solver), `G6_E_OPTIM_MODEL_INVALID`. A draft's code is on `warning_card.code`; the result's own `code` is empty unless it is blocked. For `minimise` and `global_search`, every variable needs finite bounds (`lb` is 0 unless given), and `expression` is a JSON tree, never code: a number, a variable's name, or `[operation, argument, ...]` with `+`, `*`, `min`, `max`, `-`, `/`, `^`, `neg`, `abs`, `sqrt`, `exp`, `log`, `sin`, `cos`, `tan`, `tanh`, `atan`, and `["table", [c0, c1, ...], i]` for a choice an integer variable makes; at most 2,000 nodes, 50 deep, 50 variables. The point is re-evaluated by G6's own interpreter and its bounds checked; `minimise` also checks the projected gradient and nearby points. The search stops at `max_evaluations` (default 20,000) or `time_limit`; `solution.converged` and `evidence[0].search` say how far it got. - `qualified-draft`: `G6_E_OPTIM_LOCAL_OPTIMUM` (a local minimum; the card says whether the starts disagreed), `G6_E_OPTIM_BEST_FOUND` (the best point a global search found, converged by its own test) or `G6_E_OPTIM_NOT_CONVERGED` (not shown to be a minimum: stopped early, or a better point beside it). - `blocked-escalated`: `G6_E_OPTIM_INPUT_INVALID` (an expression outside the language, a missing bound), `G6_E_OPTIM_INPUT_TOO_LARGE`, `G6_E_OPTIM_CERTIFICATE_REFUTED` (the search misreported its value, or left the box), `G6_E_OPTIM_NO_SOLUTION`, `G6_E_OPTIM_SCIPY_UNAVAILABLE`. ## Alone and composed Alone, over MCP: `g6_invoke("optimisation", "solve_lp", params_json)`. From Python: `from g6.optimisation import solve_lp, solve_mip, solve_routing, solve_max_flow, minimise, global_search`; `register_backend(name, run)` adds a `global_search` backend, whose answers are re-checked like any other. Composed: - Use `formal`'s `unsat_core` on the same rules written as SMT-LIB to find which ones conflict when a model here comes back infeasible. - Give `coding_agent_gate`'s `verify_answer` the reply as an evidence item of kind `log` before reporting a plan as done (it counts as caller-declared); an outward action the plan triggers goes through `action_gating` first. ## Failure modes it catches - `rule_breaking_plan` (a plan that breaks one of your rules): every answer is checked against the model you sent before it is reported: each constraint and bound, capacities and flow conservation, machine order and overlaps, every node visited once, loads and time windows. A violation blocks it with `G6_E_OPTIM_CERTIFICATE_REFUTED`. - `unproven_optimum` (a plan called the best when nobody proved it): where it can, G6 shows optimality without trusting the solver (duals for a linear programme, an equal cut for a maximum flow, no negative cycle in the residual network for an assignment or a minimum-cost flow). Elsewhere `optimal` is true only when the solver proves it, with its bound and gap closed; a feasible answer short of that is `G6_E_OPTIM_NOT_PROVEN_OPTIMAL`, naming the gap or saying there is no bound. - `wrong_optimiser` (a poor solution from the wrong optimisation method): `minimise` calls a local method's answer local and runs several starts, saying when they found different minima and pointing to `global_search`; a search stopped by its limits says it did not converge; and every point is re-evaluated, so a method that misreports is refused. ## Blind spots - The model is yours. A rule you left out is a rule nobody checks, and a wrong coefficient gives a wrong plan that passes. - An integer or constraint optimum rests on the solver's bound, which G6 does not re-derive, and an integer or constraint model called infeasible or unbounded rests on the solver's proof, which G6 does not re-check. - Continuous values are compared within a small tolerance scaled to the numbers, not exactly. - A hard problem may hit the time limit: with an answer, it is not proven optimal; with none, it is blocked. - No stochastic models, and no sensitivity analysis beyond GLOP's duals and reduced costs. Non-linear objectives are searched only within bounds, with no other constraints, and never proven optimal: differential evolution can pass its own test in a local basin (run another `seed`), and the gradient check uses finite differences. Around a local answer a few dozen points are sampled; with `abs`, `min`, `max` or a table, SciPy's flag alone backs the word minimum. ## What it needs - `pip install "g6[optim] @ git+https://github.com/basicisabc1994/g6solver"` for OR-Tools, imported only when an op runs. Without it solving ops are `blocked-escalated` with `G6_E_OPTIM_SOLVER_UNAVAILABLE` and the install line. - `pip install "g6[optim-nonlinear] @ git+https://github.com/basicisabc1994/g6solver"` for SciPy, used by `minimise` and `global_search`; without it they are `blocked-escalated` with `G6_E_OPTIM_SCIPY_UNAVAILABLE` and the install line. - No outside program. No op runs code, writes a file or reaches the network, so none is sensitive. ## Examples ```g6-example op=solve_lp {"variables": {"doors": {}, "windows": {}}, "constraints": [{"name": "plant1", "terms": {"doors": 1}, "ub": 4}, {"name": "plant2", "terms": {"windows": 2}, "ub": 12}, {"name": "plant3", "terms": {"doors": 3, "windows": 2}, "ub": 18}], "objective": {"doors": 3, "windows": 5}, "sense": "maximise"} ``` `objective` is 36 with 2 doors and 6 windows, `optimal` is true, and `certificate.duals` with `check.certificate` `duals` show it without trusting the solver. ```g6-example op=solve_routing {"distances": [[0, 2, 9, 10], [2, 0, 6, 4], [9, 6, 0, 8], [10, 4, 8, 0]], "time_limit": 1} ``` A route that visits every node once, checked, but `qualified-draft` with `G6_E_OPTIM_NOT_PROVEN_OPTIMAL`: the routing library gives no bound, so the reply says a better route may exist. ```g6-example op=minimise {"variables": {"x": {"lb": -2, "ub": 2}}, "expression": ["+", ["^", ["-", ["^", "x", 2], 1], 2], ["*", 0.3, "x"]], "x0": {"x": 1.0}, "starts": 6, "seed": 3} ``` Two wells: the start at `x0` finds the shallow one near 0.96, other starts the deeper one near -1.04. The reply is `G6_E_OPTIM_LOCAL_OPTIMUM` at x near -1.04, and its card says the starts found 2 different minima. ```g6-example op=global_search {"variables": {"a": {"ub": 10, "integer": true}, "b": {"ub": 10, "integer": true}}, "expression": ["+", ["^", ["-", ["*", "a", "b"], 12], 2], ["^", ["-", ["+", "a", "b"], 7], 2]]} ``` Two whole numbers whose product is 12 and sum is 7: 3 and 4, objective 0, `G6_E_OPTIM_BEST_FOUND`. ## The four open problems - **Learning signals.** Not yet: it writes nothing to a run ledger itself. Each catch is a labelled result with its own `G6_E_OPTIM_*` code and the failed check in `evidence`; recording it is the caller's step today. - **Evaluators the model cannot influence.** The checks are the package's own pure-Python code, recomputing every constraint and objective from the model you sent; no model call runs anywhere in the package. The caller supplies the model, never the check. - **Transfer by failure mode.** The checks belong to the problem class, not to a task: a dual certificate or an equal cut shows optimality for any instance. Not yet: its catch rate on task families it was not built on has not been measured. - **Enough held-out cases.** Not yet: its own catch rate and false-alarm rate are not judged by a sequential test. A repeated workflow that uses it can be tuned with `g6.metaharness`, whose gate judges a change on held-out cases.
View on GitHub