Skip to content

Commit 7d42744

Browse files
committed
Add example fpr callback to notebook
1 parent ada8323 commit 7d42744

1 file changed

Lines changed: 78 additions & 0 deletions

File tree

docs/notebooks/04-operational-constraints.ipynb

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,84 @@
417417
"cell_type": "markdown",
418418
"id": "28",
419419
"metadata": {},
420+
"source": [
421+
"## Custom Constraints\n",
422+
"\n",
423+
"Sometimes you need constraints beyond what's built into the components. The `before_solve` callback lets you add custom constraints directly to the optimization model.\n",
424+
"\n",
425+
"### Example: Limit Main Boiler Startups\n",
426+
"\n",
427+
"Let's limit the main boiler to a maximum of 3 startups:"
428+
]
429+
},
430+
{
431+
"cell_type": "code",
432+
"execution_count": null,
433+
"id": "29",
434+
"metadata": {},
435+
"outputs": [],
436+
"source": [
437+
"# Build a fresh system with status tracking on both boilers\n",
438+
"fs_custom = flow_system.copy()\n",
439+
"fs_custom.reset()\n",
440+
"\n",
441+
"\n",
442+
"def limit_main_boiler_startups(fs):\n",
443+
" \"\"\"Custom constraint: Main boiler can start at most 3 times.\"\"\"\n",
444+
" model = fs.model\n",
445+
" main_startups = model.variables['MainBoiler|startup']\n",
446+
" model.add_constraints(main_startups.sum() <= 3, name='max_main_startups')\n",
447+
"\n",
448+
"\n",
449+
"fs_custom.optimize(fx.solvers.HighsSolver(mip_gap=0.01), before_solve=limit_main_boiler_startups);"
450+
]
451+
},
452+
{
453+
"cell_type": "code",
454+
"execution_count": null,
455+
"id": "30",
456+
"metadata": {},
457+
"outputs": [],
458+
"source": [
459+
"# Verify: Main boiler startups are limited\n",
460+
"main_startups = int(fs_custom.solution['MainBoiler|startup'].sum().item())\n",
461+
"print(f'MainBoiler startups: {main_startups} (limit: 3)')\n",
462+
"\n",
463+
"# Compare with unconstrained (which had more startups)\n",
464+
"print(f'Original system startups: {total_startups}')\n",
465+
"\n",
466+
"# Show startup events\n",
467+
"startup_ds = xr.Dataset({'MainBoiler startup': fs_custom.solution['MainBoiler|startup']})\n",
468+
"startup_ds.plotly.line(x='time', title='Main Boiler Startup Events', height=250)"
469+
]
470+
},
471+
{
472+
"cell_type": "markdown",
473+
"id": "31",
474+
"metadata": {},
475+
"source": [
476+
"### Finding Available Variables\n",
477+
"\n",
478+
"To discover what variables you can use in custom constraints, inspect the model after building:"
479+
]
480+
},
481+
{
482+
"cell_type": "code",
483+
"execution_count": null,
484+
"id": "32",
485+
"metadata": {},
486+
"outputs": [],
487+
"source": [
488+
"# List all variables in the model\n",
489+
"print('Available variables:')\n",
490+
"for name in fs_custom.model.variables:\n",
491+
" print(f' {name}')"
492+
]
493+
},
494+
{
495+
"cell_type": "markdown",
496+
"id": "33",
497+
"metadata": {},
420498
"source": [
421499
"## Key Concepts\n",
422500
"\n",

0 commit comments

Comments
 (0)