[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-nvidia-generic-max-supply":3,"mdc--20io63-key":43,"related-repo-nvidia-generic-max-supply":2451,"related-org-nvidia-generic-max-supply":2540},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":23,"repoUrl":24,"updatedAt":25,"license":26,"forks":27,"topics":28,"repo":38,"sourceUrl":41,"mdContent":42},"generic-max-supply","plan supply chain models with cuOpt","Multi-period supply chain planning model: data files, BOM structure, variable\u002Fconstraint reference for the max-supply base model.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},"nvidia","NVIDIA","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fnvidia.png",[12,16,19,22],{"name":13,"slug":14,"type":15},"Supply Chain","supply-chain","tag",{"name":17,"slug":18,"type":15},"Optimization","optimization",{"name":20,"slug":21,"type":15},"Data Modeling","data-modeling",{"name":9,"slug":8,"type":15},462,"https:\u002F\u002Fgithub.com\u002FNVIDIA\u002Fcuopt-examples","2026-07-14T05:32:29.39577",null,81,[29,30,31,32,33,18,34,35,36,37],"combinatorial-optimization","gpu","linear-programming","mixed-integer-programming","operations-research","optimization-algorithms","route-optimization","traveling-salesman-problem","vehicle-routing-problem",{"repoUrl":24,"stars":23,"forks":27,"topics":39,"description":40},[29,30,31,32,33,18,34,35,36,37],"NVIDIA cuOpt examples for decision optimization","https:\u002F\u002Fgithub.com\u002FNVIDIA\u002Fcuopt-examples\u002Ftree\u002FHEAD\u002Fcuopt-agent\u002Fskills\u002Fmax-supply\u002Fgeneric-max-supply","---\nname: generic-max-supply\ndescription: >\n  Multi-period supply chain planning model: data files, BOM structure,\n  variable\u002Fconstraint reference for the max-supply base model.\nusage: >\n  - Use for *formulating* or *modifying* the max-supply MILP (constraints, objective, BOM).\n  Read data file map and variable\u002Fconstraint reference before coding. Scripts and data under this skill (scripts\u002F, scripts\u002Fdata\u002F).\n  - One task only; do not split (e.g. change model, run, compare in one step).\n---\n\n# Generic Max-Supply Planning\n\n## Core\n\n- **Execution order (mandatory):** read `scripts\u002Fmodel.py` first, then decide relevant CSV files from the prompt, then read only those CSVs, then run baseline `model.py`, then copy to `model_whatif.py`, apply a targeted edit, and run `model_whatif.py`.\n- **Source data and reference model:** **scripts\u002F** for Python (`data.py`, `model.py`); **scripts\u002Fdata\u002F** for CSV inputs. `load_data(data_dir, num_periods)` reads from that data directory; optional cost\u002Fbacklog files are read separately if needed.\n\n## Workspace layout\n\n| Location | Contents |\n|----------|----------|\n| **scripts\u002F** | Python: `data.py` (load_data), `model.py` (build\u002Fsolve). Run from repository root (or your run directory) with `python scripts\u002Fmodel.py`. |\n| **scripts\u002Fdata\u002F** | Required and optional CSV files (items, families, processes, supply, demand, etc.). All files from the [data file map](#data-file-map) live here. |\n\n## Using in the working directory\n\nDo not modify the skill files. To run or change the model: (1) Copy `skills\u002Fgeneric-max-supply\u002Fscripts\u002F` into your run directory. (2) Edit only the copy. (3) Run from that run directory or repository root. Do not assume a fixed sandbox cwd.\n\n```bash\ncp -r skills\u002Fgeneric-max-supply\u002Fscripts . && python3 scripts\u002Fmodel.py\n```\n(From repository root, this copies `skills\u002Fgeneric-max-supply\u002Fscripts\u002F` to `.\u002Fscripts\u002F`.)\n\n## What-If Variants\n\nTo run a what-if scenario (e.g. change opening inventory, tighten a supply cap, modify a cost):\n\n1. Read `model.py` first (required), identify which model block changes, and infer which CSV files are relevant to the requested change.\n\n2. Read only relevant CSV files for the prompt. Do not read all CSVs unless explicitly requested.\n\n3. Copy the scripts to the working directory and fix the data path:\n   ```bash\n   cp skills\u002Fgeneric-max-supply\u002Fscripts\u002Fdata.py data.py\n   cp skills\u002Fgeneric-max-supply\u002Fscripts\u002Fmodel.py model.py\n   ```\n   Then update `DATA_DIR` in the copied `model.py` to match your CSV location.\n\n4. Run baseline first and capture base objective:\n   ```bash\n   python model.py\n   ```\n\n5. Fork the working model:\n   ```bash\n   cp model.py model_whatif.py\n   ```\n\n6. Use `edit_file` to make **only** the targeted change in `model_whatif.py`.\n\n7. Run the what-if model and compare against baseline:\n   ```bash\n   python model_whatif.py   # ← this is the what-if result\n   ```\n\n**Do not rewrite the model from scratch.** One targeted edit keeps the change isolated and the comparison meaningful.\n\n## Problem overview\n\n**Type:** MILP (Mixed-Integer Linear Program)\n**Sense:** MAXIMIZE\n**Horizon:** configurable `num_periods` (default 10)\n\nThe planner decides how many units of each manufacturing process to run on each resource in each period. The goal is to maximise the weighted sum of finished-good inventory at the end of the last period. Constraints capture multi-level BOM structure, lead-time offsets, integer yield truncation, material supply caps, and machine-hour capacity.\n\n## Data file map\n\nAll files live in the same directory (**scripts\u002Fdata\u002F**). `load_data(data_dir, num_periods)` reads all required CSVs from that directory; the three optional cost\u002Fbacklog files are read separately if needed.\n\n| File | Key columns | What it populates |\n|------|-------------|-------------------|\n| `items.csv` | `item_id`, `name`, `family_id` | `all_items`, `item_family` lookup |\n| `families.csv` | `family_id`, `name`, `is_constrained` | `constrained_families`, `unconstrained_families` |\n| `processes.csv` | `process_id`, `name`, `lead_time`, `hours_per_unit` | `all_processes`, `process_lead_time`, `process_hours` |\n| `process_inputs.csv` | `process_id`, `item_id`, `quantity` | `process_input_qty[(p,i)]`, `item_consuming_processes` |\n| `process_outputs.csv` | `process_id`, `item_id`, `quantity` | `process_output_qty[(p,i)]`, `item_producing_processes`, derives `produced_items` |\n| `process_resources.csv` | `process_id`, `resource_id` | `process_resource_pairs`, `process_to_resources`, `resource_to_processes` |\n| `resources.csv` | `resource_id`, `name`, `period`, `available_hours` | `all_resources`, `resource_capacity[(r,t)]` |\n| `supply.csv` | `item_id`, `period`, `quantity` | `supply_qty[(i,t)]` — upper bound on procurement per period |\n| `demand.csv` | `item_id`, `period`, `quantity`, `priority_weight` | `final_items`, `demand_weight[i]` (only `priority_weight` is used in the base model) |\n\n**Optional files — NOT loaded by `data.py`; read separately if needed:**\n\n| File | Key columns | Purpose |\n|------|-------------|---------|\n| `item_costs.csv` | `item_id`, `unit_cost`, `holding_cost` | Per-unit purchase cot and per-period holding cost |\n| `resource_costs.csv` | `resource_id`, `production_cost_per_hour` | Cost per machine-hour by resource |\n| `backlog_params.csv` | `parameter`, `value` | Single row: `backlog_cost_rate` |\n\n## Key sets and derivation\n\n```python\nproduced_items      = set(process_outputs_df[\"item_id\"])\nprocured_items      = all_items - produced_items\nfinal_items         = set(demand_df[\"item_id\"])\n\nconstrained_families   = {f where is_constrained == True}\nunconstrained_families = {f where is_constrained == False}\n\n# A process is constrained if ANY of its output items is in a constrained family.\nprocess_is_constrained[p] = any(\n    item_family[i] in constrained_families\n    for i in outputs_of(p)\n)\n```\n\nIn the sample dataset: `FAM_FG`, `FAM_SA`, `FAM_RM1` are constrained; `FAM_RM2` is not. `RM3` (family `FAM_RM2`) is procured but unconstrained — no supply cap applied. All four processes (`PROC1`–`PROC4`) are constrained because they produce items in constrained families.\n\n## Variable reference\n\n| Variable | Represents | Domain | Initialisation |\n|----------|-----------|--------|----------------|\n| `x[p, r, t]` | Units of process `p` executed on resource `r` starting in period `t` | Continuous ≥ 0 | `addVariable(lb=0, vtype=CONTINUOUS)` |\n| `produced[i, t]` | Continuous (possibly fractional) output of item `i` in period `t` | Continuous ≥ 0 | `addVariable(lb=0, vtype=CONTINUOUS)` |\n| `used[i, t]` | Usable (floor-truncated) integer output of item `i` in period `t` | Integer ≥ 0 | `addVariable(lb=0, vtype=INTEGER)` |\n| `buy[i, t]` | Units of procured item `i` purchased in period `t` | Continuous ≥ 0 | `addVariable(lb=0, vtype=CONTINUOUS)` |\n| `inventory[i, t]` | On-hand inventory of item `i` at end of period `t` | Continuous ≥ 0 | `addVariable(lb=0, vtype=CONTINUOUS)` |\n| `inventory[i, 0]` | Opening balance (fixed to zero) | Continuous, lb=ub=0 | `addVariable(lb=0, ub=0, vtype=CONTINUOUS)` |\n\n`inventory[i, 0]` is a fixed variable (lb = ub = 0). For a non-zero opening balance, set ub = lb = opening_balance.\n\n## Constraint map\n\n| Label | Name pattern | What it enforces | Variables linked |\n|-------|-------------|-----------------|-----------------|\n| C1 | `prod_def_{i}_{t}` | `produced[i,t]` equals the sum of BOM-output quantities from all processes that **started** at `t − lead_time` | `produced`, `x` |\n| C2a | `trunc_upper_{i}_{t}` | `used[i,t] ≤ produced[i,t]` (integer cannot exceed real output) | `used`, `produced` |\n| C2b | `trunc_lower_{i}_{t}` | `used[i,t] ≥ produced[i,t] − (1 − ε)` with ε = 1e-4 (forces integer to be the floor) | `used`, `produced` |\n| C3a | `bal_proc_{i}_{t}` | Material balance for **procured** items: `inv[i,t] = inv[i,t−1] + buy[i,t] − consumption` | `inventory`, `buy`, `x` |\n| C3b | `bal_prod_{i}_{t}` | Material balance for **produced** items: `inv[i,t] = inv[i,t−1] + used[i,t] − consumption` | `inventory`, `used`, `x` |\n| C4 | `supply_{i}_{t}` | `buy[i,t] ≤ supply_qty[(i,t)]` — only applied to procured items in **constrained** families | `buy` |\n| C5 | `cap_{r}_{t}` | `Σ hours_per_unit[p] · x[p,r,t] ≤ capacity[(r,t)]` — only processes where `process_is_constrained[p]` is True | `x` |\n\n**Lead-time note:** C1 uses `start_t = t − lead_time[p]`. If `start_t \u003C 1`, the term is skipped (process cannot have started before period 1).\n\n## Objective\n\n```python\nlast_t = max(data.periods)\nobj = Σ  demand_weight[i] * inventory[i, last_t]   for i in final_items\n```\n\nMaximise the priority-weighted inventory of finished goods at the end of the planning horizon. `demand_weight` comes from the `priority_weight` column in `demand.csv` (the `quantity` column in demand.csv is present but not used by the base model).\n\n## Solver settings (default)\n\n```python\nsettings = SolverSettings()\nsettings.set_parameter(\"mip_relative_gap\", 0.01)\nprob.solve(settings)\n```\n\n`mip_relative_gap = 0.01` (1% gap). **Do not change solver precision** (e.g. do not tighten to 0.1% or 0.0); use this default only.\n\n## Sanity-checking results\n\nAfter solving, verify the model is correct:\n\n1. **Check model size changed** when you add items\u002Fconstraints. The solver log prints `Solving a problem with N constraints, M variables`. If you added a new item or constraint but N and M are unchanged, your data edits did not take effect — check that you edited the CSV files in the working directory.\n2. **Check item count** in the `Loading data...` output matches your expectation (e.g., adding RM4 should increase the item count by 1).\n3. **Check objective value** actually changed meaningfully. Differences smaller than the MIP gap (~1%) may just be solver noise, not real model changes.\n\n## Quick links by task\n\n| Task | Use |\n|------|-----|\n| Implement or extend the base model | Data file map, key sets, variable reference, constraint map, objective. |\n| Load or modify input data | Data file map; optional files read separately. |\n| Tune or run the solver | Solver settings (default); data in **scripts\u002Fdata\u002F** by default. |\n| Verify results after changes | Sanity-checking results. |\n",{"data":44,"body":46},{"name":4,"description":6,"usage":45},"- Use for *formulating* or *modifying* the max-supply MILP (constraints, objective, BOM). Read data file map and variable\u002Fconstraint reference before coding. Scripts and data under this skill (scripts\u002F, scripts\u002Fdata\u002F). - One task only; do not split (e.g. change model, run, compare in one step).\n",{"type":47,"children":48},"root",[49,58,65,160,166,254,260,274,329,349,355,360,558,568,574,606,611,617,635,1146,1161,1296,1302,1416,1482,1488,1769,1779,1785,2155,2181,2187,2210,2244,2250,2281,2299,2305,2310,2359,2365,2445],{"type":50,"tag":51,"props":52,"children":54},"element","h1",{"id":53},"generic-max-supply-planning",[55],{"type":56,"value":57},"text","Generic Max-Supply Planning",{"type":50,"tag":59,"props":60,"children":62},"h2",{"id":61},"core",[63],{"type":56,"value":64},"Core",{"type":50,"tag":66,"props":67,"children":68},"ul",{},[69,113],{"type":50,"tag":70,"props":71,"children":72},"li",{},[73,79,81,88,90,96,98,104,106,111],{"type":50,"tag":74,"props":75,"children":76},"strong",{},[77],{"type":56,"value":78},"Execution order (mandatory):",{"type":56,"value":80}," read ",{"type":50,"tag":82,"props":83,"children":85},"code",{"className":84},[],[86],{"type":56,"value":87},"scripts\u002Fmodel.py",{"type":56,"value":89}," first, then decide relevant CSV files from the prompt, then read only those CSVs, then run baseline ",{"type":50,"tag":82,"props":91,"children":93},{"className":92},[],[94],{"type":56,"value":95},"model.py",{"type":56,"value":97},", then copy to ",{"type":50,"tag":82,"props":99,"children":101},{"className":100},[],[102],{"type":56,"value":103},"model_whatif.py",{"type":56,"value":105},", apply a targeted edit, and run ",{"type":50,"tag":82,"props":107,"children":109},{"className":108},[],[110],{"type":56,"value":103},{"type":56,"value":112},".",{"type":50,"tag":70,"props":114,"children":115},{},[116,121,123,128,130,136,138,143,145,150,152,158],{"type":50,"tag":74,"props":117,"children":118},{},[119],{"type":56,"value":120},"Source data and reference model:",{"type":56,"value":122}," ",{"type":50,"tag":74,"props":124,"children":125},{},[126],{"type":56,"value":127},"scripts\u002F",{"type":56,"value":129}," for Python (",{"type":50,"tag":82,"props":131,"children":133},{"className":132},[],[134],{"type":56,"value":135},"data.py",{"type":56,"value":137},", ",{"type":50,"tag":82,"props":139,"children":141},{"className":140},[],[142],{"type":56,"value":95},{"type":56,"value":144},"); ",{"type":50,"tag":74,"props":146,"children":147},{},[148],{"type":56,"value":149},"scripts\u002Fdata\u002F",{"type":56,"value":151}," for CSV inputs. ",{"type":50,"tag":82,"props":153,"children":155},{"className":154},[],[156],{"type":56,"value":157},"load_data(data_dir, num_periods)",{"type":56,"value":159}," reads from that data directory; optional cost\u002Fbacklog files are read separately if needed.",{"type":50,"tag":59,"props":161,"children":163},{"id":162},"workspace-layout",[164],{"type":56,"value":165},"Workspace layout",{"type":50,"tag":167,"props":168,"children":169},"table",{},[170,189],{"type":50,"tag":171,"props":172,"children":173},"thead",{},[174],{"type":50,"tag":175,"props":176,"children":177},"tr",{},[178,184],{"type":50,"tag":179,"props":180,"children":181},"th",{},[182],{"type":56,"value":183},"Location",{"type":50,"tag":179,"props":185,"children":186},{},[187],{"type":56,"value":188},"Contents",{"type":50,"tag":190,"props":191,"children":192},"tbody",{},[193,230],{"type":50,"tag":175,"props":194,"children":195},{},[196,204],{"type":50,"tag":197,"props":198,"children":199},"td",{},[200],{"type":50,"tag":74,"props":201,"children":202},{},[203],{"type":56,"value":127},{"type":50,"tag":197,"props":205,"children":206},{},[207,209,214,216,221,223,229],{"type":56,"value":208},"Python: ",{"type":50,"tag":82,"props":210,"children":212},{"className":211},[],[213],{"type":56,"value":135},{"type":56,"value":215}," (load_data), ",{"type":50,"tag":82,"props":217,"children":219},{"className":218},[],[220],{"type":56,"value":95},{"type":56,"value":222}," (build\u002Fsolve). Run from repository root (or your run directory) with ",{"type":50,"tag":82,"props":224,"children":226},{"className":225},[],[227],{"type":56,"value":228},"python scripts\u002Fmodel.py",{"type":56,"value":112},{"type":50,"tag":175,"props":231,"children":232},{},[233,240],{"type":50,"tag":197,"props":234,"children":235},{},[236],{"type":50,"tag":74,"props":237,"children":238},{},[239],{"type":56,"value":149},{"type":50,"tag":197,"props":241,"children":242},{},[243,245,252],{"type":56,"value":244},"Required and optional CSV files (items, families, processes, supply, demand, etc.). All files from the ",{"type":50,"tag":246,"props":247,"children":249},"a",{"href":248},"#data-file-map",[250],{"type":56,"value":251},"data file map",{"type":56,"value":253}," live here.",{"type":50,"tag":59,"props":255,"children":257},{"id":256},"using-in-the-working-directory",[258],{"type":56,"value":259},"Using in the working directory",{"type":50,"tag":261,"props":262,"children":263},"p",{},[264,266,272],{"type":56,"value":265},"Do not modify the skill files. To run or change the model: (1) Copy ",{"type":50,"tag":82,"props":267,"children":269},{"className":268},[],[270],{"type":56,"value":271},"skills\u002Fgeneric-max-supply\u002Fscripts\u002F",{"type":56,"value":273}," into your run directory. (2) Edit only the copy. (3) Run from that run directory or repository root. Do not assume a fixed sandbox cwd.",{"type":50,"tag":275,"props":276,"children":281},"pre",{"className":277,"code":278,"language":279,"meta":280,"style":280},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","cp -r skills\u002Fgeneric-max-supply\u002Fscripts . && python3 scripts\u002Fmodel.py\n","bash","",[282],{"type":50,"tag":82,"props":283,"children":284},{"__ignoreMap":280},[285],{"type":50,"tag":286,"props":287,"children":290},"span",{"class":288,"line":289},"line",1,[291,297,303,308,313,319,324],{"type":50,"tag":286,"props":292,"children":294},{"style":293},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[295],{"type":56,"value":296},"cp",{"type":50,"tag":286,"props":298,"children":300},{"style":299},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[301],{"type":56,"value":302}," -r",{"type":50,"tag":286,"props":304,"children":305},{"style":299},[306],{"type":56,"value":307}," skills\u002Fgeneric-max-supply\u002Fscripts",{"type":50,"tag":286,"props":309,"children":310},{"style":299},[311],{"type":56,"value":312}," .",{"type":50,"tag":286,"props":314,"children":316},{"style":315},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[317],{"type":56,"value":318}," &&",{"type":50,"tag":286,"props":320,"children":321},{"style":293},[322],{"type":56,"value":323}," python3",{"type":50,"tag":286,"props":325,"children":326},{"style":299},[327],{"type":56,"value":328}," scripts\u002Fmodel.py\n",{"type":50,"tag":261,"props":330,"children":331},{},[332,334,339,341,347],{"type":56,"value":333},"(From repository root, this copies ",{"type":50,"tag":82,"props":335,"children":337},{"className":336},[],[338],{"type":56,"value":271},{"type":56,"value":340}," to ",{"type":50,"tag":82,"props":342,"children":344},{"className":343},[],[345],{"type":56,"value":346},".\u002Fscripts\u002F",{"type":56,"value":348},".)",{"type":50,"tag":59,"props":350,"children":352},{"id":351},"what-if-variants",[353],{"type":56,"value":354},"What-If Variants",{"type":50,"tag":261,"props":356,"children":357},{},[358],{"type":56,"value":359},"To run a what-if scenario (e.g. change opening inventory, tighten a supply cap, modify a cost):",{"type":50,"tag":361,"props":362,"children":363},"ol",{},[364,376,381,449,473,502,528],{"type":50,"tag":70,"props":365,"children":366},{},[367,369,374],{"type":56,"value":368},"Read ",{"type":50,"tag":82,"props":370,"children":372},{"className":371},[],[373],{"type":56,"value":95},{"type":56,"value":375}," first (required), identify which model block changes, and infer which CSV files are relevant to the requested change.",{"type":50,"tag":70,"props":377,"children":378},{},[379],{"type":56,"value":380},"Read only relevant CSV files for the prompt. Do not read all CSVs unless explicitly requested.",{"type":50,"tag":70,"props":382,"children":383},{},[384,386,428,432,434,440,442,447],{"type":56,"value":385},"Copy the scripts to the working directory and fix the data path:",{"type":50,"tag":275,"props":387,"children":389},{"className":277,"code":388,"language":279,"meta":280,"style":280},"cp skills\u002Fgeneric-max-supply\u002Fscripts\u002Fdata.py data.py\ncp skills\u002Fgeneric-max-supply\u002Fscripts\u002Fmodel.py model.py\n",[390],{"type":50,"tag":82,"props":391,"children":392},{"__ignoreMap":280},[393,410],{"type":50,"tag":286,"props":394,"children":395},{"class":288,"line":289},[396,400,405],{"type":50,"tag":286,"props":397,"children":398},{"style":293},[399],{"type":56,"value":296},{"type":50,"tag":286,"props":401,"children":402},{"style":299},[403],{"type":56,"value":404}," skills\u002Fgeneric-max-supply\u002Fscripts\u002Fdata.py",{"type":50,"tag":286,"props":406,"children":407},{"style":299},[408],{"type":56,"value":409}," data.py\n",{"type":50,"tag":286,"props":411,"children":413},{"class":288,"line":412},2,[414,418,423],{"type":50,"tag":286,"props":415,"children":416},{"style":293},[417],{"type":56,"value":296},{"type":50,"tag":286,"props":419,"children":420},{"style":299},[421],{"type":56,"value":422}," skills\u002Fgeneric-max-supply\u002Fscripts\u002Fmodel.py",{"type":50,"tag":286,"props":424,"children":425},{"style":299},[426],{"type":56,"value":427}," model.py\n",{"type":50,"tag":429,"props":430,"children":431},"br",{},[],{"type":56,"value":433},"Then update ",{"type":50,"tag":82,"props":435,"children":437},{"className":436},[],[438],{"type":56,"value":439},"DATA_DIR",{"type":56,"value":441}," in the copied ",{"type":50,"tag":82,"props":443,"children":445},{"className":444},[],[446],{"type":56,"value":95},{"type":56,"value":448}," to match your CSV location.",{"type":50,"tag":70,"props":450,"children":451},{},[452,454],{"type":56,"value":453},"Run baseline first and capture base objective:",{"type":50,"tag":275,"props":455,"children":457},{"className":277,"code":456,"language":279,"meta":280,"style":280},"python model.py\n",[458],{"type":50,"tag":82,"props":459,"children":460},{"__ignoreMap":280},[461],{"type":50,"tag":286,"props":462,"children":463},{"class":288,"line":289},[464,469],{"type":50,"tag":286,"props":465,"children":466},{"style":293},[467],{"type":56,"value":468},"python",{"type":50,"tag":286,"props":470,"children":471},{"style":299},[472],{"type":56,"value":427},{"type":50,"tag":70,"props":474,"children":475},{},[476,478],{"type":56,"value":477},"Fork the working model:",{"type":50,"tag":275,"props":479,"children":481},{"className":277,"code":480,"language":279,"meta":280,"style":280},"cp model.py model_whatif.py\n",[482],{"type":50,"tag":82,"props":483,"children":484},{"__ignoreMap":280},[485],{"type":50,"tag":286,"props":486,"children":487},{"class":288,"line":289},[488,492,497],{"type":50,"tag":286,"props":489,"children":490},{"style":293},[491],{"type":56,"value":296},{"type":50,"tag":286,"props":493,"children":494},{"style":299},[495],{"type":56,"value":496}," model.py",{"type":50,"tag":286,"props":498,"children":499},{"style":299},[500],{"type":56,"value":501}," model_whatif.py\n",{"type":50,"tag":70,"props":503,"children":504},{},[505,507,513,515,520,522,527],{"type":56,"value":506},"Use ",{"type":50,"tag":82,"props":508,"children":510},{"className":509},[],[511],{"type":56,"value":512},"edit_file",{"type":56,"value":514}," to make ",{"type":50,"tag":74,"props":516,"children":517},{},[518],{"type":56,"value":519},"only",{"type":56,"value":521}," the targeted change in ",{"type":50,"tag":82,"props":523,"children":525},{"className":524},[],[526],{"type":56,"value":103},{"type":56,"value":112},{"type":50,"tag":70,"props":529,"children":530},{},[531,533],{"type":56,"value":532},"Run the what-if model and compare against baseline:",{"type":50,"tag":275,"props":534,"children":536},{"className":277,"code":535,"language":279,"meta":280,"style":280},"python model_whatif.py   # ← this is the what-if result\n",[537],{"type":50,"tag":82,"props":538,"children":539},{"__ignoreMap":280},[540],{"type":50,"tag":286,"props":541,"children":542},{"class":288,"line":289},[543,547,552],{"type":50,"tag":286,"props":544,"children":545},{"style":293},[546],{"type":56,"value":468},{"type":50,"tag":286,"props":548,"children":549},{"style":299},[550],{"type":56,"value":551}," model_whatif.py",{"type":50,"tag":286,"props":553,"children":555},{"style":554},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic",[556],{"type":56,"value":557},"   # ← this is the what-if result\n",{"type":50,"tag":261,"props":559,"children":560},{},[561,566],{"type":50,"tag":74,"props":562,"children":563},{},[564],{"type":56,"value":565},"Do not rewrite the model from scratch.",{"type":56,"value":567}," One targeted edit keeps the change isolated and the comparison meaningful.",{"type":50,"tag":59,"props":569,"children":571},{"id":570},"problem-overview",[572],{"type":56,"value":573},"Problem overview",{"type":50,"tag":261,"props":575,"children":576},{},[577,582,584,589,591,596,598,604],{"type":50,"tag":74,"props":578,"children":579},{},[580],{"type":56,"value":581},"Type:",{"type":56,"value":583}," MILP (Mixed-Integer Linear Program)\n",{"type":50,"tag":74,"props":585,"children":586},{},[587],{"type":56,"value":588},"Sense:",{"type":56,"value":590}," MAXIMIZE\n",{"type":50,"tag":74,"props":592,"children":593},{},[594],{"type":56,"value":595},"Horizon:",{"type":56,"value":597}," configurable ",{"type":50,"tag":82,"props":599,"children":601},{"className":600},[],[602],{"type":56,"value":603},"num_periods",{"type":56,"value":605}," (default 10)",{"type":50,"tag":261,"props":607,"children":608},{},[609],{"type":56,"value":610},"The planner decides how many units of each manufacturing process to run on each resource in each period. The goal is to maximise the weighted sum of finished-good inventory at the end of the last period. Constraints capture multi-level BOM structure, lead-time offsets, integer yield truncation, material supply caps, and machine-hour capacity.",{"type":50,"tag":59,"props":612,"children":614},{"id":613},"data-file-map",[615],{"type":56,"value":616},"Data file map",{"type":50,"tag":261,"props":618,"children":619},{},[620,622,626,628,633],{"type":56,"value":621},"All files live in the same directory (",{"type":50,"tag":74,"props":623,"children":624},{},[625],{"type":56,"value":149},{"type":56,"value":627},"). ",{"type":50,"tag":82,"props":629,"children":631},{"className":630},[],[632],{"type":56,"value":157},{"type":56,"value":634}," reads all required CSVs from that directory; the three optional cost\u002Fbacklog files are read separately if needed.",{"type":50,"tag":167,"props":636,"children":637},{},[638,659],{"type":50,"tag":171,"props":639,"children":640},{},[641],{"type":50,"tag":175,"props":642,"children":643},{},[644,649,654],{"type":50,"tag":179,"props":645,"children":646},{},[647],{"type":56,"value":648},"File",{"type":50,"tag":179,"props":650,"children":651},{},[652],{"type":56,"value":653},"Key columns",{"type":50,"tag":179,"props":655,"children":656},{},[657],{"type":56,"value":658},"What it populates",{"type":50,"tag":190,"props":660,"children":661},{},[662,715,764,828,877,933,983,1039,1082],{"type":50,"tag":175,"props":663,"children":664},{},[665,674,697],{"type":50,"tag":197,"props":666,"children":667},{},[668],{"type":50,"tag":82,"props":669,"children":671},{"className":670},[],[672],{"type":56,"value":673},"items.csv",{"type":50,"tag":197,"props":675,"children":676},{},[677,683,684,690,691],{"type":50,"tag":82,"props":678,"children":680},{"className":679},[],[681],{"type":56,"value":682},"item_id",{"type":56,"value":137},{"type":50,"tag":82,"props":685,"children":687},{"className":686},[],[688],{"type":56,"value":689},"name",{"type":56,"value":137},{"type":50,"tag":82,"props":692,"children":694},{"className":693},[],[695],{"type":56,"value":696},"family_id",{"type":50,"tag":197,"props":698,"children":699},{},[700,706,707,713],{"type":50,"tag":82,"props":701,"children":703},{"className":702},[],[704],{"type":56,"value":705},"all_items",{"type":56,"value":137},{"type":50,"tag":82,"props":708,"children":710},{"className":709},[],[711],{"type":56,"value":712},"item_family",{"type":56,"value":714}," lookup",{"type":50,"tag":175,"props":716,"children":717},{},[718,727,748],{"type":50,"tag":197,"props":719,"children":720},{},[721],{"type":50,"tag":82,"props":722,"children":724},{"className":723},[],[725],{"type":56,"value":726},"families.csv",{"type":50,"tag":197,"props":728,"children":729},{},[730,735,736,741,742],{"type":50,"tag":82,"props":731,"children":733},{"className":732},[],[734],{"type":56,"value":696},{"type":56,"value":137},{"type":50,"tag":82,"props":737,"children":739},{"className":738},[],[740],{"type":56,"value":689},{"type":56,"value":137},{"type":50,"tag":82,"props":743,"children":745},{"className":744},[],[746],{"type":56,"value":747},"is_constrained",{"type":50,"tag":197,"props":749,"children":750},{},[751,757,758],{"type":50,"tag":82,"props":752,"children":754},{"className":753},[],[755],{"type":56,"value":756},"constrained_families",{"type":56,"value":137},{"type":50,"tag":82,"props":759,"children":761},{"className":760},[],[762],{"type":56,"value":763},"unconstrained_families",{"type":50,"tag":175,"props":765,"children":766},{},[767,776,805],{"type":50,"tag":197,"props":768,"children":769},{},[770],{"type":50,"tag":82,"props":771,"children":773},{"className":772},[],[774],{"type":56,"value":775},"processes.csv",{"type":50,"tag":197,"props":777,"children":778},{},[779,785,786,791,792,798,799],{"type":50,"tag":82,"props":780,"children":782},{"className":781},[],[783],{"type":56,"value":784},"process_id",{"type":56,"value":137},{"type":50,"tag":82,"props":787,"children":789},{"className":788},[],[790],{"type":56,"value":689},{"type":56,"value":137},{"type":50,"tag":82,"props":793,"children":795},{"className":794},[],[796],{"type":56,"value":797},"lead_time",{"type":56,"value":137},{"type":50,"tag":82,"props":800,"children":802},{"className":801},[],[803],{"type":56,"value":804},"hours_per_unit",{"type":50,"tag":197,"props":806,"children":807},{},[808,814,815,821,822],{"type":50,"tag":82,"props":809,"children":811},{"className":810},[],[812],{"type":56,"value":813},"all_processes",{"type":56,"value":137},{"type":50,"tag":82,"props":816,"children":818},{"className":817},[],[819],{"type":56,"value":820},"process_lead_time",{"type":56,"value":137},{"type":50,"tag":82,"props":823,"children":825},{"className":824},[],[826],{"type":56,"value":827},"process_hours",{"type":50,"tag":175,"props":829,"children":830},{},[831,840,861],{"type":50,"tag":197,"props":832,"children":833},{},[834],{"type":50,"tag":82,"props":835,"children":837},{"className":836},[],[838],{"type":56,"value":839},"process_inputs.csv",{"type":50,"tag":197,"props":841,"children":842},{},[843,848,849,854,855],{"type":50,"tag":82,"props":844,"children":846},{"className":845},[],[847],{"type":56,"value":784},{"type":56,"value":137},{"type":50,"tag":82,"props":850,"children":852},{"className":851},[],[853],{"type":56,"value":682},{"type":56,"value":137},{"type":50,"tag":82,"props":856,"children":858},{"className":857},[],[859],{"type":56,"value":860},"quantity",{"type":50,"tag":197,"props":862,"children":863},{},[864,870,871],{"type":50,"tag":82,"props":865,"children":867},{"className":866},[],[868],{"type":56,"value":869},"process_input_qty[(p,i)]",{"type":56,"value":137},{"type":50,"tag":82,"props":872,"children":874},{"className":873},[],[875],{"type":56,"value":876},"item_consuming_processes",{"type":50,"tag":175,"props":878,"children":879},{},[880,889,909],{"type":50,"tag":197,"props":881,"children":882},{},[883],{"type":50,"tag":82,"props":884,"children":886},{"className":885},[],[887],{"type":56,"value":888},"process_outputs.csv",{"type":50,"tag":197,"props":890,"children":891},{},[892,897,898,903,904],{"type":50,"tag":82,"props":893,"children":895},{"className":894},[],[896],{"type":56,"value":784},{"type":56,"value":137},{"type":50,"tag":82,"props":899,"children":901},{"className":900},[],[902],{"type":56,"value":682},{"type":56,"value":137},{"type":50,"tag":82,"props":905,"children":907},{"className":906},[],[908],{"type":56,"value":860},{"type":50,"tag":197,"props":910,"children":911},{},[912,918,919,925,927],{"type":50,"tag":82,"props":913,"children":915},{"className":914},[],[916],{"type":56,"value":917},"process_output_qty[(p,i)]",{"type":56,"value":137},{"type":50,"tag":82,"props":920,"children":922},{"className":921},[],[923],{"type":56,"value":924},"item_producing_processes",{"type":56,"value":926},", derives ",{"type":50,"tag":82,"props":928,"children":930},{"className":929},[],[931],{"type":56,"value":932},"produced_items",{"type":50,"tag":175,"props":934,"children":935},{},[936,945,960],{"type":50,"tag":197,"props":937,"children":938},{},[939],{"type":50,"tag":82,"props":940,"children":942},{"className":941},[],[943],{"type":56,"value":944},"process_resources.csv",{"type":50,"tag":197,"props":946,"children":947},{},[948,953,954],{"type":50,"tag":82,"props":949,"children":951},{"className":950},[],[952],{"type":56,"value":784},{"type":56,"value":137},{"type":50,"tag":82,"props":955,"children":957},{"className":956},[],[958],{"type":56,"value":959},"resource_id",{"type":50,"tag":197,"props":961,"children":962},{},[963,969,970,976,977],{"type":50,"tag":82,"props":964,"children":966},{"className":965},[],[967],{"type":56,"value":968},"process_resource_pairs",{"type":56,"value":137},{"type":50,"tag":82,"props":971,"children":973},{"className":972},[],[974],{"type":56,"value":975},"process_to_resources",{"type":56,"value":137},{"type":50,"tag":82,"props":978,"children":980},{"className":979},[],[981],{"type":56,"value":982},"resource_to_processes",{"type":50,"tag":175,"props":984,"children":985},{},[986,995,1023],{"type":50,"tag":197,"props":987,"children":988},{},[989],{"type":50,"tag":82,"props":990,"children":992},{"className":991},[],[993],{"type":56,"value":994},"resources.csv",{"type":50,"tag":197,"props":996,"children":997},{},[998,1003,1004,1009,1010,1016,1017],{"type":50,"tag":82,"props":999,"children":1001},{"className":1000},[],[1002],{"type":56,"value":959},{"type":56,"value":137},{"type":50,"tag":82,"props":1005,"children":1007},{"className":1006},[],[1008],{"type":56,"value":689},{"type":56,"value":137},{"type":50,"tag":82,"props":1011,"children":1013},{"className":1012},[],[1014],{"type":56,"value":1015},"period",{"type":56,"value":137},{"type":50,"tag":82,"props":1018,"children":1020},{"className":1019},[],[1021],{"type":56,"value":1022},"available_hours",{"type":50,"tag":197,"props":1024,"children":1025},{},[1026,1032,1033],{"type":50,"tag":82,"props":1027,"children":1029},{"className":1028},[],[1030],{"type":56,"value":1031},"all_resources",{"type":56,"value":137},{"type":50,"tag":82,"props":1034,"children":1036},{"className":1035},[],[1037],{"type":56,"value":1038},"resource_capacity[(r,t)]",{"type":50,"tag":175,"props":1040,"children":1041},{},[1042,1051,1071],{"type":50,"tag":197,"props":1043,"children":1044},{},[1045],{"type":50,"tag":82,"props":1046,"children":1048},{"className":1047},[],[1049],{"type":56,"value":1050},"supply.csv",{"type":50,"tag":197,"props":1052,"children":1053},{},[1054,1059,1060,1065,1066],{"type":50,"tag":82,"props":1055,"children":1057},{"className":1056},[],[1058],{"type":56,"value":682},{"type":56,"value":137},{"type":50,"tag":82,"props":1061,"children":1063},{"className":1062},[],[1064],{"type":56,"value":1015},{"type":56,"value":137},{"type":50,"tag":82,"props":1067,"children":1069},{"className":1068},[],[1070],{"type":56,"value":860},{"type":50,"tag":197,"props":1072,"children":1073},{},[1074,1080],{"type":50,"tag":82,"props":1075,"children":1077},{"className":1076},[],[1078],{"type":56,"value":1079},"supply_qty[(i,t)]",{"type":56,"value":1081}," — upper bound on procurement per period",{"type":50,"tag":175,"props":1083,"children":1084},{},[1085,1094,1121],{"type":50,"tag":197,"props":1086,"children":1087},{},[1088],{"type":50,"tag":82,"props":1089,"children":1091},{"className":1090},[],[1092],{"type":56,"value":1093},"demand.csv",{"type":50,"tag":197,"props":1095,"children":1096},{},[1097,1102,1103,1108,1109,1114,1115],{"type":50,"tag":82,"props":1098,"children":1100},{"className":1099},[],[1101],{"type":56,"value":682},{"type":56,"value":137},{"type":50,"tag":82,"props":1104,"children":1106},{"className":1105},[],[1107],{"type":56,"value":1015},{"type":56,"value":137},{"type":50,"tag":82,"props":1110,"children":1112},{"className":1111},[],[1113],{"type":56,"value":860},{"type":56,"value":137},{"type":50,"tag":82,"props":1116,"children":1118},{"className":1117},[],[1119],{"type":56,"value":1120},"priority_weight",{"type":50,"tag":197,"props":1122,"children":1123},{},[1124,1130,1131,1137,1139,1144],{"type":50,"tag":82,"props":1125,"children":1127},{"className":1126},[],[1128],{"type":56,"value":1129},"final_items",{"type":56,"value":137},{"type":50,"tag":82,"props":1132,"children":1134},{"className":1133},[],[1135],{"type":56,"value":1136},"demand_weight[i]",{"type":56,"value":1138}," (only ",{"type":50,"tag":82,"props":1140,"children":1142},{"className":1141},[],[1143],{"type":56,"value":1120},{"type":56,"value":1145}," is used in the base model)",{"type":50,"tag":261,"props":1147,"children":1148},{},[1149],{"type":50,"tag":74,"props":1150,"children":1151},{},[1152,1154,1159],{"type":56,"value":1153},"Optional files — NOT loaded by ",{"type":50,"tag":82,"props":1155,"children":1157},{"className":1156},[],[1158],{"type":56,"value":135},{"type":56,"value":1160},"; read separately if needed:",{"type":50,"tag":167,"props":1162,"children":1163},{},[1164,1183],{"type":50,"tag":171,"props":1165,"children":1166},{},[1167],{"type":50,"tag":175,"props":1168,"children":1169},{},[1170,1174,1178],{"type":50,"tag":179,"props":1171,"children":1172},{},[1173],{"type":56,"value":648},{"type":50,"tag":179,"props":1175,"children":1176},{},[1177],{"type":56,"value":653},{"type":50,"tag":179,"props":1179,"children":1180},{},[1181],{"type":56,"value":1182},"Purpose",{"type":50,"tag":190,"props":1184,"children":1185},{},[1186,1225,1257],{"type":50,"tag":175,"props":1187,"children":1188},{},[1189,1198,1220],{"type":50,"tag":197,"props":1190,"children":1191},{},[1192],{"type":50,"tag":82,"props":1193,"children":1195},{"className":1194},[],[1196],{"type":56,"value":1197},"item_costs.csv",{"type":50,"tag":197,"props":1199,"children":1200},{},[1201,1206,1207,1213,1214],{"type":50,"tag":82,"props":1202,"children":1204},{"className":1203},[],[1205],{"type":56,"value":682},{"type":56,"value":137},{"type":50,"tag":82,"props":1208,"children":1210},{"className":1209},[],[1211],{"type":56,"value":1212},"unit_cost",{"type":56,"value":137},{"type":50,"tag":82,"props":1215,"children":1217},{"className":1216},[],[1218],{"type":56,"value":1219},"holding_cost",{"type":50,"tag":197,"props":1221,"children":1222},{},[1223],{"type":56,"value":1224},"Per-unit purchase cot and per-period holding cost",{"type":50,"tag":175,"props":1226,"children":1227},{},[1228,1237,1252],{"type":50,"tag":197,"props":1229,"children":1230},{},[1231],{"type":50,"tag":82,"props":1232,"children":1234},{"className":1233},[],[1235],{"type":56,"value":1236},"resource_costs.csv",{"type":50,"tag":197,"props":1238,"children":1239},{},[1240,1245,1246],{"type":50,"tag":82,"props":1241,"children":1243},{"className":1242},[],[1244],{"type":56,"value":959},{"type":56,"value":137},{"type":50,"tag":82,"props":1247,"children":1249},{"className":1248},[],[1250],{"type":56,"value":1251},"production_cost_per_hour",{"type":50,"tag":197,"props":1253,"children":1254},{},[1255],{"type":56,"value":1256},"Cost per machine-hour by resource",{"type":50,"tag":175,"props":1258,"children":1259},{},[1260,1269,1285],{"type":50,"tag":197,"props":1261,"children":1262},{},[1263],{"type":50,"tag":82,"props":1264,"children":1266},{"className":1265},[],[1267],{"type":56,"value":1268},"backlog_params.csv",{"type":50,"tag":197,"props":1270,"children":1271},{},[1272,1278,1279],{"type":50,"tag":82,"props":1273,"children":1275},{"className":1274},[],[1276],{"type":56,"value":1277},"parameter",{"type":56,"value":137},{"type":50,"tag":82,"props":1280,"children":1282},{"className":1281},[],[1283],{"type":56,"value":1284},"value",{"type":50,"tag":197,"props":1286,"children":1287},{},[1288,1290],{"type":56,"value":1289},"Single row: ",{"type":50,"tag":82,"props":1291,"children":1293},{"className":1292},[],[1294],{"type":56,"value":1295},"backlog_cost_rate",{"type":50,"tag":59,"props":1297,"children":1299},{"id":1298},"key-sets-and-derivation",[1300],{"type":56,"value":1301},"Key sets and derivation",{"type":50,"tag":275,"props":1303,"children":1306},{"className":1304,"code":1305,"language":468,"meta":280,"style":280},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","produced_items      = set(process_outputs_df[\"item_id\"])\nprocured_items      = all_items - produced_items\nfinal_items         = set(demand_df[\"item_id\"])\n\nconstrained_families   = {f where is_constrained == True}\nunconstrained_families = {f where is_constrained == False}\n\n# A process is constrained if ANY of its output items is in a constrained family.\nprocess_is_constrained[p] = any(\n    item_family[i] in constrained_families\n    for i in outputs_of(p)\n)\n",[1307],{"type":50,"tag":82,"props":1308,"children":1309},{"__ignoreMap":280},[1310,1318,1326,1335,1345,1354,1363,1371,1380,1389,1398,1407],{"type":50,"tag":286,"props":1311,"children":1312},{"class":288,"line":289},[1313],{"type":50,"tag":286,"props":1314,"children":1315},{},[1316],{"type":56,"value":1317},"produced_items      = set(process_outputs_df[\"item_id\"])\n",{"type":50,"tag":286,"props":1319,"children":1320},{"class":288,"line":412},[1321],{"type":50,"tag":286,"props":1322,"children":1323},{},[1324],{"type":56,"value":1325},"procured_items      = all_items - produced_items\n",{"type":50,"tag":286,"props":1327,"children":1329},{"class":288,"line":1328},3,[1330],{"type":50,"tag":286,"props":1331,"children":1332},{},[1333],{"type":56,"value":1334},"final_items         = set(demand_df[\"item_id\"])\n",{"type":50,"tag":286,"props":1336,"children":1338},{"class":288,"line":1337},4,[1339],{"type":50,"tag":286,"props":1340,"children":1342},{"emptyLinePlaceholder":1341},true,[1343],{"type":56,"value":1344},"\n",{"type":50,"tag":286,"props":1346,"children":1348},{"class":288,"line":1347},5,[1349],{"type":50,"tag":286,"props":1350,"children":1351},{},[1352],{"type":56,"value":1353},"constrained_families   = {f where is_constrained == True}\n",{"type":50,"tag":286,"props":1355,"children":1357},{"class":288,"line":1356},6,[1358],{"type":50,"tag":286,"props":1359,"children":1360},{},[1361],{"type":56,"value":1362},"unconstrained_families = {f where is_constrained == False}\n",{"type":50,"tag":286,"props":1364,"children":1366},{"class":288,"line":1365},7,[1367],{"type":50,"tag":286,"props":1368,"children":1369},{"emptyLinePlaceholder":1341},[1370],{"type":56,"value":1344},{"type":50,"tag":286,"props":1372,"children":1374},{"class":288,"line":1373},8,[1375],{"type":50,"tag":286,"props":1376,"children":1377},{},[1378],{"type":56,"value":1379},"# A process is constrained if ANY of its output items is in a constrained family.\n",{"type":50,"tag":286,"props":1381,"children":1383},{"class":288,"line":1382},9,[1384],{"type":50,"tag":286,"props":1385,"children":1386},{},[1387],{"type":56,"value":1388},"process_is_constrained[p] = any(\n",{"type":50,"tag":286,"props":1390,"children":1392},{"class":288,"line":1391},10,[1393],{"type":50,"tag":286,"props":1394,"children":1395},{},[1396],{"type":56,"value":1397},"    item_family[i] in constrained_families\n",{"type":50,"tag":286,"props":1399,"children":1401},{"class":288,"line":1400},11,[1402],{"type":50,"tag":286,"props":1403,"children":1404},{},[1405],{"type":56,"value":1406},"    for i in outputs_of(p)\n",{"type":50,"tag":286,"props":1408,"children":1410},{"class":288,"line":1409},12,[1411],{"type":50,"tag":286,"props":1412,"children":1413},{},[1414],{"type":56,"value":1415},")\n",{"type":50,"tag":261,"props":1417,"children":1418},{},[1419,1421,1427,1428,1434,1435,1441,1443,1449,1451,1457,1459,1464,1466,1472,1474,1480],{"type":56,"value":1420},"In the sample dataset: ",{"type":50,"tag":82,"props":1422,"children":1424},{"className":1423},[],[1425],{"type":56,"value":1426},"FAM_FG",{"type":56,"value":137},{"type":50,"tag":82,"props":1429,"children":1431},{"className":1430},[],[1432],{"type":56,"value":1433},"FAM_SA",{"type":56,"value":137},{"type":50,"tag":82,"props":1436,"children":1438},{"className":1437},[],[1439],{"type":56,"value":1440},"FAM_RM1",{"type":56,"value":1442}," are constrained; ",{"type":50,"tag":82,"props":1444,"children":1446},{"className":1445},[],[1447],{"type":56,"value":1448},"FAM_RM2",{"type":56,"value":1450}," is not. ",{"type":50,"tag":82,"props":1452,"children":1454},{"className":1453},[],[1455],{"type":56,"value":1456},"RM3",{"type":56,"value":1458}," (family ",{"type":50,"tag":82,"props":1460,"children":1462},{"className":1461},[],[1463],{"type":56,"value":1448},{"type":56,"value":1465},") is procured but unconstrained — no supply cap applied. All four processes (",{"type":50,"tag":82,"props":1467,"children":1469},{"className":1468},[],[1470],{"type":56,"value":1471},"PROC1",{"type":56,"value":1473},"–",{"type":50,"tag":82,"props":1475,"children":1477},{"className":1476},[],[1478],{"type":56,"value":1479},"PROC4",{"type":56,"value":1481},") are constrained because they produce items in constrained families.",{"type":50,"tag":59,"props":1483,"children":1485},{"id":1484},"variable-reference",[1486],{"type":56,"value":1487},"Variable reference",{"type":50,"tag":167,"props":1489,"children":1490},{},[1491,1517],{"type":50,"tag":171,"props":1492,"children":1493},{},[1494],{"type":50,"tag":175,"props":1495,"children":1496},{},[1497,1502,1507,1512],{"type":50,"tag":179,"props":1498,"children":1499},{},[1500],{"type":56,"value":1501},"Variable",{"type":50,"tag":179,"props":1503,"children":1504},{},[1505],{"type":56,"value":1506},"Represents",{"type":50,"tag":179,"props":1508,"children":1509},{},[1510],{"type":56,"value":1511},"Domain",{"type":50,"tag":179,"props":1513,"children":1514},{},[1515],{"type":56,"value":1516},"Initialisation",{"type":50,"tag":190,"props":1518,"children":1519},{},[1520,1572,1614,1656,1697,1738],{"type":50,"tag":175,"props":1521,"children":1522},{},[1523,1532,1558,1563],{"type":50,"tag":197,"props":1524,"children":1525},{},[1526],{"type":50,"tag":82,"props":1527,"children":1529},{"className":1528},[],[1530],{"type":56,"value":1531},"x[p, r, t]",{"type":50,"tag":197,"props":1533,"children":1534},{},[1535,1537,1542,1544,1550,1552],{"type":56,"value":1536},"Units of process ",{"type":50,"tag":82,"props":1538,"children":1540},{"className":1539},[],[1541],{"type":56,"value":261},{"type":56,"value":1543}," executed on resource ",{"type":50,"tag":82,"props":1545,"children":1547},{"className":1546},[],[1548],{"type":56,"value":1549},"r",{"type":56,"value":1551}," starting in period ",{"type":50,"tag":82,"props":1553,"children":1555},{"className":1554},[],[1556],{"type":56,"value":1557},"t",{"type":50,"tag":197,"props":1559,"children":1560},{},[1561],{"type":56,"value":1562},"Continuous ≥ 0",{"type":50,"tag":197,"props":1564,"children":1565},{},[1566],{"type":50,"tag":82,"props":1567,"children":1569},{"className":1568},[],[1570],{"type":56,"value":1571},"addVariable(lb=0, vtype=CONTINUOUS)",{"type":50,"tag":175,"props":1573,"children":1574},{},[1575,1584,1602,1606],{"type":50,"tag":197,"props":1576,"children":1577},{},[1578],{"type":50,"tag":82,"props":1579,"children":1581},{"className":1580},[],[1582],{"type":56,"value":1583},"produced[i, t]",{"type":50,"tag":197,"props":1585,"children":1586},{},[1587,1589,1595,1597],{"type":56,"value":1588},"Continuous (possibly fractional) output of item ",{"type":50,"tag":82,"props":1590,"children":1592},{"className":1591},[],[1593],{"type":56,"value":1594},"i",{"type":56,"value":1596}," in period ",{"type":50,"tag":82,"props":1598,"children":1600},{"className":1599},[],[1601],{"type":56,"value":1557},{"type":50,"tag":197,"props":1603,"children":1604},{},[1605],{"type":56,"value":1562},{"type":50,"tag":197,"props":1607,"children":1608},{},[1609],{"type":50,"tag":82,"props":1610,"children":1612},{"className":1611},[],[1613],{"type":56,"value":1571},{"type":50,"tag":175,"props":1615,"children":1616},{},[1617,1626,1642,1647],{"type":50,"tag":197,"props":1618,"children":1619},{},[1620],{"type":50,"tag":82,"props":1621,"children":1623},{"className":1622},[],[1624],{"type":56,"value":1625},"used[i, t]",{"type":50,"tag":197,"props":1627,"children":1628},{},[1629,1631,1636,1637],{"type":56,"value":1630},"Usable (floor-truncated) integer output of item ",{"type":50,"tag":82,"props":1632,"children":1634},{"className":1633},[],[1635],{"type":56,"value":1594},{"type":56,"value":1596},{"type":50,"tag":82,"props":1638,"children":1640},{"className":1639},[],[1641],{"type":56,"value":1557},{"type":50,"tag":197,"props":1643,"children":1644},{},[1645],{"type":56,"value":1646},"Integer ≥ 0",{"type":50,"tag":197,"props":1648,"children":1649},{},[1650],{"type":50,"tag":82,"props":1651,"children":1653},{"className":1652},[],[1654],{"type":56,"value":1655},"addVariable(lb=0, vtype=INTEGER)",{"type":50,"tag":175,"props":1657,"children":1658},{},[1659,1668,1685,1689],{"type":50,"tag":197,"props":1660,"children":1661},{},[1662],{"type":50,"tag":82,"props":1663,"children":1665},{"className":1664},[],[1666],{"type":56,"value":1667},"buy[i, t]",{"type":50,"tag":197,"props":1669,"children":1670},{},[1671,1673,1678,1680],{"type":56,"value":1672},"Units of procured item ",{"type":50,"tag":82,"props":1674,"children":1676},{"className":1675},[],[1677],{"type":56,"value":1594},{"type":56,"value":1679}," purchased in period ",{"type":50,"tag":82,"props":1681,"children":1683},{"className":1682},[],[1684],{"type":56,"value":1557},{"type":50,"tag":197,"props":1686,"children":1687},{},[1688],{"type":56,"value":1562},{"type":50,"tag":197,"props":1690,"children":1691},{},[1692],{"type":50,"tag":82,"props":1693,"children":1695},{"className":1694},[],[1696],{"type":56,"value":1571},{"type":50,"tag":175,"props":1698,"children":1699},{},[1700,1709,1726,1730],{"type":50,"tag":197,"props":1701,"children":1702},{},[1703],{"type":50,"tag":82,"props":1704,"children":1706},{"className":1705},[],[1707],{"type":56,"value":1708},"inventory[i, t]",{"type":50,"tag":197,"props":1710,"children":1711},{},[1712,1714,1719,1721],{"type":56,"value":1713},"On-hand inventory of item ",{"type":50,"tag":82,"props":1715,"children":1717},{"className":1716},[],[1718],{"type":56,"value":1594},{"type":56,"value":1720}," at end of period ",{"type":50,"tag":82,"props":1722,"children":1724},{"className":1723},[],[1725],{"type":56,"value":1557},{"type":50,"tag":197,"props":1727,"children":1728},{},[1729],{"type":56,"value":1562},{"type":50,"tag":197,"props":1731,"children":1732},{},[1733],{"type":50,"tag":82,"props":1734,"children":1736},{"className":1735},[],[1737],{"type":56,"value":1571},{"type":50,"tag":175,"props":1739,"children":1740},{},[1741,1750,1755,1760],{"type":50,"tag":197,"props":1742,"children":1743},{},[1744],{"type":50,"tag":82,"props":1745,"children":1747},{"className":1746},[],[1748],{"type":56,"value":1749},"inventory[i, 0]",{"type":50,"tag":197,"props":1751,"children":1752},{},[1753],{"type":56,"value":1754},"Opening balance (fixed to zero)",{"type":50,"tag":197,"props":1756,"children":1757},{},[1758],{"type":56,"value":1759},"Continuous, lb=ub=0",{"type":50,"tag":197,"props":1761,"children":1762},{},[1763],{"type":50,"tag":82,"props":1764,"children":1766},{"className":1765},[],[1767],{"type":56,"value":1768},"addVariable(lb=0, ub=0, vtype=CONTINUOUS)",{"type":50,"tag":261,"props":1770,"children":1771},{},[1772,1777],{"type":50,"tag":82,"props":1773,"children":1775},{"className":1774},[],[1776],{"type":56,"value":1749},{"type":56,"value":1778}," is a fixed variable (lb = ub = 0). For a non-zero opening balance, set ub = lb = opening_balance.",{"type":50,"tag":59,"props":1780,"children":1782},{"id":1781},"constraint-map",[1783],{"type":56,"value":1784},"Constraint map",{"type":50,"tag":167,"props":1786,"children":1787},{},[1788,1814],{"type":50,"tag":171,"props":1789,"children":1790},{},[1791],{"type":50,"tag":175,"props":1792,"children":1793},{},[1794,1799,1804,1809],{"type":50,"tag":179,"props":1795,"children":1796},{},[1797],{"type":56,"value":1798},"Label",{"type":50,"tag":179,"props":1800,"children":1801},{},[1802],{"type":56,"value":1803},"Name pattern",{"type":50,"tag":179,"props":1805,"children":1806},{},[1807],{"type":56,"value":1808},"What it enforces",{"type":50,"tag":179,"props":1810,"children":1811},{},[1812],{"type":56,"value":1813},"Variables linked",{"type":50,"tag":190,"props":1815,"children":1816},{},[1817,1874,1917,1959,2016,2068,2111],{"type":50,"tag":175,"props":1818,"children":1819},{},[1820,1825,1834,1858],{"type":50,"tag":197,"props":1821,"children":1822},{},[1823],{"type":56,"value":1824},"C1",{"type":50,"tag":197,"props":1826,"children":1827},{},[1828],{"type":50,"tag":82,"props":1829,"children":1831},{"className":1830},[],[1832],{"type":56,"value":1833},"prod_def_{i}_{t}",{"type":50,"tag":197,"props":1835,"children":1836},{},[1837,1843,1845,1850,1852],{"type":50,"tag":82,"props":1838,"children":1840},{"className":1839},[],[1841],{"type":56,"value":1842},"produced[i,t]",{"type":56,"value":1844}," equals the sum of BOM-output quantities from all processes that ",{"type":50,"tag":74,"props":1846,"children":1847},{},[1848],{"type":56,"value":1849},"started",{"type":56,"value":1851}," at ",{"type":50,"tag":82,"props":1853,"children":1855},{"className":1854},[],[1856],{"type":56,"value":1857},"t − lead_time",{"type":50,"tag":197,"props":1859,"children":1860},{},[1861,1867,1868],{"type":50,"tag":82,"props":1862,"children":1864},{"className":1863},[],[1865],{"type":56,"value":1866},"produced",{"type":56,"value":137},{"type":50,"tag":82,"props":1869,"children":1871},{"className":1870},[],[1872],{"type":56,"value":1873},"x",{"type":50,"tag":175,"props":1875,"children":1876},{},[1877,1882,1891,1902],{"type":50,"tag":197,"props":1878,"children":1879},{},[1880],{"type":56,"value":1881},"C2a",{"type":50,"tag":197,"props":1883,"children":1884},{},[1885],{"type":50,"tag":82,"props":1886,"children":1888},{"className":1887},[],[1889],{"type":56,"value":1890},"trunc_upper_{i}_{t}",{"type":50,"tag":197,"props":1892,"children":1893},{},[1894,1900],{"type":50,"tag":82,"props":1895,"children":1897},{"className":1896},[],[1898],{"type":56,"value":1899},"used[i,t] ≤ produced[i,t]",{"type":56,"value":1901}," (integer cannot exceed real output)",{"type":50,"tag":197,"props":1903,"children":1904},{},[1905,1911,1912],{"type":50,"tag":82,"props":1906,"children":1908},{"className":1907},[],[1909],{"type":56,"value":1910},"used",{"type":56,"value":137},{"type":50,"tag":82,"props":1913,"children":1915},{"className":1914},[],[1916],{"type":56,"value":1866},{"type":50,"tag":175,"props":1918,"children":1919},{},[1920,1925,1934,1945],{"type":50,"tag":197,"props":1921,"children":1922},{},[1923],{"type":56,"value":1924},"C2b",{"type":50,"tag":197,"props":1926,"children":1927},{},[1928],{"type":50,"tag":82,"props":1929,"children":1931},{"className":1930},[],[1932],{"type":56,"value":1933},"trunc_lower_{i}_{t}",{"type":50,"tag":197,"props":1935,"children":1936},{},[1937,1943],{"type":50,"tag":82,"props":1938,"children":1940},{"className":1939},[],[1941],{"type":56,"value":1942},"used[i,t] ≥ produced[i,t] − (1 − ε)",{"type":56,"value":1944}," with ε = 1e-4 (forces integer to be the floor)",{"type":50,"tag":197,"props":1946,"children":1947},{},[1948,1953,1954],{"type":50,"tag":82,"props":1949,"children":1951},{"className":1950},[],[1952],{"type":56,"value":1910},{"type":56,"value":137},{"type":50,"tag":82,"props":1955,"children":1957},{"className":1956},[],[1958],{"type":56,"value":1866},{"type":50,"tag":175,"props":1960,"children":1961},{},[1962,1967,1976,1994],{"type":50,"tag":197,"props":1963,"children":1964},{},[1965],{"type":56,"value":1966},"C3a",{"type":50,"tag":197,"props":1968,"children":1969},{},[1970],{"type":50,"tag":82,"props":1971,"children":1973},{"className":1972},[],[1974],{"type":56,"value":1975},"bal_proc_{i}_{t}",{"type":50,"tag":197,"props":1977,"children":1978},{},[1979,1981,1986,1988],{"type":56,"value":1980},"Material balance for ",{"type":50,"tag":74,"props":1982,"children":1983},{},[1984],{"type":56,"value":1985},"procured",{"type":56,"value":1987}," items: ",{"type":50,"tag":82,"props":1989,"children":1991},{"className":1990},[],[1992],{"type":56,"value":1993},"inv[i,t] = inv[i,t−1] + buy[i,t] − consumption",{"type":50,"tag":197,"props":1995,"children":1996},{},[1997,2003,2004,2010,2011],{"type":50,"tag":82,"props":1998,"children":2000},{"className":1999},[],[2001],{"type":56,"value":2002},"inventory",{"type":56,"value":137},{"type":50,"tag":82,"props":2005,"children":2007},{"className":2006},[],[2008],{"type":56,"value":2009},"buy",{"type":56,"value":137},{"type":50,"tag":82,"props":2012,"children":2014},{"className":2013},[],[2015],{"type":56,"value":1873},{"type":50,"tag":175,"props":2017,"children":2018},{},[2019,2024,2033,2048],{"type":50,"tag":197,"props":2020,"children":2021},{},[2022],{"type":56,"value":2023},"C3b",{"type":50,"tag":197,"props":2025,"children":2026},{},[2027],{"type":50,"tag":82,"props":2028,"children":2030},{"className":2029},[],[2031],{"type":56,"value":2032},"bal_prod_{i}_{t}",{"type":50,"tag":197,"props":2034,"children":2035},{},[2036,2037,2041,2042],{"type":56,"value":1980},{"type":50,"tag":74,"props":2038,"children":2039},{},[2040],{"type":56,"value":1866},{"type":56,"value":1987},{"type":50,"tag":82,"props":2043,"children":2045},{"className":2044},[],[2046],{"type":56,"value":2047},"inv[i,t] = inv[i,t−1] + used[i,t] − consumption",{"type":50,"tag":197,"props":2049,"children":2050},{},[2051,2056,2057,2062,2063],{"type":50,"tag":82,"props":2052,"children":2054},{"className":2053},[],[2055],{"type":56,"value":2002},{"type":56,"value":137},{"type":50,"tag":82,"props":2058,"children":2060},{"className":2059},[],[2061],{"type":56,"value":1910},{"type":56,"value":137},{"type":50,"tag":82,"props":2064,"children":2066},{"className":2065},[],[2067],{"type":56,"value":1873},{"type":50,"tag":175,"props":2069,"children":2070},{},[2071,2076,2085,2103],{"type":50,"tag":197,"props":2072,"children":2073},{},[2074],{"type":56,"value":2075},"C4",{"type":50,"tag":197,"props":2077,"children":2078},{},[2079],{"type":50,"tag":82,"props":2080,"children":2082},{"className":2081},[],[2083],{"type":56,"value":2084},"supply_{i}_{t}",{"type":50,"tag":197,"props":2086,"children":2087},{},[2088,2094,2096,2101],{"type":50,"tag":82,"props":2089,"children":2091},{"className":2090},[],[2092],{"type":56,"value":2093},"buy[i,t] ≤ supply_qty[(i,t)]",{"type":56,"value":2095}," — only applied to procured items in ",{"type":50,"tag":74,"props":2097,"children":2098},{},[2099],{"type":56,"value":2100},"constrained",{"type":56,"value":2102}," families",{"type":50,"tag":197,"props":2104,"children":2105},{},[2106],{"type":50,"tag":82,"props":2107,"children":2109},{"className":2108},[],[2110],{"type":56,"value":2009},{"type":50,"tag":175,"props":2112,"children":2113},{},[2114,2119,2128,2147],{"type":50,"tag":197,"props":2115,"children":2116},{},[2117],{"type":56,"value":2118},"C5",{"type":50,"tag":197,"props":2120,"children":2121},{},[2122],{"type":50,"tag":82,"props":2123,"children":2125},{"className":2124},[],[2126],{"type":56,"value":2127},"cap_{r}_{t}",{"type":50,"tag":197,"props":2129,"children":2130},{},[2131,2137,2139,2145],{"type":50,"tag":82,"props":2132,"children":2134},{"className":2133},[],[2135],{"type":56,"value":2136},"Σ hours_per_unit[p] · x[p,r,t] ≤ capacity[(r,t)]",{"type":56,"value":2138}," — only processes where ",{"type":50,"tag":82,"props":2140,"children":2142},{"className":2141},[],[2143],{"type":56,"value":2144},"process_is_constrained[p]",{"type":56,"value":2146}," is True",{"type":50,"tag":197,"props":2148,"children":2149},{},[2150],{"type":50,"tag":82,"props":2151,"children":2153},{"className":2152},[],[2154],{"type":56,"value":1873},{"type":50,"tag":261,"props":2156,"children":2157},{},[2158,2163,2165,2171,2173,2179],{"type":50,"tag":74,"props":2159,"children":2160},{},[2161],{"type":56,"value":2162},"Lead-time note:",{"type":56,"value":2164}," C1 uses ",{"type":50,"tag":82,"props":2166,"children":2168},{"className":2167},[],[2169],{"type":56,"value":2170},"start_t = t − lead_time[p]",{"type":56,"value":2172},". If ",{"type":50,"tag":82,"props":2174,"children":2176},{"className":2175},[],[2177],{"type":56,"value":2178},"start_t \u003C 1",{"type":56,"value":2180},", the term is skipped (process cannot have started before period 1).",{"type":50,"tag":59,"props":2182,"children":2184},{"id":2183},"objective",[2185],{"type":56,"value":2186},"Objective",{"type":50,"tag":275,"props":2188,"children":2190},{"className":1304,"code":2189,"language":468,"meta":280,"style":280},"last_t = max(data.periods)\nobj = Σ  demand_weight[i] * inventory[i, last_t]   for i in final_items\n",[2191],{"type":50,"tag":82,"props":2192,"children":2193},{"__ignoreMap":280},[2194,2202],{"type":50,"tag":286,"props":2195,"children":2196},{"class":288,"line":289},[2197],{"type":50,"tag":286,"props":2198,"children":2199},{},[2200],{"type":56,"value":2201},"last_t = max(data.periods)\n",{"type":50,"tag":286,"props":2203,"children":2204},{"class":288,"line":412},[2205],{"type":50,"tag":286,"props":2206,"children":2207},{},[2208],{"type":56,"value":2209},"obj = Σ  demand_weight[i] * inventory[i, last_t]   for i in final_items\n",{"type":50,"tag":261,"props":2211,"children":2212},{},[2213,2215,2221,2223,2228,2230,2235,2237,2242],{"type":56,"value":2214},"Maximise the priority-weighted inventory of finished goods at the end of the planning horizon. ",{"type":50,"tag":82,"props":2216,"children":2218},{"className":2217},[],[2219],{"type":56,"value":2220},"demand_weight",{"type":56,"value":2222}," comes from the ",{"type":50,"tag":82,"props":2224,"children":2226},{"className":2225},[],[2227],{"type":56,"value":1120},{"type":56,"value":2229}," column in ",{"type":50,"tag":82,"props":2231,"children":2233},{"className":2232},[],[2234],{"type":56,"value":1093},{"type":56,"value":2236}," (the ",{"type":50,"tag":82,"props":2238,"children":2240},{"className":2239},[],[2241],{"type":56,"value":860},{"type":56,"value":2243}," column in demand.csv is present but not used by the base model).",{"type":50,"tag":59,"props":2245,"children":2247},{"id":2246},"solver-settings-default",[2248],{"type":56,"value":2249},"Solver settings (default)",{"type":50,"tag":275,"props":2251,"children":2253},{"className":1304,"code":2252,"language":468,"meta":280,"style":280},"settings = SolverSettings()\nsettings.set_parameter(\"mip_relative_gap\", 0.01)\nprob.solve(settings)\n",[2254],{"type":50,"tag":82,"props":2255,"children":2256},{"__ignoreMap":280},[2257,2265,2273],{"type":50,"tag":286,"props":2258,"children":2259},{"class":288,"line":289},[2260],{"type":50,"tag":286,"props":2261,"children":2262},{},[2263],{"type":56,"value":2264},"settings = SolverSettings()\n",{"type":50,"tag":286,"props":2266,"children":2267},{"class":288,"line":412},[2268],{"type":50,"tag":286,"props":2269,"children":2270},{},[2271],{"type":56,"value":2272},"settings.set_parameter(\"mip_relative_gap\", 0.01)\n",{"type":50,"tag":286,"props":2274,"children":2275},{"class":288,"line":1328},[2276],{"type":50,"tag":286,"props":2277,"children":2278},{},[2279],{"type":56,"value":2280},"prob.solve(settings)\n",{"type":50,"tag":261,"props":2282,"children":2283},{},[2284,2290,2292,2297],{"type":50,"tag":82,"props":2285,"children":2287},{"className":2286},[],[2288],{"type":56,"value":2289},"mip_relative_gap = 0.01",{"type":56,"value":2291}," (1% gap). ",{"type":50,"tag":74,"props":2293,"children":2294},{},[2295],{"type":56,"value":2296},"Do not change solver precision",{"type":56,"value":2298}," (e.g. do not tighten to 0.1% or 0.0); use this default only.",{"type":50,"tag":59,"props":2300,"children":2302},{"id":2301},"sanity-checking-results",[2303],{"type":56,"value":2304},"Sanity-checking results",{"type":50,"tag":261,"props":2306,"children":2307},{},[2308],{"type":56,"value":2309},"After solving, verify the model is correct:",{"type":50,"tag":361,"props":2311,"children":2312},{},[2313,2331,2349],{"type":50,"tag":70,"props":2314,"children":2315},{},[2316,2321,2323,2329],{"type":50,"tag":74,"props":2317,"children":2318},{},[2319],{"type":56,"value":2320},"Check model size changed",{"type":56,"value":2322}," when you add items\u002Fconstraints. The solver log prints ",{"type":50,"tag":82,"props":2324,"children":2326},{"className":2325},[],[2327],{"type":56,"value":2328},"Solving a problem with N constraints, M variables",{"type":56,"value":2330},". If you added a new item or constraint but N and M are unchanged, your data edits did not take effect — check that you edited the CSV files in the working directory.",{"type":50,"tag":70,"props":2332,"children":2333},{},[2334,2339,2341,2347],{"type":50,"tag":74,"props":2335,"children":2336},{},[2337],{"type":56,"value":2338},"Check item count",{"type":56,"value":2340}," in the ",{"type":50,"tag":82,"props":2342,"children":2344},{"className":2343},[],[2345],{"type":56,"value":2346},"Loading data...",{"type":56,"value":2348}," output matches your expectation (e.g., adding RM4 should increase the item count by 1).",{"type":50,"tag":70,"props":2350,"children":2351},{},[2352,2357],{"type":50,"tag":74,"props":2353,"children":2354},{},[2355],{"type":56,"value":2356},"Check objective value",{"type":56,"value":2358}," actually changed meaningfully. Differences smaller than the MIP gap (~1%) may just be solver noise, not real model changes.",{"type":50,"tag":59,"props":2360,"children":2362},{"id":2361},"quick-links-by-task",[2363],{"type":56,"value":2364},"Quick links by task",{"type":50,"tag":167,"props":2366,"children":2367},{},[2368,2384],{"type":50,"tag":171,"props":2369,"children":2370},{},[2371],{"type":50,"tag":175,"props":2372,"children":2373},{},[2374,2379],{"type":50,"tag":179,"props":2375,"children":2376},{},[2377],{"type":56,"value":2378},"Task",{"type":50,"tag":179,"props":2380,"children":2381},{},[2382],{"type":56,"value":2383},"Use",{"type":50,"tag":190,"props":2385,"children":2386},{},[2387,2400,2413,2432],{"type":50,"tag":175,"props":2388,"children":2389},{},[2390,2395],{"type":50,"tag":197,"props":2391,"children":2392},{},[2393],{"type":56,"value":2394},"Implement or extend the base model",{"type":50,"tag":197,"props":2396,"children":2397},{},[2398],{"type":56,"value":2399},"Data file map, key sets, variable reference, constraint map, objective.",{"type":50,"tag":175,"props":2401,"children":2402},{},[2403,2408],{"type":50,"tag":197,"props":2404,"children":2405},{},[2406],{"type":56,"value":2407},"Load or modify input data",{"type":50,"tag":197,"props":2409,"children":2410},{},[2411],{"type":56,"value":2412},"Data file map; optional files read separately.",{"type":50,"tag":175,"props":2414,"children":2415},{},[2416,2421],{"type":50,"tag":197,"props":2417,"children":2418},{},[2419],{"type":56,"value":2420},"Tune or run the solver",{"type":50,"tag":197,"props":2422,"children":2423},{},[2424,2426,2430],{"type":56,"value":2425},"Solver settings (default); data in ",{"type":50,"tag":74,"props":2427,"children":2428},{},[2429],{"type":56,"value":149},{"type":56,"value":2431}," by default.",{"type":50,"tag":175,"props":2433,"children":2434},{},[2435,2440],{"type":50,"tag":197,"props":2436,"children":2437},{},[2438],{"type":56,"value":2439},"Verify results after changes",{"type":50,"tag":197,"props":2441,"children":2442},{},[2443],{"type":56,"value":2444},"Sanity-checking results.",{"type":50,"tag":2446,"props":2447,"children":2448},"style",{},[2449],{"type":56,"value":2450},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":2452,"total":1373},[2453,2468,2478,2493,2500,2515,2530],{"slug":2454,"name":2454,"fn":2455,"description":2456,"org":2457,"tags":2458,"stars":23,"repoUrl":24,"updatedAt":2467},"cuopt-debugging","debug NVIDIA cuOpt optimization problems","Troubleshoot cuOpt LP\u002FMILP problems including errors, wrong results, infeasible solutions, performance issues, and status codes. Use when the user says something isn't working, gets unexpected results, or needs help diagnosing issues.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2459,2462,2465,2466],{"name":2460,"slug":2461,"type":15},"Debugging","debugging",{"name":2463,"slug":2464,"type":15},"Mathematics","mathematics",{"name":9,"slug":8,"type":15},{"name":17,"slug":18,"type":15},"2026-07-23T05:43:32.51428",{"slug":2469,"name":2469,"fn":2470,"description":2471,"org":2472,"tags":2473,"stars":23,"repoUrl":24,"updatedAt":2477},"cuopt-model-mapper","map optimization problems to cuOpt models","Map interpreted optimization problems into cuOpt-native models for the fast path with minimal clarifying questions.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2474,2475,2476],{"name":20,"slug":21,"type":15},{"name":9,"slug":8,"type":15},{"name":17,"slug":18,"type":15},"2026-07-30T05:29:19.401656",{"slug":2479,"name":2479,"fn":2480,"description":2481,"org":2482,"tags":2483,"stars":23,"repoUrl":24,"updatedAt":2492},"cuopt-sandbox","run cuOpt optimization in NemoClaw sandbox","Run cuOpt in the NemoClaw sandbox — probe\u002Fsmoke gates, prefer cancelable Python gRPC jobs, use legacy remote execution only when that API is unavailable, then vendored cuOpt skills.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2484,2487,2488,2489],{"name":2485,"slug":2486,"type":15},"CLI","cli",{"name":9,"slug":8,"type":15},{"name":17,"slug":18,"type":15},{"name":2490,"slug":2491,"type":15},"Simulation","simulation","2026-07-30T05:29:17.131364",{"slug":4,"name":4,"fn":5,"description":6,"org":2494,"tags":2495,"stars":23,"repoUrl":24,"updatedAt":25},{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2496,2497,2498,2499],{"name":20,"slug":21,"type":15},{"name":9,"slug":8,"type":15},{"name":17,"slug":18,"type":15},{"name":13,"slug":14,"type":15},{"slug":2501,"name":2501,"fn":2502,"description":2503,"org":2504,"tags":2505,"stars":23,"repoUrl":24,"updatedAt":2514},"optimization-from-data-orchestrator","orchestrate optimization data and solving","Coordinate uploaded data plus a natural-language question into interpretation, clarification, cuOpt solve, and a user-facing answer.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2506,2509,2512,2513],{"name":2507,"slug":2508,"type":15},"Automation","automation",{"name":2510,"slug":2511,"type":15},"Data Engineering","data-engineering",{"name":9,"slug":8,"type":15},{"name":17,"slug":18,"type":15},"2026-07-14T05:32:59.680482",{"slug":2516,"name":2516,"fn":2517,"description":2518,"org":2519,"tags":2520,"stars":23,"repoUrl":24,"updatedAt":2529},"optimization-intent-router","classify optimization and analytics requests","Classify whether a data-backed request is LP, MILP, QP, routing, or non-optimization analytics.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2521,2524,2527,2528],{"name":2522,"slug":2523,"type":15},"Analytics","analytics",{"name":2525,"slug":2526,"type":15},"Data Analysis","data-analysis",{"name":9,"slug":8,"type":15},{"name":17,"slug":18,"type":15},"2026-07-14T05:32:53.475243",{"slug":2531,"name":2531,"fn":2532,"description":2533,"org":2534,"tags":2535,"stars":23,"repoUrl":24,"updatedAt":2539},"optimization-mode-router","route optimization requests to cuOpt solvers","Choose fast direct-to-cuOpt solve versus replayable or auditable model artifact mode.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2536,2537,2538],{"name":2507,"slug":2508,"type":15},{"name":9,"slug":8,"type":15},{"name":17,"slug":18,"type":15},"2026-07-30T05:29:18.162351",{"items":2541,"total":2695},[2542,2560,2577,2588,2600,2612,2625,2639,2652,2663,2677,2686],{"slug":2543,"name":2543,"fn":2544,"description":2545,"org":2546,"tags":2547,"stars":2557,"repoUrl":2558,"updatedAt":2559},"nemoclaw-user-guide","retrieve NemoClaw documentation and configuration","Guides human users' AI agents to the NemoClaw docs MCP server and canonical Fern documentation in Markdown form. Use when users ask how to install, configure, operate, troubleshoot, secure, or learn NemoClaw with an AI coding assistant. Trigger keywords - nemoclaw docs, use nemoclaw with ai agent, nemoclaw mcp docs, nemoclaw install help, nemoclaw quickstart, nemoclaw markdown docs, llms.txt, agent skills.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2548,2551,2554],{"name":2549,"slug":2550,"type":15},"Documentation","documentation",{"name":2552,"slug":2553,"type":15},"MCP","mcp",{"name":2555,"slug":2556,"type":15},"Search","search",21777,"https:\u002F\u002Fgithub.com\u002FNVIDIA\u002FNemoClaw","2026-07-20T06:00:01.461044",{"slug":2561,"name":2561,"fn":2562,"description":2563,"org":2564,"tags":2565,"stars":2574,"repoUrl":2575,"updatedAt":2576},"mcore-build-and-dependency","manage Megatron-LM development environments","Container-based dev environment setup and dependency management for Megatron-LM. Covers acquiring and launching the CI container, uv package management, and updating uv.lock.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2566,2569,2572],{"name":2567,"slug":2568,"type":15},"Containers","containers",{"name":2570,"slug":2571,"type":15},"Deployment","deployment",{"name":2573,"slug":468,"type":15},"Python",17049,"https:\u002F\u002Fgithub.com\u002FNVIDIA\u002FMegatron-LM","2026-07-27T06:06:11.249662",{"slug":2578,"name":2578,"fn":2579,"description":2580,"org":2581,"tags":2582,"stars":2574,"repoUrl":2575,"updatedAt":2587},"mcore-bump-base-image","update NVIDIA PyTorch base images","Bump the NVIDIA PyTorch base image (`nvcr.io\u002Fnvidia\u002Fpytorch:YY.MM-py3`) used by Megatron-LM CI. Covers the two pin sites (GitHub CI in `docker\u002F.ngc_version.dev` and GitLab CI in `.gitlab\u002Fstages\u002F01.build.yml`), the post-bump CI loop (re-run functional tests, refresh golden values, mark broken tests), and the gotchas that bit PRs",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2583,2586],{"name":2584,"slug":2585,"type":15},"CI\u002FCD","ci-cd",{"name":2570,"slug":2571,"type":15},"2026-07-14T05:25:59.97109",{"slug":2589,"name":2589,"fn":2590,"description":2591,"org":2592,"tags":2593,"stars":2574,"repoUrl":2575,"updatedAt":2599},"mcore-cicd","manage CI\u002FCD pipelines for Megatron-LM","CI\u002FCD reference for Megatron-LM. Covers CI pipeline structure, PR scope labels, triggering internal GitLab CI (which force-pushes the current branch to a pull-request\u002FBRANCH ref — always dry-run and verify the destination first; never run against shared or protected branches), and CI failure investigation.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2594,2595,2596],{"name":2584,"slug":2585,"type":15},{"name":2570,"slug":2571,"type":15},{"name":2597,"slug":2598,"type":15},"GitHub","github","2026-07-27T06:06:12.278222",{"slug":2601,"name":2601,"fn":2602,"description":2603,"org":2604,"tags":2605,"stars":2574,"repoUrl":2575,"updatedAt":2611},"mcore-create-issue","investigate CI failures and create issues","Investigate a failing GitHub Actions run or job and create a GitHub issue for the failure.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2606,2607,2608],{"name":2460,"slug":2461,"type":15},{"name":2597,"slug":2598,"type":15},{"name":2609,"slug":2610,"type":15},"Triage","triage","2026-07-14T05:25:57.442089",{"slug":2613,"name":2613,"fn":2614,"description":2615,"org":2616,"tags":2617,"stars":2574,"repoUrl":2575,"updatedAt":2624},"mcore-linting-and-formatting","lint and format Megatron-LM code","Linting and formatting for Megatron-LM. Covers running autoformat.sh, tools (ruff, black, isort, pylint, mypy), and code style rules.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2618,2621],{"name":2619,"slug":2620,"type":15},"Best Practices","best-practices",{"name":2622,"slug":2623,"type":15},"Code Analysis","code-analysis","2026-07-14T05:25:56.18433",{"slug":2626,"name":2626,"fn":2627,"description":2628,"org":2629,"tags":2630,"stars":2574,"repoUrl":2575,"updatedAt":2638},"mcore-migrate-gpt-to-hybrid","migrate Megatron-LM models to HybridModel","Migration guide for moving Megatron Core GPTModel checkpoints, model providers, training commands, and layer mappings to HybridModel.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2631,2634,2637],{"name":2632,"slug":2633,"type":15},"Machine Learning","machine-learning",{"name":2635,"slug":2636,"type":15},"Migration","migration",{"name":9,"slug":8,"type":15},"2026-07-17T06:07:11.777011",{"slug":2640,"name":2640,"fn":2641,"description":2642,"org":2643,"tags":2644,"stars":2574,"repoUrl":2575,"updatedAt":2651},"mcore-onboard-gb200-1node-tests","onboard functional tests for GB200","Onboard 1-node GitHub MR functional tests for GB200 from existing mr-scoped 2-node tests.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2645,2648],{"name":2646,"slug":2647,"type":15},"QA","qa",{"name":2649,"slug":2650,"type":15},"Testing","testing","2026-07-14T05:25:53.673039",{"slug":2653,"name":2653,"fn":2654,"description":2655,"org":2656,"tags":2657,"stars":2574,"repoUrl":2575,"updatedAt":2662},"mcore-run-on-slurm","launch distributed training jobs on SLURM","How to launch distributed Megatron-LM training jobs on a SLURM cluster. Covers a minimal sbatch skeleton, environment-variable setup for torch.distributed.run, CUDA_DEVICE_MAX_CONNECTIONS rules across hardware and parallelism modes, container conventions, monitoring, and per-rank failure diagnosis.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2658,2659],{"name":2570,"slug":2571,"type":15},{"name":2660,"slug":2661,"type":15},"Infrastructure","infrastructure","2026-07-14T05:25:49.362534",{"slug":2664,"name":2664,"fn":2665,"description":2666,"org":2667,"tags":2668,"stars":2574,"repoUrl":2575,"updatedAt":2676},"mcore-split-pr","split pull requests to reduce review load","Split a PR into multiple PRs to reduce the number of required CODEOWNERS reviewer groups.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2669,2672,2673],{"name":2670,"slug":2671,"type":15},"Code Review","code-review",{"name":2597,"slug":2598,"type":15},{"name":2674,"slug":2675,"type":15},"Pull Requests","pull-requests","2026-07-14T05:26:01.226578",{"slug":2678,"name":2678,"fn":2679,"description":2680,"org":2681,"tags":2682,"stars":2574,"repoUrl":2575,"updatedAt":2685},"mcore-testing","run and manage Megatron-LM tests","Test system for Megatron-LM. Covers test layout, recipe YAML structure, adding and running unit and functional tests, golden values, marker filters, and CI parity.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2683,2684],{"name":2646,"slug":2647,"type":15},{"name":2649,"slug":2650,"type":15},"2026-07-14T05:25:54.928983",{"slug":2687,"name":2687,"fn":2688,"description":2689,"org":2690,"tags":2691,"stars":2574,"repoUrl":2575,"updatedAt":2694},"nightly-sync","manage nightly main-to-dev sync workflows","Domain knowledge for the nightly main-to-dev sync workflow. Covers merge strategy, CI architecture, failure investigation, and known issues.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2692,2693],{"name":2507,"slug":2508,"type":15},{"name":2584,"slug":2585,"type":15},"2026-07-30T05:29:03.275638",496]