anofox_optimize
Kombinatorische Entscheidungsalgorithmen als SQL — Bin Packing, Knapsack, Wave-Batching, Sequenzierung, Scheduling, Sortiments- und Portfolioauswahl
Maintainer: jrosskopf
Installation und Laden
INSTALL anofox_optimize FROM community;LOAD anofox_optimize;Beispiel
-- Cartons waiting to ship, and a container that holds 1000 units.CREATE TABLE cartons AS SELECT * FROM VALUES (1, 420.0), (2, 380.0), (3, 260.0), (4, 240.0), (5, 190.0), (6, 180.0), (7, 150.0), (8, 130.0) AS t(carton_id, size);
-- How few containers hold everything? `best_of` runs every packing-- algorithm in the family and returns whichever used the fewest bins.SELECT opt_pack_best_of(list(size ORDER BY carton_id), 1000.0).bins_used AS containersFROM cartons;
-- Which shipments go on a cheaper carrier that only takes 1000 units?-- Value == weight, so this is subset-sum, and `exact` finds the perfect-- fill that greedy rules miss.SELECT opt_knapsack_exact( list(weight ORDER BY shipment_id), list(weight ORDER BY shipment_id), 1000.0 ).total_weight AS loaded_on_cheap_carrierFROM (VALUES (1, 505.0), (2, 380.0), (3, 260.0), (4, 240.0), (5, 115.0)) AS s(shipment_id, weight);Über anofox_optimize
anofox_optimize stellt kombinatorische Entscheidungsalgorithmen als DuckDB- Funktionen bereit. Container packen, ein Sortiment wählen, eine Maschine sequenzieren, ein Portfolio zuweisen — in SQL, gegen die Tabellen, in denen die Daten bereits liegen. Kein Solver-Prozess, kein externer Dienst, keine Modellierungssprache.
Acht Familien, jeweils eine Signatur
Jedes Mitglied einer Familie nimmt dieselben Argumente entgegen; tauschen Sie einen Bezeichner, tauschen Sie nur den Algorithmus:
| Family | Decision | Example |
|---|---|---|
pack_* |
fit items into the fewest containers | opt_pack_best_of |
knapsack_* |
pick a subset under one capacity | opt_knapsack_exact |
wave_* |
group orders into capacity-limited waves | opt_wave_best_of |
sequence_* |
order jobs to cut changeover cost | opt_sequence_two_opt |
schedule_* |
order jobs against due dates with setups | opt_schedule_best_of |
assortment_* |
choose what to stock when products interact | opt_assortment_best_of |
portfolio_* |
choose assets and weights under a holding limit | opt_portfolio_best_of |
matrix_from_triples |
build a matrix from (from, to, value) rows |
— |
Jede Funktion hat einen kanonischen Namen anofox_optimize_* und einen kurzen Alias opt_*
— es ist dieselbe Funktion. opt_*_best_of führt jeden Algorithmus der
Familie aus und liefert den Sieger; dort sollten Sie beginnen.
Ehrlichkeit bei Garantien
Zwei Funktionen liefern ein bewiesenes Optimum und sagen das im Namen:
knapsack_exact und schedule_exact. Alles andere ist heuristisch und
ohne Garantie. Funktionen, die explodieren würden, lehnen ab statt zu hängen —
schedule_exact weist mehr als 14 Jobs mit einem Fehler zurück, der die
stattdessen zu verwendende Heuristik nennt.
Jede Familie enthält außerdem ein bewusst schwaches Mitglied (pack_next_fit,
portfolio_top_return, assortment_top_margin, sequence_as_given),
weil Sie eine ehrliche Baseline brauchen, um zu wissen, ob das Optimieren etwas
gebracht hat — und „was wir heute tun“ ist meist eine gierige Regel.
Zwei Wege, die falsche Funktion zu wählen
Beide sind still, daher sollten Sie sie kennen. assortment_* und
assortment_recapture_* nehmen dieselben Argumente entgegen und modellieren gegensätzliche
Ökonomien — Produkte, die sich gegenseitig kannibalisieren, versus Nachfrage, die zu den
Verbleibenden fließt, wenn Sie etwas auslisten. Und sequence_* und schedule_* ordnen beide
Jobs, aber nur schedule_* kennt Fälligkeitstermine.
Tests
Die Suite prüft gegen Optima, die außerhalb der Erweiterung berechnet wurden: Falkenauer-Tripel, deren Optimum konstruktionsbedingt festliegt, Subset-Sum per dynamischer Programmierung, Held-Karp-Scheduling und Portfolio-Enumeration über alle 15,504 Teilmengen. Dieser Maßstab hat sich bereits bezahlt gemacht — er hat eine lokale Suche erwischt, die 168 gegen ein bewiesenes Optimum von 60 lieferte, und einen „exakten“ Scheduler, der nicht exakt war.
Die Erweiterung erfasst anonyme Nutzungstelemetrie, abschaltbar mit
SET anofox_telemetry_enabled = false. Im
Projekt-Repository finden Sie
Anleitungen, Theoriehinweise und eine API-Referenz, erzeugt aus
duckdb_functions() der gebauten Erweiterung.
Hinzugefügte Funktionen
| function_name | function_type | description | comment | examples |
|---|---|---|---|---|
| anofox_optimize_assortment_best_of | scalar | Runs every assortment algorithm in this family and returns whichever captured the most margin. MODEL: CANNIBALISATION — each listed product earns margin * (base_demand minus the demand the OTHER LISTED products take from it). Listing near-duplicates destroys value here. If instead you are DELISTING and want the demand of dropped products to flow to the survivors, use the anofox_optimize_assortment_recapture_* family: it answers a different question and the two disagree. Takes margins and base_demands (one per product) plus the substitution matrix flattened ROW-MAJOR — substitution[j*n+i] is the fraction of product j’s demand that moves to product i — and a shelf limit. Returns a boolean per product and the resulting captured margin. | NULL | [anofox_optimize_assortment_best_of([5.0,4.0],[100.0,90.0],[0.0,0.6,0.6,0.0], 2)] |
| anofox_optimize_assortment_greedy_marginal | scalar | Lists products one at a time, each time adding whichever raises TOTAL captured margin most given what it takes from the products already listed. Stops early when no addition helps, even below the shelf limit: listing a pure cannibaliser loses money. MODEL: CANNIBALISATION — each listed product earns margin * (base_demand minus the demand the OTHER LISTED products take from it). Listing near-duplicates destroys value here. If instead you are DELISTING and want the demand of dropped products to flow to the survivors, use the anofox_optimize_assortment_recapture_* family: it answers a different question and the two disagree. Takes margins and base_demands (one per product) plus the substitution matrix flattened ROW-MAJOR — substitution[j*n+i] is the fraction of product j’s demand that moves to product i — and a shelf limit. Returns a boolean per product and the resulting captured margin. | NULL | [anofox_optimize_assortment_greedy_marginal([5.0,4.0],[100.0,90.0],[0.0,0.6,0.6,0.0], 2)] |
| anofox_optimize_assortment_local_search | scalar | Greedy marginal, then swaps a listed product for an unlisted one while that raises captured margin. Escapes the greedy ordering, at O(n^2) evaluations per improving pass. MODEL: CANNIBALISATION — each listed product earns margin * (base_demand minus the demand the OTHER LISTED products take from it). Listing near-duplicates destroys value here. If instead you are DELISTING and want the demand of dropped products to flow to the survivors, use the anofox_optimize_assortment_recapture_* family: it answers a different question and the two disagree. Takes margins and base_demands (one per product) plus the substitution matrix flattened ROW-MAJOR — substitution[j*n+i] is the fraction of product j’s demand that moves to product i — and a shelf limit. Returns a boolean per product and the resulting captured margin. | NULL | [anofox_optimize_assortment_local_search([5.0,4.0],[100.0,90.0],[0.0,0.6,0.6,0.0], 2)] |
| anofox_optimize_assortment_recapture_best_of | scalar | Runs every recapture algorithm in this family and returns whichever recaptured the most margin. MODEL: RECAPTURE — each listed product keeps margin * base_demand IN FULL, and additionally earns the demand handed to it by DELISTED products, valued at the LISTED product’s own margin. A high-margin, low-demand product can be worth listing purely as a recapture sink, which a margindemand ranking never selects. If instead listed products erode each other, use the anofox_optimize_assortment_ family: it answers a different question and the two disagree. Takes margins and base_demands (one per product) plus the substitution matrix flattened ROW-MAJOR — substitution[j*n+i] is the fraction of product j’s demand that moves to product i — and a shelf limit. Returns a boolean per product and the resulting captured margin. | NULL | [anofox_optimize_assortment_recapture_best_of([5.0,4.0],[100.0,90.0],[0.0,0.6,0.6,0.0], 2)] |
| anofox_optimize_assortment_recapture_greedy_marginal | scalar | Lists products one at a time, each time adding whichever raises TOTAL recaptured margin most — which accounts for the demand that product stops donating to others once it is listed itself. Stops early when no addition helps, even below the shelf limit. MODEL: RECAPTURE — each listed product keeps margin * base_demand IN FULL, and additionally earns the demand handed to it by DELISTED products, valued at the LISTED product’s own margin. A high-margin, low-demand product can be worth listing purely as a recapture sink, which a margindemand ranking never selects. If instead listed products erode each other, use the anofox_optimize_assortment_ family: it answers a different question and the two disagree. Takes margins and base_demands (one per product) plus the substitution matrix flattened ROW-MAJOR — substitution[j*n+i] is the fraction of product j’s demand that moves to product i — and a shelf limit. Returns a boolean per product and the resulting captured margin. | NULL | [anofox_optimize_assortment_recapture_greedy_marginal([5.0,4.0],[100.0,90.0],[0.0,0.6,0.6,0.0], 2)] |
| anofox_optimize_assortment_recapture_local_search | scalar | Recapture greedy, then swaps a listed product for an unlisted one while that raises recaptured margin. Escapes the greedy ordering, at O(n^2) evaluations per improving pass. MODEL: RECAPTURE — each listed product keeps margin * base_demand IN FULL, and additionally earns the demand handed to it by DELISTED products, valued at the LISTED product’s own margin. A high-margin, low-demand product can be worth listing purely as a recapture sink, which a margindemand ranking never selects. If instead listed products erode each other, use the anofox_optimize_assortment_ family: it answers a different question and the two disagree. Takes margins and base_demands (one per product) plus the substitution matrix flattened ROW-MAJOR — substitution[j*n+i] is the fraction of product j’s demand that moves to product i — and a shelf limit. Returns a boolean per product and the resulting captured margin. | NULL | [anofox_optimize_assortment_recapture_local_search([5.0,4.0],[100.0,90.0],[0.0,0.6,0.6,0.0], 2)] |
| anofox_optimize_assortment_recapture_top_margin | scalar | Lists the top products by standalone marginbase_demand, IGNORING where delisted demand would go. The obvious rule, and a poor one here: it never lists a small-demand product that would soak up a lot of orphaned demand at a high margin. Included so a search has something to beat. MODEL: RECAPTURE — each listed product keeps margin * base_demand IN FULL, and additionally earns the demand handed to it by DELISTED products, valued at the LISTED product’s own margin. A high-margin, low-demand product can be worth listing purely as a recapture sink, which a margindemand ranking never selects. If instead listed products erode each other, use the anofox_optimize_assortment_* family: it answers a different question and the two disagree. Takes margins and base_demands (one per product) plus the substitution matrix flattened ROW-MAJOR — substitution[j*n+i] is the fraction of product j’s demand that moves to product i — and a shelf limit. Returns a boolean per product and the resulting captured margin. | NULL | [anofox_optimize_assortment_recapture_top_margin([5.0,4.0],[100.0,90.0],[0.0,0.6,0.6,0.0], 2)] |
| anofox_optimize_assortment_top_margin | scalar | Lists the top products by standalone margindemand, IGNORING cannibalisation. The obvious rule, and the one that overstates its own result whenever listed products substitute for each other — included so a search has something to beat. MODEL: CANNIBALISATION — each listed product earns margin * (base_demand minus the demand the OTHER LISTED products take from it). Listing near-duplicates destroys value here. If instead you are DELISTING and want the demand of dropped products to flow to the survivors, use the anofox_optimize_assortment_recapture_ family: it answers a different question and the two disagree. Takes margins and base_demands (one per product) plus the substitution matrix flattened ROW-MAJOR — substitution[j*n+i] is the fraction of product j’s demand that moves to product i — and a shelf limit. Returns a boolean per product and the resulting captured margin. | NULL | [anofox_optimize_assortment_top_margin([5.0,4.0],[100.0,90.0],[0.0,0.6,0.6,0.0], 2)] |
| anofox_optimize_knapsack_best_of | scalar | Runs the greedy knapsack members and returns whichever captured more value. Cheap and never loses to any single greedy member, but it is NOT exact — use knapsack_exact when the instance is small enough. Same signature as the other knapsack functions. | NULL | [anofox_optimize_knapsack_best_of([10.0, 6.0], [5.0, 4.0], 6.0)] |
| anofox_optimize_knapsack_exact | scalar | 0/1 knapsack solved EXACTLY by dynamic programming over integer-scaled weights. Returns the true optimum, unlike the greedy members. RAISES rather than degrading when the instance needs too large a table (many items, large capacity, or weights needing fine scaling) — a caller who asked for the exact answer and silently received a heuristic one could not tell its result is no longer a bound. Same signature as the other knapsack functions. | NULL | [anofox_optimize_knapsack_exact([10.0, 6.0], [5.0, 4.0], 6.0)] |
| anofox_optimize_knapsack_greedy_ratio | scalar | 0/1 knapsack by descending value-per-weight: takes each item that still fits. Optimal for the FRACTIONAL problem and usually good for 0/1, but can be arbitrarily bad — one heavy high-ratio item can crowd out a better combination. Returns a boolean per input item plus the selected total value and weight. | NULL | [anofox_optimize_knapsack_greedy_ratio([10.0, 6.0], [5.0, 4.0], 6.0)] |
| anofox_optimize_knapsack_greedy_value | scalar | 0/1 knapsack by descending VALUE, ignoring weight: takes each item that still fits. The weakest member of the family — it loses to by-ratio whenever value and weight are correlated — and included so a search has a poor-but-valid option to move away from. Same signature as the other knapsack functions. | NULL | [anofox_optimize_knapsack_greedy_value([10.0, 6.0], [5.0, 4.0], 6.0)] |
| anofox_optimize_matrix_from_triples | scalar | Builds the flattened ROW-MAJOR matrix the sequencing, scheduling, assortment and portfolio functions expect, from (from, to, value) TRIPLES — which is how the data is usually stored. Missing cells are 0; duplicate cells RAISE rather than silently keeping the last one. index_base is subtracted from the ids, so pass 1 for 1-based ids and 0 for 0-based. Use with list aggregation, e.g. SELECT anofox_optimize_matrix_from_triples(list(a), list(b), list(v), 8, 1) FROM t. |
NULL | [anofox_optimize_matrix_from_triples([1,2], [2,1], [0.5, 0.5], 2, 1)] |
| anofox_optimize_pack_best_fit_decreasing | scalar | Packs items into bins by best-fit-decreasing: sorts items largest first and puts each into the FULLEST bin it still fits, leaving emptier bins for larger items later. Same signature as the other packing functions. | NULL | [anofox_optimize_pack_best_fit_decreasing([4.0, 8.0, 1.0], 10.0)] |
| anofox_optimize_pack_best_of | scalar | Runs every packing algorithm in this family and returns whichever used the fewest bins. Costs the sum of the parts and never loses to any single member; use it when you do not want to choose. Same signature as the other packing functions. | NULL | [anofox_optimize_pack_best_of([4.0, 8.0, 1.0], 10.0)] |
| anofox_optimize_pack_bin_completion | scalar | Packs items by BOUNDED BIN COMPLETION: seeds each bin with the largest unplaced item, searches all PAIRS of companions exhaustively for the combination that fills the bin fullest, then tops up greedily with anything that still fits. Not exhaustive over arbitrary subsets and not optimal, but it recovers the exact three-per-bin fills that make every greedy member stall together on triplet-style instances. Costs O(n^2) per bin. Same signature as the other packing functions. | NULL | [anofox_optimize_pack_bin_completion([4.0, 8.0, 1.0], 10.0)] |
| anofox_optimize_pack_first_fit_decreasing | scalar | Packs items into bins by first-fit-decreasing: sorts items largest first and puts each into the first bin it fits. Fast and near-optimal on typical instances, but provably up to 11/9 of optimal and weak on triplet-style instances. Returns bins_used and a 0-based bin index per input item. An empty item list uses 0 bins; a non-empty list of zero-size items uses 1. | NULL | [anofox_optimize_pack_first_fit_decreasing([4.0, 8.0, 1.0], 10.0)] |
| anofox_optimize_pack_local_search | scalar | Packs items by first-fit-decreasing and then IMPROVES the result: tries to dissolve bins one at a time, from least-loaded upward, by relocating their items into other bins — including a swap that displaces a smaller item to a third bin to make room. Repeats until no bin can be emptied. Slower than the greedy members; on triplet-style instances it does not beat them (use bin_completion there). Same signature as the other packing functions. | NULL | [anofox_optimize_pack_local_search([4.0, 8.0, 1.0], 10.0)] |
| anofox_optimize_pack_next_fit | scalar | Packs items into bins by next-fit, in the given order, only ever using the most recently opened bin. The weakest member of the family and the cheapest; included so a search has a poor-but-valid baseline to move away from. | NULL | [anofox_optimize_pack_next_fit([4.0, 8.0, 1.0], 10.0)] |
| anofox_optimize_pack_worst_fit_decreasing | scalar | Packs items into bins by worst-fit-decreasing: puts each item into the EMPTIEST bin it fits, spreading load evenly. Usually uses more bins than best-fit but produces balanced loads. Same signature as the other packing functions. | NULL | [anofox_optimize_pack_worst_fit_decreasing([4.0, 8.0, 1.0], 10.0)] |
| anofox_optimize_portfolio_best_of | scalar | Runs every portfolio algorithm in this family and returns whichever achieved the highest Sharpe ratio. Takes expected_returns (one per asset) and the covariance matrix flattened ROW-MAJOR, a maximum number of holdings, and a per-asset weight cap. Weights sum to 1 over the chosen assets. Returns the weight vector, expected return, volatility and Sharpe ratio (return/volatility). | NULL | [anofox_optimize_portfolio_best_of([0.12,0.10,0.10],[0.04,0.036,-0.01,0.036,0.04,-0.01,-0.01,-0.01,0.04], 2, 0.6)] |
| anofox_optimize_portfolio_greedy_sharpe | scalar | Grows the holding set one asset at a time, each time adding whichever most improves Sharpe AFTER re-optimizing the weights — so it can pick a lower-return asset because it diversifies — then SWAPS held assets for unheld ones while that improves Sharpe, which is what lets it choose a different set when the holding limit leaves no room to grow. The member that actually uses the covariance to choose WHICH assets, not just how much of them. Takes expected_returns (one per asset) and the covariance matrix flattened ROW-MAJOR, a maximum number of holdings, and a per-asset weight cap. Weights sum to 1 over the chosen assets. Returns the weight vector, expected return, volatility and Sharpe ratio (return/volatility). | NULL | [anofox_optimize_portfolio_greedy_sharpe([0.12,0.10,0.10],[0.04,0.036,-0.01,0.036,0.04,-0.01,-0.01,-0.01,0.04], 2, 0.6)] |
| anofox_optimize_portfolio_top_return | scalar | Picks the highest-expected-return assets up to the holding limit and weights them EQUALLY, ignoring covariance entirely — so it will happily buy assets that all move together. The naive rule, included so a search has something to beat. Takes expected_returns (one per asset) and the covariance matrix flattened ROW-MAJOR, a maximum number of holdings, and a per-asset weight cap. Weights sum to 1 over the chosen assets. Returns the weight vector, expected return, volatility and Sharpe ratio (return/volatility). | NULL | [anofox_optimize_portfolio_top_return([0.12,0.10,0.10],[0.04,0.036,-0.01,0.036,0.04,-0.01,-0.01,-0.01,0.04], 2, 0.6)] |
| anofox_optimize_portfolio_top_return_optimized | scalar | Picks the highest-expected-return assets up to the holding limit, then OPTIMISES THE WEIGHTS on that fixed set by projected gradient ascent on Sharpe. Better than equal weighting, but still cannot choose a lower-return asset that would diversify. Takes expected_returns (one per asset) and the covariance matrix flattened ROW-MAJOR, a maximum number of holdings, and a per-asset weight cap. Weights sum to 1 over the chosen assets. Returns the weight vector, expected return, volatility and Sharpe ratio (return/volatility). | NULL | [anofox_optimize_portfolio_top_return_optimized([0.12,0.10,0.10],[0.04,0.036,-0.01,0.036,0.04,-0.01,-0.01,-0.01,0.04], 2, 0.6)] |
| anofox_optimize_schedule_atcs | scalar | Sequences jobs by APPARENT TARDINESS COST WITH SETUPS: at each step picks the job maximising priority/processing, discounted by its slack and by the setup needed to switch to it. Unlike EDD and WSPT it weighs due dates, priorities AND setups together, which is what this objective actually trades off. Takes processing_times, due_dates and priorities (one per job) plus the setup matrix flattened ROW-MAJOR over n+1 rows, where index 0 is the VIRTUAL START: setup[i*(n+1)+j] is the cost of running job j-1 after job i-1, and row 0 is the cost of running a job first. Returns a 0-based job order, the total priority-weighted tardiness of that order, and its makespan. | NULL | [anofox_optimize_schedule_atcs([10.0,10.0],[20.0,5.0],[1.0,3.0],[5.0,5.0,5.0,0.0,2.0,2.0,0.0,2.0,2.0], 2)] |
| anofox_optimize_schedule_best_of | scalar | Runs every scheduling algorithm in this family and returns whichever had the lowest total weighted tardiness. Costs the sum of the parts and never loses to any single member. Takes processing_times, due_dates and priorities (one per job) plus the setup matrix flattened ROW-MAJOR over n+1 rows, where index 0 is the VIRTUAL START: setup[i*(n+1)+j] is the cost of running job j-1 after job i-1, and row 0 is the cost of running a job first. Returns a 0-based job order, the total priority-weighted tardiness of that order, and its makespan. | NULL | [anofox_optimize_schedule_best_of([10.0,10.0],[20.0,5.0],[1.0,3.0],[5.0,5.0,5.0,0.0,2.0,2.0,0.0,2.0,2.0], 2)] |
| anofox_optimize_schedule_edd | scalar | Sequences jobs by EARLIEST DUE DATE. The textbook rule and optimal for maximum lateness without setups, but it ignores priorities and setup costs entirely, so it can be poor on weighted tardiness. Takes processing_times, due_dates and priorities (one per job) plus the setup matrix flattened ROW-MAJOR over n+1 rows, where index 0 is the VIRTUAL START: setup[i*(n+1)+j] is the cost of running job j-1 after job i-1, and row 0 is the cost of running a job first. Returns a 0-based job order, the total priority-weighted tardiness of that order, and its makespan. | NULL | [anofox_optimize_schedule_edd([10.0,10.0],[20.0,5.0],[1.0,3.0],[5.0,5.0,5.0,0.0,2.0,2.0,0.0,2.0,2.0], 2)] |
| anofox_optimize_schedule_exact | scalar | The PROVEN OPTIMUM by Held-Karp dynamic programming over (scheduled set, last job). Weighted tardiness with sequence-dependent setups is NP-hard, so this is exponential: it REFUSES more than 16 jobs with an error naming the heuristic to use instead, rather than running for hours. Use it to check how far a heuristic really is on a small instance. Takes processing_times, due_dates and priorities (one per job) plus the setup matrix flattened ROW-MAJOR over n+1 rows, where index 0 is the VIRTUAL START: setup[i*(n+1)+j] is the cost of running job j-1 after job i-1, and row 0 is the cost of running a job first. Returns a 0-based job order, the total priority-weighted tardiness of that order, and its makespan. | NULL | [anofox_optimize_schedule_exact([10.0,10.0],[20.0,5.0],[1.0,3.0],[5.0,5.0,5.0,0.0,2.0,2.0,0.0,2.0,2.0], 2)] |
| anofox_optimize_schedule_local_search | scalar | Sequences by ATCS and then improves with adjacent-pair swaps while they reduce weighted tardiness. Slower than the dispatch rules and usually better than any of them alone. Takes processing_times, due_dates and priorities (one per job) plus the setup matrix flattened ROW-MAJOR over n+1 rows, where index 0 is the VIRTUAL START: setup[i*(n+1)+j] is the cost of running job j-1 after job i-1, and row 0 is the cost of running a job first. Returns a 0-based job order, the total priority-weighted tardiness of that order, and its makespan. | NULL | [anofox_optimize_schedule_local_search([10.0,10.0],[20.0,5.0],[1.0,3.0],[5.0,5.0,5.0,0.0,2.0,2.0,0.0,2.0,2.0], 2)] |
| anofox_optimize_schedule_wspt | scalar | Sequences jobs by WEIGHTED SHORTEST PROCESSING TIME (priority/processing, descending). Strong when nearly everything will be late, weak when only a few jobs are, because it ignores due dates and setups. Takes processing_times, due_dates and priorities (one per job) plus the setup matrix flattened ROW-MAJOR over n+1 rows, where index 0 is the VIRTUAL START: setup[i*(n+1)+j] is the cost of running job j-1 after job i-1, and row 0 is the cost of running a job first. Returns a 0-based job order, the total priority-weighted tardiness of that order, and its makespan. | NULL | [anofox_optimize_schedule_wspt([10.0,10.0],[20.0,5.0],[1.0,3.0],[5.0,5.0,5.0,0.0,2.0,2.0,0.0,2.0,2.0], 2)] |
| anofox_optimize_sequence_as_given | scalar | Sequences jobs in the order given, changing nothing. The do-nothing baseline and usually poor; included so a search has a valid option to move away from rather than seeing every member look equally good. setup is the nn matrix flattened ROW-MAJOR: setup[in+j] is the cost of running job j immediately after job i. Returns a 0-based job order and the total setup cost of that order. |
NULL | [anofox_optimize_sequence_as_given([0.0,5.0,9.0,5.0,0.0,3.0,9.0,3.0,0.0], 3)] |
| anofox_optimize_sequence_best_of | scalar | Runs every sequencing algorithm in this family and returns whichever had the lowest total setup. Costs the sum of the parts and never loses to any single member. setup is the nn matrix flattened ROW-MAJOR: setup[in+j] is the cost of running job j immediately after job i. Returns a 0-based job order and the total setup cost of that order. |
NULL | [anofox_optimize_sequence_best_of([0.0,5.0,9.0,5.0,0.0,3.0,9.0,3.0,0.0], 3)] |
| anofox_optimize_sequence_nearest_neighbour | scalar | Sequences jobs by repeatedly jumping to the cheapest unvisited successor, starting from job 0. Fast and usually far better than the given order; its classic failure is stranding an expensive job until last, which it cannot then undo. setup is the nn matrix flattened ROW-MAJOR: setup[in+j] is the cost of running job j immediately after job i. Returns a 0-based job order and the total setup cost of that order. |
NULL | [anofox_optimize_sequence_nearest_neighbour([0.0,5.0,9.0,5.0,0.0,3.0,9.0,3.0,0.0], 3)] |
| anofox_optimize_sequence_two_opt | scalar | Sequences jobs by nearest-neighbour and then improves with 2-OPT: reverses any segment whose reversal lowers total setup, until none does. The member that can escape a bad greedy start, at O(n^2) per improving pass. setup is the nn matrix flattened ROW-MAJOR: setup[in+j] is the cost of running job j immediately after job i. Returns a 0-based job order and the total setup cost of that order. |
NULL | [anofox_optimize_sequence_two_opt([0.0,5.0,9.0,5.0,0.0,3.0,9.0,3.0,0.0], 3)] |
| anofox_optimize_version | scalar | Returns the version of the loaded anofox_optimize extension, as stamped by the build. | NULL | [anofox_optimize_version()] |
| anofox_optimize_wave_as_given | scalar | Batches orders into capacity-bounded waves in the order given. The do-nothing baseline and usually poor; included so a search has a valid option to move away from. Takes items and priorities (one per order) and a per-wave capacity. Returns a 1-based wave number per order and the priority-weighted mean wave, sum(wave*priority)/sum(priority) — lower is better. | NULL | [anofox_optimize_wave_as_given([3.0,4.0,5.0],[1.0,5.0,1.0], 7.0)] |
| anofox_optimize_wave_best_of | scalar | Runs every batching algorithm in this family and returns whichever had the lowest priority-weighted mean wave. Takes items and priorities (one per order) and a per-wave capacity. Returns a 1-based wave number per order and the priority-weighted mean wave, sum(wave*priority)/sum(priority) — lower is better. | NULL | [anofox_optimize_wave_best_of([3.0,4.0,5.0],[1.0,5.0,1.0], 7.0)] |
| anofox_optimize_wave_fewest_waves | scalar | Batches largest orders first, minimising the NUMBER of waves rather than the weighted mean wave. Kept deliberately: it optimizes the wrong quantity for this objective, and shows what that costs. Takes items and priorities (one per order) and a per-wave capacity. Returns a 1-based wave number per order and the priority-weighted mean wave, sum(wave*priority)/sum(priority) — lower is better. | NULL | [anofox_optimize_wave_fewest_waves([3.0,4.0,5.0],[1.0,5.0,1.0], 7.0)] |
| anofox_optimize_wave_priority_density | scalar | Batches by highest priority PER UNIT OF WORK, since an urgent order that fills a whole wave delays everything behind it. Usually beats plain priority-first when order sizes vary widely. Takes items and priorities (one per order) and a per-wave capacity. Returns a 1-based wave number per order and the priority-weighted mean wave, sum(wave*priority)/sum(priority) — lower is better. | NULL | [anofox_optimize_wave_priority_density([3.0,4.0,5.0],[1.0,5.0,1.0], 7.0)] |
| anofox_optimize_wave_priority_first | scalar | Batches HIGHEST PRIORITY FIRST, so urgent orders land in early waves. Directly targets the weighted-wave objective; can waste capacity when an urgent order is also large. Takes items and priorities (one per order) and a per-wave capacity. Returns a 1-based wave number per order and the priority-weighted mean wave, sum(wave*priority)/sum(priority) — lower is better. | NULL | [anofox_optimize_wave_priority_first([3.0,4.0,5.0],[1.0,5.0,1.0], 7.0)] |
| opt_assortment_best_of | scalar | NULL | NULL | |
| opt_assortment_greedy_marginal | scalar | NULL | NULL | |
| opt_assortment_local_search | scalar | NULL | NULL | |
| opt_assortment_recapture_best_of | scalar | NULL | NULL | |
| opt_assortment_recapture_greedy_marginal | scalar | NULL | NULL | |
| opt_assortment_recapture_local_search | scalar | NULL | NULL | |
| opt_assortment_recapture_top_margin | scalar | NULL | NULL | |
| opt_assortment_top_margin | scalar | NULL | NULL | |
| opt_knapsack_best_of | scalar | NULL | NULL | |
| opt_knapsack_exact | scalar | NULL | NULL | |
| opt_knapsack_greedy_ratio | scalar | NULL | NULL | |
| opt_knapsack_greedy_value | scalar | NULL | NULL | |
| opt_matrix_from_triples | scalar | NULL | NULL | |
| opt_pack_best_fit_decreasing | scalar | NULL | NULL | |
| opt_pack_best_of | scalar | NULL | NULL | |
| opt_pack_bin_completion | scalar | NULL | NULL | |
| opt_pack_first_fit_decreasing | scalar | NULL | NULL | |
| opt_pack_local_search | scalar | NULL | NULL | |
| opt_pack_next_fit | scalar | NULL | NULL | |
| opt_pack_worst_fit_decreasing | scalar | NULL | NULL | |
| opt_portfolio_best_of | scalar | NULL | NULL | |
| opt_portfolio_greedy_sharpe | scalar | NULL | NULL | |
| opt_portfolio_top_return | scalar | NULL | NULL | |
| opt_portfolio_top_return_optimized | scalar | NULL | NULL | |
| opt_schedule_atcs | scalar | NULL | NULL | |
| opt_schedule_best_of | scalar | NULL | NULL | |
| opt_schedule_edd | scalar | NULL | NULL | |
| opt_schedule_exact | scalar | NULL | NULL | |
| opt_schedule_local_search | scalar | NULL | NULL | |
| opt_schedule_wspt | scalar | NULL | NULL | |
| opt_sequence_as_given | scalar | NULL | NULL | |
| opt_sequence_best_of | scalar | NULL | NULL | |
| opt_sequence_nearest_neighbour | scalar | NULL | NULL | |
| opt_sequence_two_opt | scalar | NULL | NULL | |
| opt_version | scalar | NULL | NULL | |
| opt_wave_as_given | scalar | NULL | NULL | |
| opt_wave_best_of | scalar | NULL | NULL | |
| opt_wave_fewest_waves | scalar | NULL | NULL | |
| opt_wave_priority_density | scalar | NULL | NULL | |
| opt_wave_priority_first | scalar | NULL | NULL |
Überladene Funktionen
Diese Erweiterung fügt keine Funktionsüberladungen hinzu.
Hinzugefügte Typen
Diese Erweiterung fügt keine Typen hinzu.
Hinzugefügte Einstellungen
| name | description | input_type | scope | aliases |
|---|---|---|---|---|
| anofox_telemetry_enabled | Enable or disable anonymous usage telemetry | BOOLEAN | GLOBAL | [] |
| anofox_telemetry_key | PostHog API key for telemetry | VARCHAR | GLOBAL | [] |
| datazoo_banner | Show the DataZoo feedback banner when an extension is loaded in an interactive terminal (at most once a day per extension). | BOOLEAN | GLOBAL | [] |