{
"cells": [
{
"cell_type": "markdown",
"id": "97191ca7",
"metadata": {},
"source": [
"# PULPO Optimization Framework: Complete Demonstration\n",
"\n",
"This notebook provides a comprehensive demonstration of PULPO's capabilities for sustainable technology optimization, covering basic single-objective optimization through advanced uncertainty analysis and multi-objective trade-off exploration."
]
},
{
"cell_type": "markdown",
"id": "fc21234c",
"metadata": {},
"source": [
"## 1. System Description\n",
"\n",
"The demonstration system models interconnected background and foreground processes for low-carbon methanol production:\n",
"\n",
"**Background System** supplies conventional commodities:\n",
"- Natural gas extraction and electricity generation\n",
"- Wind electricity generation \n",
"- Water supply\n",
"- Hydrogen production via steam methane reforming (SMR)\n",
"- Oxygen production via air separation unit (ASU)\n",
"\n",
"**Foreground System** represents novel technologies:\n",
"- Hydrogen electrolysis (producing H₂ and O₂ as byproduct)\n",
"- Direct air capture (DAC) for CO₂ supply\n",
"- Methanol synthesis using captured CO₂ and H₂\n",
"- Ozone production consuming oxygen\n",
"\n",
"**Multifunctional Links**: The O₂-byproduct and O₂-market activities balance oxygen flows between electrolysis byproduct recovery and conventional supply, ensuring proper system allocation.\n",
"\n",
"**Environmental Flows**: The system tracks emissions of CO₂, CH₄, particulate matter (PM), and water use to the biosphere.\n",
"\n",
"This represents an integrated Power-to-Methanol pathway with linked energy and material exchanges between renewable and fossil-based subsystems.\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"id": "76511589",
"metadata": {},
"source": [
"### 1.1 Technology Choices and System Interdependencies\n",
"\n",
"The system incorporates several critical technological choices that determine environmental performance:\n",
"\n",
"**Energy Supply Alternatives:**\n",
"- Electricity generation: Natural gas combined-cycle (NGCC) vs. wind power\n",
"- Represents background system choices reflecting alternative energy mixes\n",
"\n",
"**Hydrogen Production Pathways:**\n",
"- Steam methane reforming (SMR) in background system\n",
"- Water electrolysis in foreground system \n",
"- Demonstrates foreground-background substitution dynamics\n",
"\n",
"**Oxygen Supply Options:**\n",
"- Conventional production via air separation unit (ASU) in background\n",
"- Recovery as electrolysis byproduct in foreground\n",
"- Market-based supply balancing both sources\n",
"\n",
"The O₂-market activity ensures that multiple oxygen sources can coexist or compete depending on system boundaries and optimization objectives."
]
},
{
"cell_type": "markdown",
"id": "c90925a2",
"metadata": {},
"source": [
"### 1.2 Technosphere Matrix (A)\n",
"\n",
"The technosphere matrix represents product flows between processes. Positive values indicate outputs, negative values indicate inputs.\n",
"\n",
"
\n",
"\n",
"\n",
"Product ↓ \\\\ Process → \n",
"NG extraction \n",
"NG electricity \n",
"Wind electricity \n",
"Water supply \n",
"H₂ SMR \n",
"O₂ ASU \n",
"H₂ electrolysis \n",
"O₂-byproduct \n",
"O₂-market \n",
"DAC plant \n",
"Methanol synthesis \n",
"Ozone production \n",
" \n",
" \n",
"\n",
"\n",
"Natural gas [kg] \n",
"+1 \n",
"−0.19 \n",
"0 \n",
"0 \n",
"−3.2 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"\n",
"Electricity, NG [kWh] \n",
"0 \n",
"+1 \n",
"0 \n",
"−0.49 \n",
"−0.10 \n",
"−0.22 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"−1.2 \n",
"0 \n",
"\n",
"Electricity, wind [kWh] \n",
"0 \n",
"0 \n",
"+1 \n",
"0 \n",
"0 \n",
"0 \n",
"−50.0 \n",
"0 \n",
"0 \n",
"−1.5 \n",
"0 \n",
"−0.5 \n",
"\n",
"Water [m³] \n",
"0 \n",
"0 \n",
"0 \n",
"+1 \n",
"−0.003 \n",
"0 \n",
"−0.009 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"\n",
"Hydrogen (SMR) [kg] \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"+1 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"\n",
"Oxygen (ASU) [kg] \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"+1 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"−1.0 \n",
"\n",
"Hydrogen (electrolysis) [kg] \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"+1 \n",
"0 \n",
"0 \n",
"0 \n",
"−0.19 \n",
"0 \n",
"\n",
"Oxygen (byproduct) [kg] \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"+8.0 \n",
"-1 \n",
"−1 \n",
"0 \n",
"0 \n",
"0 \n",
"\n",
"Oxygen (market) [kg] \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"+1 \n",
"0 \n",
"0 \n",
"0 \n",
"\n",
"CO₂, captured [kg] \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"+1 \n",
"−1.375 \n",
"0 \n",
"\n",
"Methanol [kg] \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"+1 \n",
"0 \n",
"\n",
"Ozone [kg] \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"+1 \n",
"\n",
" \n",
"
\n"
]
},
{
"cell_type": "markdown",
"id": "3ee2be9f",
"metadata": {},
"source": [
"### 1.3 Biosphere Matrix (B)\n",
"\n",
"The biosphere matrix represents environmental flows from processes to the environment. All values represent emissions or resource consumption.\n",
"\n",
"\n",
"\n",
"\n",
"Flow ↓ ---- \\\\ ---- Process → \n",
"NG extraction \n",
"NG electricity \n",
"Wind electricity \n",
"Water supply \n",
"H₂ SMR \n",
"O₂ ASU \n",
"H₂ electrolysis \n",
"O₂-byproduct \n",
"O₂-market \n",
"DAC plant \n",
"Methanol synthesis \n",
"Ozone production \n",
" \n",
" \n",
"\n",
"\n",
"CO₂ emission [kg] \n",
"+0.0 \n",
"+0.44 \n",
"+0.012 \n",
"0 \n",
"+9.0 \n",
"0 \n",
"+0.1 \n",
"0 \n",
"0 \n",
"−1.0 \n",
"+0.2 \n",
"0 \n",
"\n",
"CH₄ emission [kg] \n",
"+0.0074 \n",
"+0.0000028 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"\n",
"PM emission [g] \n",
"0 \n",
"+0.015 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"+0.001 \n",
"+0.002 \n",
"\n",
"Water use [m³] \n",
"0 \n",
"+0.0018 \n",
"0 \n",
"+1.0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"0 \n",
"\n",
" \n",
"
\n"
]
},
{
"cell_type": "markdown",
"id": "be3d3d52",
"metadata": {},
"source": [
"## 2. Implementation: Basic Setup\n",
"\n",
"### 2.1 Database Initialization\n",
"\n",
"Initialize the sample database containing all processes and flows described in the system matrices. This creates both background and foreground databases with the complete methanol production system."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "49c29fef",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"biosphere3 created with 4 flows.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"technosphere database created with 5 activities.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"background_db created with 6 activities and uncertainty added to exchanges.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"foreground_db created with 6 activities and uncertainty added to exchanges.\n",
"Registered 3 LCIA methods.\n"
]
}
],
"source": [
"from pulpo import pulpo\n",
"pulpo.setup_sample_db()"
]
},
{
"cell_type": "markdown",
"id": "f53b0cf5",
"metadata": {},
"source": [
"### 2.2 Library Import\n",
"\n",
"Import required libraries for optimization analysis and data manipulation."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "c459cca2",
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"import numpy as np\n",
"import pandas as pd\n",
"import copy"
]
},
{
"cell_type": "markdown",
"id": "a882d243",
"metadata": {},
"source": [
"### 2.3 PULPO Configuration\n",
"\n",
"Configure the PULPO optimizer with:\n",
"- **Project name**: Identifier for optimization project\n",
"- **Databases**: Background (conventional) and foreground (novel) systems\n",
"- **Methods**: Impact assessment categories with relative weights\n",
" - Climate change: weight = 1 (primary objective)\n",
" - Resources: weight = 0 (inactive initially)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "a2f93f81",
"metadata": {},
"outputs": [],
"source": [
"from pulpo.utils.utils import is_bw25\n",
"\n",
"project = \"sample_project_bw25\" if is_bw25() else \"sample_project\"\n",
"database = [\"background_db\", \"foreground_db\"]\n",
"method = {\"('my project', 'climate change')\": 1,\n",
" \"('my project', 'resources')\": 0,}"
]
},
{
"cell_type": "markdown",
"id": "01d89a3f",
"metadata": {},
"source": [
"### 2.4 Optimizer Initialization\n",
"\n",
"Create the PULPO optimizer instance."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "726f2139",
"metadata": {},
"outputs": [],
"source": [
"pulpo_worker = pulpo.PulpoOptimizer(project, database, method)"
]
},
{
"cell_type": "markdown",
"id": "f11a6898",
"metadata": {},
"source": [
"> **⚠️ Attention:** \n",
"> PULPO assumes that the biosphere in your project is named **`biosphere3`**. \n",
"> If your project uses a different biosphere name, make sure to explicitly provide it to your PULPO worker. \n",
"> \n",
"> For example:\n",
"\n",
"```python\n",
"pulpo_worker.intervention_matrix = \"ecoinvent-3.10-biosphere\"\n",
"```\n"
]
},
{
"cell_type": "markdown",
"id": "bde304d9",
"metadata": {},
"source": [
"### 2.5 Life Cycle Inventory Data Loading\n",
"\n",
"Load technosphere matrix (A), biosphere matrix (B), and process/intervention mappings. This creates the mathematical foundation for optimization by establishing the linear system: **Ax = f** and **environmental impacts = Bx**."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "82d48799",
"metadata": {},
"outputs": [],
"source": [
"pulpo_worker.get_lci_data()"
]
},
{
"cell_type": "markdown",
"id": "3fcb751c",
"metadata": {},
"source": [
"## 3. Single-Objective Optimization Examples\n",
"\n",
"### 3.1 Functional Unit Definition\n",
"\n",
"The functional unit defines the reference output for environmental impact assessment. We begin with 1 kg methanol as the primary product demand."
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "2acfad63",
"metadata": {},
"outputs": [],
"source": [
"methanol_process = pulpo_worker.retrieve_processes(reference_products='methanol')\n",
"\n",
"demand = {methanol_process[0]: 1}"
]
},
{
"cell_type": "markdown",
"id": "17b70c81",
"metadata": {},
"source": [
"### 3.2 Technology Choice Definition\n",
"\n",
"Define alternative technologies for key system components:\n",
"\n",
"**Electricity Generation:**\n",
"- Wind electricity (renewable)\n",
"- Natural gas electricity (fossil-based)\n",
"\n",
"**Hydrogen Production:**\n",
"- Steam methane reforming (SMR) - conventional background process\n",
"- Water electrolysis - novel foreground process\n",
"\n",
"**Oxygen Supply:**\n",
"- Air separation unit (ASU) - conventional production\n",
"- Market supply - generic oxygen source\n",
"- Electrolysis byproduct - recovered from hydrogen production\n",
"\n",
"These alternatives represent the core technological decisions determining system environmental performance."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "41d95cfd",
"metadata": {},
"outputs": [],
"source": [
"## Electricity Choice\n",
"electricity_technologies = [\"wind electricity\",\n",
" \"natural gas electricity\",]\n",
"electricity_processes = pulpo_worker.retrieve_processes(processes=electricity_technologies)\n",
"\n",
"## Hydrogen Choice\n",
"hydrogen_technologies = [\"hydrogen SMR\",\n",
" \"hydrogen electrolysis\",]\n",
"hydrogen_processes = pulpo_worker.retrieve_processes(processes=hydrogen_technologies)\n",
"\n",
"## Oxygen Choice\n",
"oxygen_technologies = [\"O2-market\",\n",
" \"O2 ASU\",]\n",
"oxygen_processes = pulpo_worker.retrieve_processes(processes=oxygen_technologies)\n",
"\n",
"### Oxygen byproduct\n",
"oxygen_aux = \"O2-byproduct\"\n",
"oxygen_byproduct = pulpo_worker.retrieve_processes(processes=[oxygen_aux])\n"
]
},
{
"cell_type": "markdown",
"id": "3ba9003f",
"metadata": {},
"source": [
"### 3.3 Choices Dictionary Configuration\n",
"\n",
"Organize technology alternatives into an optimization-ready structure. Each choice category contains multiple alternatives with capacity constraints.\n",
"\n",
"> **⚠️ Attention:** \n",
"> A capacity of `float('inf')` means *no limit*: the solver is not restricted by it. \n",
"> Give an alternative a finite capacity only where it has a real limit. A huge finite number such as `1e10` adds \n",
"> nothing and can degrade the solver's numerics; leave it infinite instead.\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "8aafd1fa",
"metadata": {},
"outputs": [],
"source": [
"## Choices\n",
"choices = {\n",
" \"Electricity\": {electricity_processes[0]: float('inf'),\n",
" electricity_processes[1]: float('inf')},\n",
" \"Hydrogen\": {hydrogen_processes[0]: float('inf'),\n",
" hydrogen_processes[1]: float('inf')},\n",
" \"Oxygen\": {oxygen_processes[0]: float('inf'), \n",
" oxygen_processes[1]: float('inf'),},\n",
"}"
]
},
{
"cell_type": "markdown",
"id": "eb884274",
"metadata": {},
"source": [
"### 3.4 Lower Bound Constraints\n",
"\n",
"Configure process flow constraints. The O₂-byproduct process requires non-negative flow (≥ 0) to ensure physically meaningful byproduct recovery from electrolysis."
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "7561033e",
"metadata": {},
"outputs": [],
"source": [
"# Lower bound\n",
"lower_bound = {oxygen_byproduct[0]: 0}"
]
},
{
"cell_type": "markdown",
"id": "cd77d1a9",
"metadata": {},
"source": [
"> **⚠️ Attention:** \n",
"> With this configuration, the O₂ by-product is **allowed to be vented** (e.g., to a market or directly to the environment).\n",
"> If you want to **force the system to internally utilize the by-product**, you must also specify an **upper bound of `0`**, which prevents any venting and requires full integration within the production system.\n"
]
},
{
"cell_type": "markdown",
"id": "9eb88b82",
"metadata": {},
"source": [
"### 3.5 First Optimization: Single Product\n",
"\n",
"Solve optimization with 1 kg methanol demand. PULPO identifies the technology combination minimizing climate change impact while satisfying demand constraints."
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "ba7220d7",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Creating Instance\n",
"Instance created\n",
"optimal solution found: 1.7471600582975855\n",
"Optimization problem solved using Highspy\n"
]
}
],
"source": [
"pulpo_worker.instantiate(choices=choices, demand=demand, lower_limit=lower_bound)\n",
"results = pulpo_worker.solve()"
]
},
{
"cell_type": "markdown",
"id": "3b1eab67",
"metadata": {},
"source": [
"#### Results Analysis: Technology Selection\n",
"\n",
"The optimization results show selected technologies and resource utilization. Observe which electricity and hydrogen sources were chosen to minimize climate impact."
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "850a6f86",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"## Total Impact(s)"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Weight \n",
" Value \n",
" \n",
" \n",
" Method \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" ('my project', 'climate change') \n",
" 1 \n",
" 1.74716 \n",
" \n",
" \n",
" ('my project', 'resources') \n",
" 0 \n",
" 0.00171 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Weight Value\n",
"Method \n",
"('my project', 'climate change') 1 1.74716\n",
"('my project', 'resources') 0 0.00171"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"## Choices Made"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Electricity"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Value \n",
" Capacity \n",
" \n",
" \n",
" Metadata \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" wind electricity | electricity | GLO \n",
" 12.763338 \n",
" inf \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Value Capacity\n",
"Metadata \n",
"wind electricity | electricity | GLO 12.763338 inf"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Hydrogen"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Value \n",
" Capacity \n",
" \n",
" \n",
" Metadata \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" hydrogen electrolysis | hydrogen | GLO \n",
" 0.19 \n",
" inf \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Value Capacity\n",
"Metadata \n",
"hydrogen electrolysis | hydrogen | GLO 0.19 inf"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Oxygen"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Value \n",
" Capacity \n",
" \n",
" \n",
" Metadata \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
"Empty DataFrame\n",
"Columns: [Value, Capacity]\n",
"Index: []"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"## Constraints"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Constraints Lower"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Key \n",
" Metadata \n",
" Value \n",
" Limit \n",
" \n",
" \n",
" ID \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" 7 \n",
" (foreground_db, O2-byproduct) \n",
" O2-byproduct | oxygen | GLO \n",
" 1.52 \n",
" 0 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Key Metadata Value Limit\n",
"ID \n",
"7 (foreground_db, O2-byproduct) O2-byproduct | oxygen | GLO 1.52 0"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"pulpo_worker.summarize_results(zeroes=True)"
]
},
{
"cell_type": "markdown",
"id": "e0018d74",
"metadata": {},
"source": [
"### 3.6 Multi-Product Demand\n",
"\n",
"Extend the system to include ozone production (2 kg) alongside methanol. This demonstrates PULPO's handling of multi-functional systems and oxygen flow optimization between different end uses."
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "30b77b60",
"metadata": {},
"outputs": [],
"source": [
"ozone_process = pulpo_worker.retrieve_processes(reference_products='ozone')\n",
"\n",
"demand = {methanol_process[0]: 1,\n",
" ozone_process[0]: 2,}"
]
},
{
"cell_type": "markdown",
"id": "5253adb4",
"metadata": {},
"source": [
"#### Optimization: Multi-Product System\n",
"\n",
"Solve with combined methanol and ozone demands. Oxygen byproduct from hydrogen electrolysis can now be utilized for ozone production, enabling potential system synergies."
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "23c7f8d0",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Creating Instance\n",
"Instance created\n",
"optimal solution found: 1.760427258456396\n",
"Optimization problem solved using Highspy\n"
]
}
],
"source": [
"pulpo_worker.instantiate(choices=choices, demand=demand, lower_limit=lower_bound)\n",
"results = pulpo_worker.solve()"
]
},
{
"cell_type": "markdown",
"id": "b716a886",
"metadata": {},
"source": [
"#### Results Analysis: Multi-Product System\n",
"\n",
"Compare results with single-product case. Examine how oxygen flows changed and whether optimal technology choices shifted due to ozone demand integration."
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "034e398d",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"## Total Impact(s)"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Weight \n",
" Value \n",
" \n",
" \n",
" Method \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" ('my project', 'climate change') \n",
" 1 \n",
" 1.760427 \n",
" \n",
" \n",
" ('my project', 'resources') \n",
" 0 \n",
" 0.001710 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Weight Value\n",
"Method \n",
"('my project', 'climate change') 1 1.760427\n",
"('my project', 'resources') 0 0.001710"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"## Choices Made"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Electricity"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Value \n",
" Capacity \n",
" \n",
" \n",
" Metadata \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" wind electricity | electricity | GLO \n",
" 13.868938 \n",
" inf \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Value Capacity\n",
"Metadata \n",
"wind electricity | electricity | GLO 13.868938 inf"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Hydrogen"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Value \n",
" Capacity \n",
" \n",
" \n",
" Metadata \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" hydrogen electrolysis | hydrogen | GLO \n",
" 0.19 \n",
" inf \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Value Capacity\n",
"Metadata \n",
"hydrogen electrolysis | hydrogen | GLO 0.19 inf"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Oxygen"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Value \n",
" Capacity \n",
" \n",
" \n",
" Metadata \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" O2-market | oxygen | GLO \n",
" 1.52 \n",
" inf \n",
" \n",
" \n",
" O2 ASU | oxygen | GLO \n",
" 0.48 \n",
" inf \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Value Capacity\n",
"Metadata \n",
"O2-market | oxygen | GLO 1.52 inf\n",
"O2 ASU | oxygen | GLO 0.48 inf"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"## Constraints"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"'No constraint data to display.'"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"pulpo_worker.summarize_results(zeroes=True)"
]
},
{
"cell_type": "markdown",
"id": "5ad4b05f",
"metadata": {},
"source": [
"## 4. Constrained Optimization\n",
"\n",
"### 4.1 Technology Capacity Constraints\n",
"\n",
"Real-world technologies operate within finite capacity limits. Apply realistic constraints:\n",
"- Electricity sources: 8 units maximum each\n",
"- Hydrogen production: 0.1 units maximum each\n",
"- Oxygen supply: 1.2 units maximum each\n",
"\n",
"These constraints force optimization within technological feasibility bounds."
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "24550c3e",
"metadata": {},
"outputs": [],
"source": [
"## Choices\n",
"choices = {\n",
" \"Electricity\": {electricity_processes[0]: 8, electricity_processes[1]: 8},\n",
" \"Hydrogen\": {hydrogen_processes[0]: 0.1, hydrogen_processes[1]: 0.1},\n",
" \"Oxygen\": {oxygen_processes[0]: 1.2, oxygen_processes[1]:1.2,},\n",
"}"
]
},
{
"cell_type": "markdown",
"id": "69798c20",
"metadata": {},
"source": [
"#### Optimization: Capacity-Constrained System\n",
"\n",
"Solve with active capacity constraints. This may require technology portfolio diversification rather than single-technology selection for environmental optimality."
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "24fc4366",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Creating Instance\n",
"Instance created\n",
"optimal solution found: 3.2944402907815795\n",
"Optimization problem solved using Highspy\n"
]
}
],
"source": [
"pulpo_worker.instantiate(choices=choices, demand=demand, lower_limit=lower_bound)\n",
"results = pulpo_worker.solve()"
]
},
{
"cell_type": "markdown",
"id": "b6f1e981",
"metadata": {},
"source": [
"#### Results Analysis: Impact of Capacity Constraints\n",
"\n",
"Examine how technology mix and total environmental impact change under capacity limitations. The optimizer balances environmental optimality against technological feasibility."
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "d0b71ece",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"## Total Impact(s)"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Weight \n",
" Value \n",
" \n",
" \n",
" Method \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" ('my project', 'climate change') \n",
" 1 \n",
" 3.294440 \n",
" \n",
" \n",
" ('my project', 'resources') \n",
" 0 \n",
" 0.003935 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Weight Value\n",
"Method \n",
"('my project', 'climate change') 1 3.294440\n",
"('my project', 'resources') 0 0.003935"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"## Choices Made"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Electricity"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Value \n",
" Capacity \n",
" \n",
" \n",
" Metadata \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" wind electricity | electricity | GLO \n",
" 8.000000 \n",
" 8 \n",
" \n",
" \n",
" natural gas electricity | electricity | GLO \n",
" 1.536073 \n",
" 8 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Value Capacity\n",
"Metadata \n",
"wind electricity | electricity | GLO 8.000000 8\n",
"natural gas electricity | electricity | GLO 1.536073 8"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Hydrogen"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Value \n",
" Capacity \n",
" \n",
" \n",
" Metadata \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" hydrogen electrolysis | hydrogen | GLO \n",
" 0.10 \n",
" 0.1 \n",
" \n",
" \n",
" hydrogen SMR | hydrogen | GLO \n",
" 0.09 \n",
" 0.1 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Value Capacity\n",
"Metadata \n",
"hydrogen electrolysis | hydrogen | GLO 0.10 0.1\n",
"hydrogen SMR | hydrogen | GLO 0.09 0.1"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Oxygen"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Value \n",
" Capacity \n",
" \n",
" \n",
" Metadata \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" O2 ASU | oxygen | GLO \n",
" 1.2 \n",
" 1.2 \n",
" \n",
" \n",
" O2-market | oxygen | GLO \n",
" 0.8 \n",
" 1.2 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Value Capacity\n",
"Metadata \n",
"O2 ASU | oxygen | GLO 1.2 1.2\n",
"O2-market | oxygen | GLO 0.8 1.2"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"## Constraints"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"'No constraint data to display.'"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"pulpo_worker.summarize_results(zeroes=True)"
]
},
{
"cell_type": "markdown",
"id": "d6eb9696",
"metadata": {},
"source": [
"### 4.2 Resource Availability Constraints\n",
"\n",
"Beyond technology capacity, resource availability represents another critical limitation. Constrain water supply to 1 m³ to simulate water scarcity scenarios."
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "5969aa86",
"metadata": {},
"outputs": [],
"source": [
"water_process = pulpo_worker.retrieve_processes(reference_products='water')"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "89dc0823",
"metadata": {},
"outputs": [],
"source": [
"upper_bound = {water_process[0]: 1}"
]
},
{
"cell_type": "markdown",
"id": "2dff0884",
"metadata": {},
"source": [
"#### Optimization: Combined Constraints\n",
"\n",
"Apply both technology capacity limits and water availability constraints simultaneously. This represents realistic scenarios with multiple operational limitations."
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "2b5bd842",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Creating Instance\n",
"Instance created\n",
"optimal solution found: 3.2944402907815795\n",
"Optimization problem solved using Highspy\n"
]
}
],
"source": [
"pulpo_worker.instantiate(choices=choices, demand=demand, lower_limit=lower_bound, upper_limit=upper_bound)\n",
"results = pulpo_worker.solve()"
]
},
{
"cell_type": "markdown",
"id": "602dec6d",
"metadata": {},
"source": [
"#### Results Analysis: Resource Limitation Effects\n",
"\n",
"Water limitation forces the system toward less water-intensive processes. Compare water consumption across scenarios to quantify constraint effects on technology selection."
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "4daf6a1a",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"## Total Impact(s)"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Weight \n",
" Value \n",
" \n",
" \n",
" Method \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" ('my project', 'climate change') \n",
" 1 \n",
" 3.294440 \n",
" \n",
" \n",
" ('my project', 'resources') \n",
" 0 \n",
" 0.003935 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Weight Value\n",
"Method \n",
"('my project', 'climate change') 1 3.294440\n",
"('my project', 'resources') 0 0.003935"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"## Choices Made"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Electricity"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Value \n",
" Capacity \n",
" \n",
" \n",
" Metadata \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" wind electricity | electricity | GLO \n",
" 8.000000 \n",
" 8 \n",
" \n",
" \n",
" natural gas electricity | electricity | GLO \n",
" 1.536073 \n",
" 8 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Value Capacity\n",
"Metadata \n",
"wind electricity | electricity | GLO 8.000000 8\n",
"natural gas electricity | electricity | GLO 1.536073 8"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Hydrogen"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Value \n",
" Capacity \n",
" \n",
" \n",
" Metadata \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" hydrogen electrolysis | hydrogen | GLO \n",
" 0.10 \n",
" 0.1 \n",
" \n",
" \n",
" hydrogen SMR | hydrogen | GLO \n",
" 0.09 \n",
" 0.1 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Value Capacity\n",
"Metadata \n",
"hydrogen electrolysis | hydrogen | GLO 0.10 0.1\n",
"hydrogen SMR | hydrogen | GLO 0.09 0.1"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Oxygen"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Value \n",
" Capacity \n",
" \n",
" \n",
" Metadata \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" O2 ASU | oxygen | GLO \n",
" 1.2 \n",
" 1.2 \n",
" \n",
" \n",
" O2-market | oxygen | GLO \n",
" 0.8 \n",
" 1.2 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Value Capacity\n",
"Metadata \n",
"O2 ASU | oxygen | GLO 1.2 1.2\n",
"O2-market | oxygen | GLO 0.8 1.2"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"## Constraints"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Constraints Upper"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Key \n",
" Metadata \n",
" Value \n",
" Limit \n",
" \n",
" \n",
" ID \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" 3 \n",
" (background_db, water supply) \n",
" water supply | water | GLO \n",
" 0.00117 \n",
" 1 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Key Metadata Value Limit\n",
"ID \n",
"3 (background_db, water supply) water supply | water | GLO 0.00117 1"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"pulpo_worker.summarize_results(zeroes=True)"
]
},
{
"cell_type": "markdown",
"id": "79f33769",
"metadata": {},
"source": [
"### 4.3 Impact Category Switching\n",
"\n",
"Demonstrate objective function flexibility by switching from climate change to resource use optimization. Different environmental priorities lead to distinct technology choices."
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "d6ef6773",
"metadata": {},
"outputs": [],
"source": [
"pulpo_worker.method = {\"('my project', 'climate change')\": 0,\n",
" \"('my project', 'resources')\": 1,}"
]
},
{
"cell_type": "markdown",
"id": "e5b972e0",
"metadata": {},
"source": [
"#### Optimization: Resource Efficiency Focus\n",
"\n",
"Reset constraints to unconstrained levels and optimize for resource efficiency. This will likely select different technologies than climate-optimized solutions."
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "0270204f",
"metadata": {},
"outputs": [],
"source": [
"## Choices\n",
"choices = {\n",
" \"Electricity\": {electricity_processes[0]: float('inf'), electricity_processes[1]: float('inf')},\n",
" \"Hydrogen\": {hydrogen_processes[0]: float('inf'), hydrogen_processes[1]: float('inf')},\n",
" \"Oxygen\": {oxygen_processes[0]: float('inf'), oxygen_processes[1]: float('inf'),},\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "32e31a2a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Creating Instance\n",
"Instance created\n",
"optimal solution found: 0.0005699999978020787\n",
"Optimization problem solved using Highspy\n"
]
}
],
"source": [
"pulpo_worker.instantiate(choices=choices, demand=demand, lower_limit=lower_bound)\n",
"results = pulpo_worker.solve()"
]
},
{
"cell_type": "markdown",
"id": "87800bd9",
"metadata": {},
"source": [
"#### Results Analysis\n",
"\n",
"Compare resource-optimized results with climate change optimization. Different environmental priorities (climate vs. resources) yield different optimal technology portfolios, demonstrating the importance of multi-criteria decision-making in sustainable technology design."
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "f9d46543",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"## Total Impact(s)"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Weight \n",
" Value \n",
" \n",
" \n",
" Method \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" ('my project', 'resources') \n",
" 1 \n",
" 0.000570 \n",
" \n",
" \n",
" ('my project', 'climate change') \n",
" 0 \n",
" 3.475288 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Weight Value\n",
"Method \n",
"('my project', 'resources') 1 0.000570\n",
"('my project', 'climate change') 0 3.475288"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"## Choices Made"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Electricity"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Value \n",
" Capacity \n",
" \n",
" \n",
" Metadata \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" wind electricity | electricity | GLO \n",
" 4.721779 \n",
" inf \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Value Capacity\n",
"Metadata \n",
"wind electricity | electricity | GLO 4.721779 inf"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Hydrogen"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Value \n",
" Capacity \n",
" \n",
" \n",
" Metadata \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" hydrogen SMR | hydrogen | GLO \n",
" 0.19 \n",
" inf \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Value Capacity\n",
"Metadata \n",
"hydrogen SMR | hydrogen | GLO 0.19 inf"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Oxygen"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Value \n",
" Capacity \n",
" \n",
" \n",
" Metadata \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" O2 ASU | oxygen | GLO \n",
" 2.0 \n",
" inf \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Value Capacity\n",
"Metadata \n",
"O2 ASU | oxygen | GLO 2.0 inf"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"## Constraints"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"'No constraint data to display.'"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"pulpo_worker.summarize_results(zeroes=True)"
]
},
{
"cell_type": "markdown",
"id": "c9e1fa48",
"metadata": {},
"source": [
"## 5. Summary: Core PULPO Capabilities\n",
"\n",
"This demonstration covered PULPO's fundamental optimization features:\n",
"\n",
"**System Integration:**\n",
"- Multi-database integration (background + foreground systems)\n",
"- Technology choice optimization across energy, hydrogen, and oxygen sources\n",
"- Multi-product system optimization with material flow synergies\n",
"\n",
"**Constraint Handling:**\n",
"- Technology capacity constraints (realistic deployment limits)\n",
"- Resource availability constraints (scarcity scenarios)\n",
"- Process flow constraints (physical feasibility)\n",
"\n",
"**Multi-Criteria Analysis:**\n",
"- Objective function flexibility (climate change vs. resource use)\n",
"- Technology trade-off analysis under different environmental priorities\n",
"- Impact assessment across multiple environmental categories"
]
},
{
"cell_type": "markdown",
"id": "aa9d9470",
"metadata": {},
"source": [
"## 6. Multi-Objective Optimization: Pareto Front Analysis\n",
"\n",
"Explore trade-offs between competing objectives through Pareto front generation. This analysis reveals how environmental performance varies when balancing climate change and resource use priorities using the epsilon-constraint method."
]
},
{
"cell_type": "markdown",
"id": "1d1787c8",
"metadata": {},
"source": [
"### 6.1 Multi-Objective Setup\n",
"\n",
"Create dual-objective PULPO worker with equal weighting for both climate change and resource use objectives to establish baseline performance ranges."
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "3af5a051",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Multi-objective PULPO worker created with both climate change and resource use objectives\n"
]
}
],
"source": [
"# Create multi-objective method configuration\n",
"methods_multi = {\n",
" \"('my project', 'climate change')\": 1,\n",
" \"('my project', 'resources')\": 1\n",
"}\n",
"\n",
"# Initialize multi-objective PULPO worker\n",
"pulpo_worker_multi = pulpo.PulpoOptimizer(project, database, methods_multi)\n",
"pulpo_worker_multi.get_lci_data()\n",
"\n",
"print(\"Multi-objective PULPO worker created with both climate change and resource use objectives\")"
]
},
{
"cell_type": "markdown",
"id": "0e937936",
"metadata": {},
"source": [
"### 6.2 Extreme Point Identification\n",
"\n",
"Determine boundary solutions for Pareto front generation:\n",
"1. **Climate-optimal solution**: Minimize climate change (resource use unconstrained)\n",
"2. **Resource-optimal solution**: Minimize resource use (climate change unconstrained)\n",
"\n",
"These extreme points define the feasible range for epsilon constraints."
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "b35e4a90",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Creating Instance\n",
"Instance created\n",
"optimal solution found: 1.760427258456396\n",
"Optimization problem solved using Highspy\n",
"Climate-optimal solution:\n",
" Climate change: 1.7604\n",
" Resource use: 0.0017\n"
]
}
],
"source": [
"# 1. Find climate-optimal solution (minimize climate change)\n",
"methods_climate = {\n",
" \"('my project', 'climate change')\": 1,\n",
" \"('my project', 'resources')\": 0\n",
"}\n",
"\n",
"pulpo_worker_climate = pulpo.PulpoOptimizer(project, database, methods_climate)\n",
"pulpo_worker_climate.get_lci_data()\n",
"\n",
"# Use unconstrained choices for extreme points\n",
"choices_unconstrained = {\n",
" \"Electricity\": {electricity_processes[0]: float('inf'), electricity_processes[1]: float('inf')},\n",
" \"Hydrogen\": {hydrogen_processes[0]: float('inf'), hydrogen_processes[1]: float('inf')},\n",
" \"Oxygen\": {oxygen_processes[0]: float('inf'), oxygen_processes[1]: float('inf')},\n",
"}\n",
"\n",
"pulpo_worker_climate.instantiate(choices=choices_unconstrained, demand=demand, lower_limit=lower_bound)\n",
"results_climate = pulpo_worker_climate.solve()\n",
"\n",
"# Extract optimal impacts\n",
"climate_optimal_cc = pulpo_worker_climate.instance.impacts_calculated[\"('my project', 'climate change')\"].value\n",
"climate_optimal_res = pulpo_worker_climate.instance.impacts_calculated[\"('my project', 'resources')\"].value\n",
"\n",
"print(f\"Climate-optimal solution:\")\n",
"print(f\" Climate change: {climate_optimal_cc:.4f}\")\n",
"print(f\" Resource use: {climate_optimal_res:.4f}\")"
]
},
{
"cell_type": "code",
"execution_count": 29,
"id": "0781323c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Creating Instance\n",
"Instance created\n",
"optimal solution found: 0.0005699999978020787\n",
"Optimization problem solved using Highspy\n",
"Resource-optimal solution:\n",
" Climate change: 3.4753\n",
" Resource use: 0.0006\n",
"\n",
"Objective ranges:\n",
" Climate change: 1.7604 to 3.4753\n",
" Resource use: 0.0006 to 0.0017\n"
]
}
],
"source": [
"# 2. Find resource-optimal solution (minimize resource use)\n",
"methods_resource = {\n",
" \"('my project', 'climate change')\": 0,\n",
" \"('my project', 'resources')\": 1\n",
"}\n",
"\n",
"pulpo_worker_resource = pulpo.PulpoOptimizer(project, database, methods_resource)\n",
"pulpo_worker_resource.get_lci_data()\n",
"\n",
"pulpo_worker_resource.instantiate(choices=choices_unconstrained, demand=demand, lower_limit=lower_bound)\n",
"results_resource = pulpo_worker_resource.solve()\n",
"\n",
"# Extract optimal impacts\n",
"resource_optimal_cc = pulpo_worker_resource.instance.impacts_calculated[\"('my project', 'climate change')\"].value\n",
"resource_optimal_res = pulpo_worker_resource.instance.impacts_calculated[\"('my project', 'resources')\"].value\n",
"\n",
"print(f\"Resource-optimal solution:\")\n",
"print(f\" Climate change: {resource_optimal_cc:.4f}\")\n",
"print(f\" Resource use: {resource_optimal_res:.4f}\")\n",
"\n",
"print(f\"\\nObjective ranges:\")\n",
"print(f\" Climate change: {climate_optimal_cc:.4f} to {resource_optimal_cc:.4f}\")\n",
"print(f\" Resource use: {resource_optimal_res:.4f} to {climate_optimal_res:.4f}\")"
]
},
{
"cell_type": "markdown",
"id": "c220afa0",
"metadata": {},
"source": [
"### 6.3 Epsilon-Constraint Implementation\n",
"\n",
"Generate Pareto front using systematic constraint variation:\n",
"- **Primary objective**: Minimize resource use\n",
"- **Secondary objective**: Climate change (constrained via upper impact limits)\n",
"- **Method**: Vary climate change constraint from climate-optimal to resource-optimal values"
]
},
{
"cell_type": "code",
"execution_count": 30,
"id": "a7d14f8b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Generating Pareto front with 8 points...\n",
"Climate change constraint range: 1.7604 to 3.4753\n",
"============================================================\n",
"Point 1/8: Climate constraint = 1.7604\n",
"Creating Instance\n",
"Instance created\n",
"optimal solution found: 0.0017099999049305925\n",
"Optimization problem solved using Highspy\n",
" → Resource use: 0.0017\n",
" → Climate change: 1.7604\n",
"\n",
"Point 2/8: Climate constraint = 2.0054\n",
"Creating Instance\n",
"Instance created\n",
"optimal solution found: 0.001547142775340805\n",
"Optimization problem solved using Highspy\n",
" → Resource use: 0.0015\n",
" → Climate change: 2.0054\n",
"\n",
"Point 3/8: Climate constraint = 2.2504\n",
"Creating Instance\n",
"Instance created\n",
"optimal solution found: 0.0013842856457510172\n",
"Optimization problem solved using Highspy\n",
" → Resource use: 0.0014\n",
" → Climate change: 2.2504\n",
"\n",
"Point 4/8: Climate constraint = 2.4954\n",
"Creating Instance\n",
"Instance created\n",
"optimal solution found: 0.0012214285161612295\n",
"Optimization problem solved using Highspy\n",
" → Resource use: 0.0012\n",
" → Climate change: 2.4954\n",
"\n",
"Point 5/8: Climate constraint = 2.7403\n",
"Creating Instance\n",
"Instance created\n",
"optimal solution found: 0.0010585713865714416\n",
"Optimization problem solved using Highspy\n",
" → Resource use: 0.0011\n",
" → Climate change: 2.7403\n",
"\n",
"Point 6/8: Climate constraint = 2.9853\n",
"Creating Instance\n",
"Instance created\n",
"optimal solution found: 0.0008957142569816538\n",
"Optimization problem solved using Highspy\n",
" → Resource use: 0.0009\n",
" → Climate change: 2.9853\n",
"\n",
"Point 7/8: Climate constraint = 3.2303\n",
"Creating Instance\n",
"Instance created\n",
"optimal solution found: 0.0007328571273918662\n",
"Optimization problem solved using Highspy\n",
" → Resource use: 0.0007\n",
" → Climate change: 3.2303\n",
"\n",
"Point 8/8: Climate constraint = 3.4753\n",
"Creating Instance\n",
"Instance created\n",
"optimal solution found: 0.0005699999978020787\n",
"Optimization problem solved using Highspy\n",
" → Resource use: 0.0006\n",
" → Climate change: 3.4753\n",
"\n",
"Pareto front generation complete: 8 feasible points\n"
]
}
],
"source": [
"# Generate epsilon constraints for climate change\n",
"n_points = 8 # Number of Pareto points\n",
"epsilon_list = np.linspace(climate_optimal_cc, resource_optimal_cc, num=n_points)\n",
"\n",
"# Initialize empty list to store Pareto front data\n",
"pareto_front = []\n",
"\n",
"# Category names for easier reference\n",
"cc_category = \"('my project', 'climate change')\"\n",
"res_category = \"('my project', 'resources')\"\n",
"\n",
"print(f\"Generating Pareto front with {n_points} points...\")\n",
"print(f\"Climate change constraint range: {climate_optimal_cc:.4f} to {resource_optimal_cc:.4f}\")\n",
"print(\"=\" * 60)\n",
"\n",
"# Configure worker for epsilon-constraint (minimize resources, constrain climate)\n",
"methods_epsilon = {\n",
" \"('my project', 'climate change')\": 0,\n",
" \"('my project', 'resources')\": 1\n",
"}\n",
"\n",
"pulpo_worker_pareto = pulpo.PulpoOptimizer(project, database, methods_epsilon)\n",
"pulpo_worker_pareto.get_lci_data()\n",
"\n",
"for i, epsilon in enumerate(epsilon_list):\n",
" print(f\"Point {i+1}/{n_points}: Climate constraint = {epsilon:.4f}\")\n",
" \n",
" # Set up epsilon constraint\n",
" epsilon_constraint = {cc_category: epsilon}\n",
" \n",
" # Solve with climate change constraint\n",
" pulpo_worker_pareto.instantiate(\n",
" choices=choices_unconstrained, \n",
" demand=demand, \n",
" lower_limit=lower_bound,\n",
" upper_imp_limit=epsilon_constraint\n",
" )\n",
" results = pulpo_worker_pareto.solve()\n",
" \n",
"\n",
" impacts = {x: pulpo_worker_pareto.instance.impacts_calculated[x].value for x in pulpo_worker_pareto.instance.impacts_calculated}\n",
" \n",
" # Store Pareto point (resource use, climate change)\n",
" pareto_point = (impacts[res_category], impacts[cc_category])\n",
" pareto_front.append(pareto_point)\n",
" \n",
" print(f\" → Resource use: {impacts[res_category]:.4f}\")\n",
" print(f\" → Climate change: {impacts[cc_category]:.4f}\")\n",
" print()\n",
"\n",
"print(f\"Pareto front generation complete: {len(pareto_front)} feasible points\")"
]
},
{
"cell_type": "markdown",
"id": "2869da7a",
"metadata": {},
"source": [
"### 6.4 Pareto Front Visualization\n",
"\n",
"Generate comprehensive visualization showing trade-offs between climate change and resource use across the complete feasible solution space."
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "7b5048ec",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAA90AAAJOCAYAAACqS2TfAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjcsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvTLEjVAAAAAlwSFlzAAAPYQAAD2EBqD+naQAA0HNJREFUeJzs3QeYE1UXBuBvqUvvXZAqvfeiFFFpShFERARUsKDSi0hVEAVBQFCKv1IEKUoTFKlSBemCoICAIL33upv/+e44u7NhO7ubbPZ7ffKsmUySyUwScubce46fy+VyQURERERERERiXKKYf0gRERERERERUdAtIiIiIiIiEouU6RYRERERERGJJQq6RURERERERGKJgm4RERERERGRWKKgW0RERERERCSWKOgWERERERERiSUKukVERERERERiiYJuERERERERkViioFtERBKEWrVqwc/Pz1zatWsXtPzIkSNBy3n55ZdfPLqd8R33n3N/cv+KiIgkZAq6RSRWf3A7L6lTp0axYsXw9ttv49ChQ1695z0VOOTNmzfM/ee8eDMGtPZ2MtCNLbdu3cLkyZPxzDPPIHfu3EiRIgX8/f3NPmzWrBm+/vpr3LhxA758wiCu/P7773jnnXdQtmxZZMyYEUmTJkWGDBlQqVIl9OzZ09wuviWs76KUKVMif/78eP7557F69WpPb6aE8W/WlClTwv1u9vZ/R0R8TRJPb4CIJBzXr1/Hvn37zOWrr77CwoULUbduXU9vlsRDa9euRevWrfHvv//ed9s///xjLvPnz49UkMogcsSIEUHXCxQoECvbHB/xxEbnzp0xadKk+267dOkStmzZYi5z585VRjuBuHnzJg4fPmwus2fPxsSJE9GxY0dPb5aIiFdT0C0isaply5aoUKEC7ty5g19//RWLFy82y5mBbNOmjfmhnjx58hh/3oCAANy+fdtkZeIrZpPeeOONaN//ypUrSJs2LXzNunXr8OSTT5rja6tSpQpq165tRlOcOHECq1atMid3IoP7qEePHrG4xfETP0PPPfccfvjhh6Bl6dKlM6MIChYsaAJyZriXLVvm0e2UuPsu4vc4j/mcOXPgcrnMbX379sWrr76KRIkS5uBJ7hPui9j4d0xEfIhLRCQGrV69mr/Egi5ff/11iNtbt24d4vaVK1cG3e/ll192lS1b1pU9e3ZXsmTJ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tGfPnhCvbdOmTWb5tWvXzD7i+y916tSuJEmSuLJkyeIqXbq0+bflp59+ivLniriPPvvsM9ejjz5qvme4P7hfmjdv7tq4cWOE+/7SpUuut99+29wnZcqUrlq1ark2b95s1v37779dzz77rNm/3OannnrKtXv37lD35aRJk4Ies27dupE+BiISsxR0i0i8lydPnqAfFYsXL47wx0yTJk2C/n/JkiVmnYMHDwYFR/xBmlCCbuKPQOftx48fv+9+DMKKFCkSYj076N67d6/5kRve6+jcuXOI57xz5475MRraug0bNozxoPvmzZv3Pa775eLFi7ESdDOot98XDFru3r17X5Dg/p5zbjuDhzZt2oS7TS1atAgKTKIbdFesWNGVMWPG+9b18/NzrVixIsTr4w/+8B6fAd7vv/8e5j4pVaqUK02aNJF6rui8v7wt6Ob7z9/fP2h78uXLF/Q+cOKJLQZR9np58+aNdtAdE/utRo0aod6P70enqL5HI8Jg0/ndw+/niJw4cSLoJJbzu93m/LzxBJ+NwWx4292yZcsof67OnDljPvdhrcd/a0aPHh3uvueJEvf78T20cOHCUD+nPHnF53XHYNxehye3wjphIiKxS3O6RSReO3r0qLnYKlSoEOF9OK+NxYru3r1r5tlyGOe4ceMQGBhobmeRNRZmiwsc5v33339jwoQJQcs4jDJDhgzm/0uUKBGrz8+Kts4CXyxWlClTpvvWO3funLnUrVsX1atXN0MVWdyIcwVZEOrff/816yVOnBht2rQx88IXLFiAPXv2BA2jLleunJmnaV9ft25d0OOXLVsWjRo1MuvHxr7v3r17iAJVHK7P7WZhpj/++AOLFy82yytWrGiOyezZs7F161azjAWu+J5xzq+PCu6Tt956Cz179jRV9b/77js0a9bMFO2zH5+vPazXPXz48KChthzmzDnBpUuXNvN/uZzv47lz55rhyXzvPPnkk0idOrUpnMQpA/bnomXLluHWBOD8cr7vOHyXlY8nT56MgIAAM/ef+4RDo20swMfnKVq0qLkPh/qePn3avAZ+Hjnvtnfv3vjxxx9DfU0cYh2Z54ru+8vbcN86h4o3adIESZLc/xOMnz1+xvjaiHOX+dr5ep9//vn7vg+4f1evXh103b49pvbb+vXrzeMUK1bMFH+zC/zx/z/66CPkzJkzWu/RiHCbbPze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fkf2IekGAAAAgIA55xzpqaekwYOlGjVS2q23u3dv6bnnvF5wZD1KhgEAAABAQMuMWYmxCy/05nVPnCjt2OHdNn++tHCh1KaN1KmTFB8f6b0NLnq6AQAAACDgyfell3plxu66K6WOd2Ki9OGH3krntuL54cOR3tNgIukGAAAAgFwgXz7pmmu8MmOdO0uxsV57QoJX29uSb6v1ffx4pPc0WEi6AQAAACAXKVRIuuUWL/n+4x+lvHm99v37vdJjvXpJ8+ZRZuxMIekGAAAAgFzI5nHffbdXz9uGn/ts3vfw4d6Ca0uXknz/r0i6AQAAACAXq1BB+utfpRdf9BZd861fLw0aJD32mLRmTST3MGcj6QYAAAAA6OyzpSeekJ58UqpZM+WArFgh/eUv0tCh0tatHKhAJN0jR45U9erVFRsbqyZNmujf//73KbefNm2azj33XLd9vXr19NFHH6W6PRQKaeDAgapQoYIKFSqk1q1ba02aUzV79uxRly5dVKxYMcXHx+uOO+7QwYMH0z3O8OHDVatWLRUsWFCVKlXS008/fQZfOQAAAABE1gUXSC+8ID30kNcL7rMSY/fcY/ma5U+R3MOcJeqS7n/+85/6y1/+oscff1zLli1TgwYNdPXVV2vnzp0Zbr9o0SJ17tzZJcnLly/Xdddd536+/fbb5G2GDRumESNGaPTo0fryyy8VFxfnHjPBlun7lSXcq1at0qeffqoPPvhA8+fP1122nn6YBx54QGPHjnWJ9+rVq/Xee++pcePGWXg0AAAAACAyZcZatJBeecVbWM2v452UJM2a5ZUee+MN6dAhonM6MSHrvo0i1rN98cUX6+WXX3bXk5KSVKVKFd1///16+OGH023fsWNHHTp0yCXKvj/84Q+64IILXJJtL69ixYrq27ev+vXr527ft2+fypUrp/Hjx6tTp0767rvvdN555+mrr77SRRdd5LaZNWuW2rVrpx9//NHd37apX7++S+Zr1679u17b/v37Vbx4cff81qMeSXZc7URG2bJllSdP1J17we9EXIOJuAYPMQ0m4hpMxDWYiOtvZ/2V774rvfOOdORISnvRopaTSe3aSfnzK1fFdH8m87uoyraOHTumpUuXuuHfPjtgdn3x4sUZ3sfaw7c31ovtb79hwwZt37491TZ2YCy597exSxtS7ifcxra357aecfP++++rRo0a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",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"📈 PARETO FRONT ANALYSIS\n",
"========================================\n",
"Number of Pareto points: 8\n",
"\n",
"Climate Change Range:\n",
" Best: 1.7604\n",
" Worst: 3.4753\n",
" Range: 1.7149\n",
"\n",
"Resource Use Range:\n",
" Best: 0.0006\n",
" Worst: 0.0017\n",
" Range: 0.0011\n"
]
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"\n",
"# Extract data for plotting\n",
"if pareto_front:\n",
" resource_values = [point[0] for point in pareto_front]\n",
" climate_values = [point[1] for point in pareto_front]\n",
" \n",
" # Create the plot\n",
" plt.figure(figsize=(10, 6))\n",
" \n",
" # Plot Pareto front\n",
" plt.plot(climate_values, resource_values, 'bo-', linewidth=2, markersize=8, \n",
" label='Pareto Front', alpha=0.7)\n",
" \n",
" # Highlight extreme points\n",
" plt.plot(climate_optimal_cc, climate_optimal_res, 'ro', markersize=12, \n",
" label='Climate Optimal', alpha=0.8)\n",
" plt.plot(resource_optimal_cc, resource_optimal_res, 'go', markersize=12, \n",
" label='Resource Optimal', alpha=0.8)\n",
" \n",
" # Formatting\n",
" plt.xlabel('Climate Change Impact', fontsize=12)\n",
" plt.ylabel('Resource Use Impact', fontsize=12)\n",
" plt.title('Pareto Front: Climate Change vs. Resource Use\\n(Multi-Product Methanol + Ozone System)', \n",
" fontsize=14, fontweight='bold')\n",
" plt.grid(True, alpha=0.3)\n",
" plt.legend()\n",
" \n",
" plt.tight_layout()\n",
" plt.show()\n",
" \n",
" # Print summary statistics\n",
" print(\"📈 PARETO FRONT ANALYSIS\")\n",
" print(\"=\" * 40)\n",
" print(f\"Number of Pareto points: {len(pareto_front)}\")\n",
" print(f\"\\nClimate Change Range:\")\n",
" print(f\" Best: {min(climate_values):.4f}\")\n",
" print(f\" Worst: {max(climate_values):.4f}\")\n",
" print(f\" Range: {max(climate_values) - min(climate_values):.4f}\")\n",
" print(f\"\\nResource Use Range:\")\n",
" print(f\" Best: {min(resource_values):.4f}\")\n",
" print(f\" Worst: {max(resource_values):.4f}\")\n",
" print(f\" Range: {max(resource_values) - min(resource_values):.4f}\")\n",
" \n",
"else:\n",
" print(\"No feasible Pareto points found\")"
]
},
{
"cell_type": "markdown",
"id": "cc8f5094",
"metadata": {},
"source": [
"## 7. Uncertainty Analysis: Monte Carlo Simulation\n",
"\n",
"Real-world systems contain parameter uncertainties that propagate through optimization results. PULPO's Monte Carlo capabilities enable robustness assessment and uncertainty quantification for environmental impact optimization.\n",
"\n",
"**Analysis Objectives:**\n",
"- Quantify parameter uncertainty effects on optimal solutions\n",
"- Assess result robustness across uncertainty ranges\n",
"- Analyze correlation between environmental objectives under uncertainty\n",
"- Give 90% intervals for the optimal impacts"
]
},
{
"cell_type": "markdown",
"id": "8a9253c9",
"metadata": {},
"source": [
"### 7.1 Uncertainty Worker Configuration\n",
"\n",
"Configure specialized PULPO worker for uncertainty analysis with climate change minimization as primary objective while tracking both impact categories."
]
},
{
"cell_type": "code",
"execution_count": 32,
"id": "cc13c873",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Uncertainty analysis PULPO worker created successfully\n",
"Objective: Minimize climate change impact under parameter uncertainty\n"
]
}
],
"source": [
"# Create uncertainty analysis worker focusing on climate change\n",
"methods_uncertainty = {\n",
" \"('my project', 'climate change')\": 1,\n",
" \"('my project', 'resources')\": 0, # weight 0: not optimized, but reported in the results\n",
"}\n",
"\n",
"# Initialize uncertainty PULPO worker\n",
"pulpo_worker_unc = pulpo.PulpoOptimizer(project, database, methods_uncertainty)\n",
"pulpo_worker_unc.get_lci_data()\n",
"\n",
"print(\"Uncertainty analysis PULPO worker created successfully\")\n",
"print(\"Objective: Minimize climate change impact under parameter uncertainty\")"
]
},
{
"cell_type": "markdown",
"id": "82bdebd8",
"metadata": {},
"source": [
"### 7.2 Monte Carlo Parameter Configuration\n",
"\n",
"Configure system parameters for uncertainty analysis:\n",
"- **Demand specification**: Multi-product system (1 kg methanol + 2 kg ozone)\n",
"- **Technology options**: All electricity, hydrogen, and oxygen alternatives available\n",
"- **Constraints**: Unconstrained capacities for computational clarity\n",
"- **Uncertainty source**: Parameter sampling from database uncertainty distributions"
]
},
{
"cell_type": "code",
"execution_count": 33,
"id": "f4f26a19",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"System configuration for uncertainty analysis:\n",
" Demand: 2 products\n",
" Technology choices: 3 categories\n",
" Lower bounds: 1 constraints\n"
]
}
],
"source": [
"# Configure same system as before for uncertainty analysis\n",
"# Multi-product demand: methanol + ozone\n",
"demand_unc = {methanol_process[0]: 1, ozone_process[0]: 2}\n",
"\n",
"# Technology choices (unconstrained for clarity)\n",
"choices_unc = {\n",
" \"Electricity\": {electricity_processes[0]: float('inf'), electricity_processes[1]: float('inf')},\n",
" \"Hydrogen\": {hydrogen_processes[0]: float('inf'), hydrogen_processes[1]: float('inf')},\n",
" \"Oxygen\": {oxygen_processes[0]: float('inf'), oxygen_processes[1]: float('inf')},\n",
"}\n",
"\n",
"# Lower bounds\n",
"lower_bound_unc = {oxygen_byproduct[0]: 0}\n",
"\n",
"print(\"System configuration for uncertainty analysis:\")\n",
"print(f\" Demand: {len(demand_unc)} products\")\n",
"print(f\" Technology choices: {len(choices_unc)} categories\")\n",
"print(f\" Lower bounds: {len(lower_bound_unc)} constraints\")"
]
},
{
"cell_type": "markdown",
"id": "6170b0e4",
"metadata": {},
"source": [
"### 7.3 Monte Carlo Execution\n",
"\n",
"Execute Monte Carlo simulation using `solve_MC` function:\n",
"1. **Problem instantiation** with specified configuration\n",
"2. **Parameter sampling** across multiple iterations from uncertainty distributions\n",
"3. **Optimization solving** for each parameter realization\n",
"4. **Result collection** across all Monte Carlo iterations\n",
"\n",
"The function automatically handles parameter uncertainty sampling from database distributions."
]
},
{
"cell_type": "code",
"execution_count": 34,
"id": "0a56cb47",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"🎲 Starting Monte Carlo simulation...\n",
"==================================================\n",
"Creating Instance\n",
"Instance created\n",
"Pre-sampling 500 LCI matrix sets...\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Solving 500 Monte Carlo optimizations in parallel...\n",
"Running 500 Monte Carlo optimizations in parallel (n_jobs=-1)...\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"✅ Monte Carlo simulation completed successfully!\n",
" Total iterations: 500\n",
" Results structure: dict with 500 entries\n",
" Available result keys per iteration: ['Scaling Vector', 'Intervention Vector', 'Slack', 'Impacts', 'Transgressions', 'Demand', 'Choices', 'Constraints Upper', 'Constraints Lower', 'Constraints Upper Elem']\n"
]
}
],
"source": [
"# Run Monte Carlo simulation\n",
"print(\"🎲 Starting Monte Carlo simulation...\")\n",
"print(\"=\" * 50)\n",
"\n",
"# Number of Monte Carlo iterations\n",
"n_iterations = 500\n",
"\n",
"# Run Monte Carlo analysis\n",
"pulpo_worker_unc.instantiate(choices=choices_unc, demand=demand_unc, lower_limit=lower_bound_unc)\n",
"mc_results = pulpo_worker_unc.solve_MC(\n",
" n_it=n_iterations,\n",
" seed=1, # reproducible samples\n",
")\n",
"\n",
"print(f\"✅ Monte Carlo simulation completed successfully!\")\n",
"print(f\" Total iterations: {n_iterations}\")\n",
"print(f\" Results structure: dict with {len(mc_results)} entries\")\n",
"print(f\" Available result keys per iteration: {list(next(iter(mc_results.values())).keys())}\")\n"
]
},
{
"cell_type": "markdown",
"id": "0850fd03",
"metadata": {},
"source": [
"### 7.4 Statistical Analysis\n",
"\n",
"Collect the optimal impacts of every sample and summarize them: mean, standard deviation, 90% interval (5th to 95th percentile) and the correlation between the two impact categories."
]
},
{
"cell_type": "code",
"execution_count": 35,
"id": "15b7f169",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Weight \n",
" Value \n",
" \n",
" \n",
" Method \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" ('my project', 'climate change') \n",
" 1 \n",
" 1.633252 \n",
" \n",
" \n",
" ('my project', 'resources') \n",
" 0 \n",
" 0.001787 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Weight Value\n",
"Method \n",
"('my project', 'climate change') 1 1.633252\n",
"('my project', 'resources') 0 0.001787"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mc_results[0]['Impacts']"
]
},
{
"cell_type": "code",
"execution_count": 36,
"id": "d9831ba2",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Extracting both climate change and resource impacts from 500 Monte Carlo iterations...\n",
"Successfully extracted impacts from 500/500 iterations\n",
"Climate change: mean 1.7676, std 0.2798, 90% interval [1.3284, 2.2473]\n",
"Resource use: mean 0.0017, std 0.0003, 90% interval [0.0012, 0.0023]\n",
"Correlation between the two impacts: -0.04\n"
]
}
],
"source": [
"# Extract both climate change and resource impacts from Monte Carlo results\n",
"\n",
"climate_key = \"('my project', 'climate change')\"\n",
"resource_key = \"('my project', 'resources')\"\n",
"\n",
"if isinstance(mc_results, dict) and len(mc_results) > 0:\n",
" print(f\"Extracting both climate change and resource impacts from {len(mc_results)} Monte Carlo iterations...\")\n",
" \n",
" climate_impacts = []\n",
" resource_impacts = []\n",
" successful_iterations = 0\n",
" \n",
" for i, iteration_result in mc_results.items():\n",
" try:\n",
" if \"error\" in iteration_result:\n",
" continue\n",
" # Access impact values from the Impacts DataFrame\n",
" impacts_df = iteration_result[\"Impacts\"]\n",
" climate_value = impacts_df.loc[climate_key, \"Value\"]\n",
" resource_value = impacts_df.loc[resource_key, \"Value\"]\n",
" \n",
" if climate_value is not None and resource_value is not None:\n",
" climate_impacts.append(climate_value)\n",
" resource_impacts.append(resource_value)\n",
" successful_iterations += 1\n",
" except (KeyError, AttributeError) as e:\n",
" print(f\"Warning: Could not extract impacts from iteration {i}: {e}\")\n",
" continue\n",
" \n",
" print(f\"Successfully extracted impacts from {successful_iterations}/{len(mc_results)} iterations\")\n",
" \n",
" if len(climate_impacts) > 0 and len(resource_impacts) > 0:\n",
" # Convert to numpy arrays for analysis\n",
" climate_impacts = np.array(climate_impacts)\n",
" resource_impacts = np.array(resource_impacts)\n",
" \n",
" # Calculate statistical measures for climate change\n",
" climate_mean = np.mean(climate_impacts)\n",
" \n",
" # Calculate statistical measures for resource use\n",
" resource_mean = np.mean(resource_impacts)\n",
"\n",
" climate_std, resource_std = np.std(climate_impacts, ddof=1), np.std(resource_impacts, ddof=1)\n",
" climate_90 = np.percentile(climate_impacts, [5, 95])\n",
" resource_90 = np.percentile(resource_impacts, [5, 95])\n",
" correlation = np.corrcoef(climate_impacts, resource_impacts)[0, 1]\n",
" print(f\"Climate change: mean {climate_mean:.4f}, std {climate_std:.4f}, \"\n",
" f\"90% interval [{climate_90[0]:.4f}, {climate_90[1]:.4f}]\")\n",
" print(f\"Resource use: mean {resource_mean:.4f}, std {resource_std:.4f}, \"\n",
" f\"90% interval [{resource_90[0]:.4f}, {resource_90[1]:.4f}]\")\n",
" print(f\"Correlation between the two impacts: {correlation:.2f}\")"
]
},
{
"cell_type": "markdown",
"id": "bc2f73c5",
"metadata": {},
"source": [
"### 7.5 Uncertainty Visualization\n",
"\n",
"The joint density of the two optimal impacts over all samples, with their means."
]
},
{
"cell_type": "code",
"execution_count": 37,
"id": "41133bba",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"if climate_impacts is not None and resource_impacts is not None and len(climate_impacts) > 0:\n",
" import seaborn as sns\n",
" \n",
" # Create elegant dual-objective uncertainty visualization\n",
" fig, ax1 = plt.subplots(1, 1, figsize=(6, 4))\n",
" \n",
" # 1. Seaborn KDE plot for density distribution\n",
" ax1.set_title('Climate vs. Resource Density Distribution', fontsize=14, fontweight='bold')\n",
" sns.kdeplot(x=climate_impacts, y=resource_impacts, cmap='viridis', fill=True, \n",
" thresh=0.02, ax=ax1, alpha=0.7)\n",
" \n",
" # Add mean lines\n",
" ax1.axvline(climate_mean, color='red', linestyle='--', linewidth=2, alpha=0.8, \n",
" label=f'Climate Mean: {climate_mean:.4f}')\n",
" ax1.axhline(resource_mean, color='red', linestyle='--', linewidth=2, alpha=0.8, \n",
" label=f'Resource Mean: {resource_mean:.4f}')\n",
" \n",
" ax1.set_xlabel('Climate Change Impact')\n",
" ax1.set_ylabel('Resource Use Impact')\n",
" ax1.legend()\n",
" ax1.grid(True, alpha=0.3)\n",
"\n",
" plt.tight_layout()\n",
" plt.show()\n",
"\n",
"else:\n",
" print(\"❌ Cannot create visualization - missing valid impact data for both objectives\")"
]
},
{
"cell_type": "markdown",
"id": "3e08ecfc",
"metadata": {},
"source": [
"> **See also:** `pulpo.utils.uncertainty` for the uncertainty of an impact from its declared distributions: closed-form moments and chance-constrained optimization in reduced space ([uncertainty toy notebook](uncertainty_toy.ipynb))."
]
},
{
"cell_type": "markdown",
"id": "ee1c233a",
"metadata": {},
"source": [
"## 8. Infeasible Problems\n",
"\n",
"Limits that cannot all be met make the optimization problem infeasible. PULPO then raises a `SolveError` (from `pulpo.utils.optimizer`) and loads nothing: the worker keeps its previous solution. The same happens when a solve stops early, for example at a time limit.\n",
"\n",
"Limits belong on the processes, flows and impacts that really have one (`lower_limit`, `upper_limit`, `upper_elem_limit`, `upper_imp_limit`, ...), as in section 4. Bounds on every activity through `default_limits` have no physical meaning; they raise a `FutureWarning`, and `default_limits` may be deprecated in a near-future release."
]
},
{
"cell_type": "markdown",
"id": "7f2fafe4",
"metadata": {},
"source": [
"### 8.1 The Lowest Achievable Impact\n",
"\n",
"Solve the unconstrained problem to find the lowest climate change impact the system can reach."
]
},
{
"cell_type": "code",
"execution_count": 38,
"id": "e220158a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Creating Instance\n",
"Instance created\n",
"optimal solution found: 1.760427258456396\n",
"Optimization problem solved using Highspy\n",
"Lowest achievable climate change impact: 1.760427\n"
]
}
],
"source": [
"from pulpo.utils.optimizer import SolveError\n",
"\n",
"climate = \"('my project', 'climate change')\"\n",
"methods_default = {climate: 1, \"('my project', 'resources')\": 0}\n",
"pulpo_worker_default = pulpo.PulpoOptimizer(project, database, methods_default)\n",
"pulpo_worker_default.get_lci_data()\n",
"\n",
"pulpo_worker_default.instantiate(choices=choices_unconstrained, demand=demand, lower_limit=lower_bound)\n",
"pulpo_worker_default.solve()\n",
"lowest_climate = pulpo_worker_default.instance.impacts_calculated[climate].value\n",
"print(f\"Lowest achievable climate change impact: {lowest_climate:.6f}\")"
]
},
{
"cell_type": "markdown",
"id": "8f06eb1b",
"metadata": {},
"source": [
"### 8.2 A Limit Below It\n",
"\n",
"Ask for half of that impact. No combination of technologies reaches it, so the solve raises a `SolveError`:"
]
},
{
"cell_type": "code",
"execution_count": 39,
"id": "06bc79b4",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Creating Instance\n",
"Instance created\n",
"No solution: HiGHS did not solve the model to optimality (infeasible); the instance keeps its previous values. The solver's results are on the exception's .results.\n"
]
}
],
"source": [
"pulpo_worker_default.instantiate(choices=choices_unconstrained, demand=demand, lower_limit=lower_bound,\n",
" upper_imp_limit={climate: lowest_climate / 2})\n",
"try:\n",
" pulpo_worker_default.solve()\n",
"except SolveError as error:\n",
" print(f\"No solution: {error}\")"
]
},
{
"cell_type": "markdown",
"id": "c29b0289",
"metadata": {},
"source": [
"## 9. Dependent Constraints: Technology Coupling\n",
"\n",
"Real-world systems often require interdependent technology operation rules. PULPO's dependent constraints enable specification of relationships between different process scaling levels, allowing for operational constraints, market share limitations, or technology coupling requirements.\n",
"\n",
"**Use Cases:**\n",
"- Maximum renewable energy penetration limits\n",
"- Technology deployment ratios\n",
"- Supply chain coordination constraints\n",
"- Market share limitations\n",
"- Infrastructure coupling requirements"
]
},
{
"cell_type": "markdown",
"id": "1da9e902",
"metadata": {},
"source": [
"### 9.1 Market Penetration Constraint\n",
"\n",
"Implement a realistic constraint where wind electricity can constitute a maximum of 80% of total electricity production. This represents grid stability or market penetration limitations for renewable energy sources.\n",
"\n",
"**Constraint Formulation:**\n",
"- Wind electricity ≤ 0.8 × (Wind electricity + Gas electricity)\n",
"- Mathematical rearrangement: Wind ≤ 4 × Gas electricity\n",
"- Ensures renewable energy integration within practical bounds"
]
},
{
"cell_type": "code",
"execution_count": 40,
"id": "8b8dbe86",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Retrieved electricity technologies:\n",
" Wind electricity: wind electricity\n",
" Gas electricity: natural gas electricity\n",
"\n",
"Demand specification: 2 products\n"
]
}
],
"source": [
"# Configure PULPO worker for dependent constraints demonstration\n",
"methods_dependent = {\"('my project', 'climate change')\": 1, \"('my project', 'resources')\": 0}\n",
"pulpo_worker_dep = pulpo.PulpoOptimizer(project, database, methods_dependent)\n",
"pulpo_worker_dep.get_lci_data()\n",
"\n",
"# Retrieve electricity technologies specifically by name for clarity\n",
"wind_electricity = pulpo_worker_dep.retrieve_processes(processes=['wind electricity'])\n",
"gas_electricity = pulpo_worker_dep.retrieve_processes(processes=['natural gas electricity'])\n",
"\n",
"print(\"Retrieved electricity technologies:\")\n",
"print(f\" Wind electricity: {wind_electricity[0]['name']}\")\n",
"print(f\" Gas electricity: {gas_electricity[0]['name']}\")\n",
"\n",
"# Multi-product demand (1 kg methanol + 2 kg ozone)\n",
"demand_dep = {methanol_process[0]: 1, ozone_process[0]: 2}\n",
"print(f\"\\nDemand specification: {len(demand_dep)} products\")"
]
},
{
"cell_type": "code",
"execution_count": 41,
"id": "16653190",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Dependent constraint configuration:\n",
" Constraint: Wind electricity ≤ 4 × Gas electricity\n",
" Interpretation: Wind ≤ 80% of total electricity production\n",
" Technology choices: 3 categories available\n"
]
}
],
"source": [
"# Define dependent constraint: Wind ≤ 80% of total electricity\n",
"# Mathematical form: wind ≤ 4 × gas_electricity (derived from wind ≤ 0.8 × (wind + gas))\n",
"dependent_constraints = {\n",
" 'wind_penetration_limit': {\n",
" 'left': {wind_electricity[0]: 1}, # Wind electricity scaling\n",
" 'right': {gas_electricity[0]: 4} # 4 × Gas electricity scaling\n",
" }\n",
"}\n",
"\n",
"# Technology choices (allow both options)\n",
"choices_dep = {\n",
" \"Electricity\": {wind_electricity[0]: float('inf'), gas_electricity[0]: float('inf')},\n",
" \"Hydrogen\": {hydrogen_processes[0]: float('inf'), hydrogen_processes[1]: float('inf')},\n",
" \"Oxygen\": {oxygen_processes[0]: float('inf'), oxygen_processes[1]: float('inf')},\n",
"}\n",
"\n",
"# Lower bounds for physical feasibility\n",
"lower_bound_dep = {oxygen_byproduct[0]: 0}\n",
"\n",
"print(\"Dependent constraint configuration:\")\n",
"print(\" Constraint: Wind electricity ≤ 4 × Gas electricity\")\n",
"print(\" Interpretation: Wind ≤ 80% of total electricity production\")\n",
"print(f\" Technology choices: {len(choices_dep)} categories available\")"
]
},
{
"cell_type": "code",
"execution_count": 42,
"id": "a18c5ee2",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"🔄 Solving optimization with wind penetration constraint...\n",
"Creating Instance\n",
"Instance created\n",
"optimal solution found: 3.0636673756672597\n",
"Optimization problem solved using Highspy\n",
"✅ Optimization completed successfully!\n",
"\n",
"Active process scaling values:\n",
" natural gas extraction: 0.5270\n",
" natural gas electricity: 2.7738\n",
" wind electricity: 11.0952\n",
" water supply: 0.0017\n",
" O2 ASU: 0.4800\n",
" hydrogen electrolysis: 0.1900\n",
" O2-market: 1.5200\n",
" direct air capture: 1.3750\n",
" methanol synthesis: 1.0000\n",
" ozone production: 2.0000\n"
]
}
],
"source": [
"# Solve optimization with dependent constraints\n",
"print(\"🔄 Solving optimization with wind penetration constraint...\")\n",
"\n",
"pulpo_worker_dep.instantiate(\n",
" choices=choices_dep, \n",
" demand=demand_dep, \n",
" lower_limit=lower_bound_dep,\n",
" dependent_constraints=dependent_constraints\n",
")\n",
"\n",
"results_dep = pulpo_worker_dep.solve()\n",
"\n",
"# Extract scaling values for analysis\n",
"scaling_results = {}\n",
"for activity_name, process_id in pulpo_worker_dep.lci_data['process_map'].items():\n",
" if pulpo_worker_dep.instance.scaling_vector[process_id].value > 1e-6: # Only show active processes\n",
" scaling_results[activity_name[1]] = pulpo_worker_dep.instance.scaling_vector[process_id].value\n",
"\n",
"print(\"✅ Optimization completed successfully!\")\n",
"print(\"\\nActive process scaling values:\")\n",
"for process_name, scaling_value in scaling_results.items():\n",
" print(f\" {process_name}: {scaling_value:.4f}\")"
]
},
{
"cell_type": "code",
"execution_count": 43,
"id": "10745926",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"📊 CONSTRAINT VERIFICATION\n",
"Wind: 11.0952 | Gas: 2.7738 | Wind %: 80.0%\n",
"Constraint satisfied: True (wind ≤ 4×gas: 11.0952 ≤ 11.0952)\n",
"Climate impact: 3.0637\n"
]
}
],
"source": [
"# Verify constraint satisfaction and analyze electricity mix\n",
"wind_scaling = scaling_results.get('wind electricity', 0)\n",
"gas_scaling = scaling_results.get('natural gas electricity', 0)\n",
"total_electricity = wind_scaling + gas_scaling\n",
"\n",
"if total_electricity > 0:\n",
" wind_percentage = (wind_scaling / total_electricity) * 100\n",
" constraint_satisfied = wind_scaling <= (4 * gas_scaling + 1e-6)\n",
" climate_impact = pulpo_worker_dep.instance.impacts_calculated[\"('my project', 'climate change')\"].value\n",
" \n",
" print(f\"\\n📊 CONSTRAINT VERIFICATION\")\n",
" print(f\"Wind: {wind_scaling:.4f} | Gas: {gas_scaling:.4f} | Wind %: {wind_percentage:.1f}%\")\n",
" print(f\"Constraint satisfied: {constraint_satisfied} (wind ≤ 4×gas: {wind_scaling:.4f} ≤ {4*gas_scaling:.4f})\")\n",
" print(f\"Climate impact: {climate_impact:.4f}\")\n",
"else:\n",
" print(\"⚠️ No electricity production detected\")"
]
},
{
"cell_type": "markdown",
"id": "ec583a97",
"metadata": {},
"source": [
"## 10. Supply Specification: Fixing a Process Output\n",
"\n",
"All previous examples are *demand-driven*: a functional unit is specified and the system must deliver it. PULPO also supports *supply-driven* analysis. When a process is given **identical lower and upper limits**, its scaling is fixed to exactly that value, and PULPO automatically activates a **slack variable** for the corresponding reference product. The slack relaxes the product balance, so the fixed output does not need to be absorbed by a final demand — the question becomes:\n",
"\n",
"> *“What is the optimal system configuration (and what are its impacts) when this process runs at exactly this level?”*\n",
"\n",
"**Use Cases:**\n",
"- Assessing an existing plant operating at a known production level\n",
"- Impact accounting for a fixed production quota rather than a functional unit\n",
"- Analyzing systems where the output is determined by upstream availability (e.g., waste treatment capacity) instead of downstream demand"
]
},
{
"cell_type": "markdown",
"id": "43d8803a",
"metadata": {},
"source": [
"### 10.1 Supply-Driven Optimization: Fixed Methanol Output\n",
"\n",
"Fix the methanol synthesis process to a scaling of exactly 1 by passing the **same value as lower and upper limit**. No demand is specified — the fixed supply alone drives the system. The technology choices remain open, so the optimizer still selects the impact-minimal electricity, hydrogen, and oxygen sources needed to run the fixed process."
]
},
{
"cell_type": "code",
"execution_count": 44,
"id": "3ee3382d",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Creating Instance\n",
"Instance created\n",
"optimal solution found: 1.7471600582975855\n",
"Optimization problem solved using Highspy\n",
"Supply-driven climate impact: 1.747160\n"
]
}
],
"source": [
"# Configure a fresh worker for the supply-driven demonstration\n",
"methods_supply = {\"('my project', 'climate change')\": 1, \"('my project', 'resources')\": 0}\n",
"pulpo_worker_supply = pulpo.PulpoOptimizer(project, database, methods_supply)\n",
"pulpo_worker_supply.get_lci_data()\n",
"\n",
"# Identical lower and upper limit -> scaling is fixed and the supply slack is activated\n",
"methanol_supply = {methanol_process[0]: 1}\n",
"\n",
"# Technology choices remain open for the optimizer\n",
"choices_supply = {\n",
" \"Electricity\": {electricity_processes[0]: float('inf'), electricity_processes[1]: float('inf')},\n",
" \"Hydrogen\": {hydrogen_processes[0]: float('inf'), hydrogen_processes[1]: float('inf')},\n",
" \"Oxygen\": {oxygen_processes[0]: float('inf'), oxygen_processes[1]: float('inf')},\n",
"}\n",
"\n",
"# Note: no demand is passed!\n",
"pulpo_worker_supply.instantiate(\n",
" choices=choices_supply,\n",
" lower_limit={**methanol_supply, oxygen_byproduct[0]: 0},\n",
" upper_limit=methanol_supply,\n",
")\n",
"results_supply = pulpo_worker_supply.solve()\n",
"\n",
"supply_climate = pulpo_worker_supply.instance.impacts_calculated[\"('my project', 'climate change')\"].value\n",
"print(f\"Supply-driven climate impact: {supply_climate:.6f}\")"
]
},
{
"cell_type": "markdown",
"id": "41c980af",
"metadata": {},
"source": [
"#### Results Analysis: Slack Activation\n",
"\n",
"The slack variable exists **only** for the methanol product (the model carries no slack for any other product). Its value equals the fixed methanol output that is not consumed by any demand — the balance `production = demand + slack` closes with `demand = 0`, so the slack absorbs the full supply of 1."
]
},
{
"cell_type": "code",
"execution_count": 45,
"id": "225105fb",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Slack (exists only for the supply product):\n",
" Value\n",
"10 1.0\n",
"Methanol synthesis scaling (fixed): 1.0000\n"
]
}
],
"source": [
"# The slack absorbs the fixed methanol output that no demand consumes\n",
"slack = pulpo_worker_supply.extract_results()['Slack']\n",
"print(\"Slack (exists only for the supply product):\")\n",
"print(slack)\n",
"\n",
"methanol_id = pulpo_worker_supply.lci_data['process_map'][methanol_process[0].key]\n",
"print(f\"Methanol synthesis scaling (fixed): {pulpo_worker_supply.instance.scaling_vector[methanol_id].value:.4f}\")"
]
},
{
"cell_type": "markdown",
"id": "963f60eb",
"metadata": {},
"source": [
"### 10.2 Comparison with the Demand-Driven Formulation\n",
"\n",
"For this system the supply-driven and demand-driven formulations coincide: methanol is not consumed by any other process, so fixing the *gross* output of 1 is equivalent to demanding a *net* output of 1. In systems where the fixed product is also consumed internally, the two formulations differ — the supply specification fixes how much the process runs, while a demand fixes how much must be left over for the functional unit."
]
},
{
"cell_type": "code",
"execution_count": 46,
"id": "617eb1f7",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Creating Instance\n",
"Instance created\n",
"optimal solution found: 1.7471600582975855\n",
"Optimization problem solved using Highspy\n",
"Supply-driven (fixed output): 1.747160\n",
"Demand-driven (functional unit): 1.747160\n",
"Difference: 0.00e+00\n"
]
}
],
"source": [
"# Same 1 kg methanol as a conventional demand for comparison\n",
"pulpo_worker_supply.instantiate(\n",
" choices=choices_supply,\n",
" demand={methanol_process[0]: 1},\n",
" lower_limit={oxygen_byproduct[0]: 0},\n",
")\n",
"results_demand = pulpo_worker_supply.solve()\n",
"demand_climate = pulpo_worker_supply.instance.impacts_calculated[\"('my project', 'climate change')\"].value\n",
"\n",
"print(f\"Supply-driven (fixed output): {supply_climate:.6f}\")\n",
"print(f\"Demand-driven (functional unit): {demand_climate:.6f}\")\n",
"print(f\"Difference: {abs(supply_climate - demand_climate):.2e}\")"
]
},
{
"cell_type": "markdown",
"id": "f48ad6af",
"metadata": {},
"source": [
"## 11. Goal Programming: Average Transgression Level\n",
"\n",
"All previous examples minimize a (weighted) sum of impacts. In many policy-oriented settings — e.g. Planetary-Boundary assessments expressed through the EF 3.1 categories — the question is different: each impact category has a **budget that should not be transgressed**, but some transgression may be unavoidable. PULPO supports this as a goal-programming objective: for each category $h$ with a soft limit (goal) $L_h$, the transgression level is $TL_h = \\text{Impact}_h / L_h$, and the optimizer minimizes the **average transgression**\n",
"\n",
"$$\\min \\; \\frac{1}{K} \\sum_{h=1}^{K} \\max\\left(0, \\; TL_h - 1\\right)$$\n",
"\n",
"Categories within their budget contribute nothing; transgressed categories contribute proportionally to how far they exceed it. Unlike the hard `upper_imp_limit` constraints from Section 4, goals **can** be exceeded — the problem stays feasible and the solution reports *how much* each budget is blown.\n",
"\n",
"### 11.1 An (Invented) Regulatory Budget Scenario\n",
"\n",
"Suppose a regulator allocates the methanol producer a per-kg budget in all three impact categories (the numbers are made up for demonstration):\n",
"\n",
"| Category | Budget $L_h$ | Attainable minimum |\n",
"|---|---|---|\n",
"| climate change | 2.0 | 1.747 (climate-optimal solution) |\n",
"| air quality | 0.05 | 0.0 |\n",
"| resources | 0.001 | 0.00057 (resource-optimal solution) |\n",
"\n",
"The budgets are deliberately **conflicting**: the climate-optimal technology mix (wind + electrolysis) overshoots the resource budget by 71%, while the resource-optimal mix (gas + SMR) overshoots the climate budget by 73% and the air-quality budget as well. No corner solution satisfies everything — the goal objective must find the best compromise."
]
},
{
"cell_type": "code",
"execution_count": 47,
"id": "de4eedcd",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Creating Instance\n",
"Instance created\n",
"optimal solution found: 0.15903260059682106\n",
"Optimization problem solved using Highspy\n",
"Average transgression level: 0.1590\n"
]
}
],
"source": [
"# Fresh worker with ALL three impact categories (weights are ignored in goal mode)\n",
"methods_goal = {\n",
" \"('my project', 'climate change')\": 1,\n",
" \"('my project', 'air quality')\": 1,\n",
" \"('my project', 'resources')\": 1,\n",
"}\n",
"pulpo_worker_goal = pulpo.PulpoOptimizer(project, database, methods_goal)\n",
"pulpo_worker_goal.get_lci_data()\n",
"\n",
"# The invented per-kg-methanol budgets (soft limits)\n",
"imp_goals = {\n",
" \"('my project', 'climate change')\": 2.0,\n",
" \"('my project', 'air quality')\": 0.05,\n",
" \"('my project', 'resources')\": 0.001,\n",
"}\n",
"\n",
"# Same system as Section 3: 1 kg methanol, free technology choices\n",
"choices_goal = {\n",
" \"Electricity\": {electricity_processes[0]: float('inf'), electricity_processes[1]: float('inf')},\n",
" \"Hydrogen\": {hydrogen_processes[0]: float('inf'), hydrogen_processes[1]: float('inf')},\n",
" \"Oxygen\": {oxygen_processes[0]: float('inf'), oxygen_processes[1]: float('inf')},\n",
"}\n",
"\n",
"pulpo_worker_goal.instantiate(\n",
" choices=choices_goal,\n",
" demand={methanol_process[0]: 1},\n",
" lower_limit={oxygen_byproduct[0]: 0},\n",
" imp_goals=imp_goals,\n",
" objective='goal',\n",
")\n",
"results_goal = pulpo_worker_goal.solve()\n",
"print(f\"Average transgression level: {pulpo_worker_goal.instance.OBJ():.4f}\")"
]
},
{
"cell_type": "markdown",
"id": "9a6ccb5c",
"metadata": {},
"source": [
"### 11.2 Results Analysis: Budget Status and Compromise Mix\n",
"\n",
"`extract_results()` gains a **Transgressions** table (also shown by `summarize_results()` and exported by `save_results()`): per goal category the impact, the budget, the transgression level $TL$, and the transgression $\\max(0, TL-1)$."
]
},
{
"cell_type": "code",
"execution_count": 48,
"id": "4c78e8f0",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Impact \n",
" Goal \n",
" TL \n",
" Transgression \n",
" \n",
" \n",
" Method \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" ('my project', 'resources') \n",
" 0.001283 \n",
" 0.001 \n",
" 1.283437 \n",
" 0.283437 \n",
" \n",
" \n",
" ('my project', 'climate change') \n",
" 2.387322 \n",
" 2.000 \n",
" 1.193661 \n",
" 0.193661 \n",
" \n",
" \n",
" ('my project', 'air quality') \n",
" 0.050000 \n",
" 0.050 \n",
" 1.000000 \n",
" 0.000000 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Impact Goal TL Transgression\n",
"Method \n",
"('my project', 'resources') 0.001283 0.001 1.283437 0.283437\n",
"('my project', 'climate change') 2.387322 2.000 1.193661 0.193661\n",
"('my project', 'air quality') 0.050000 0.050 1.000000 0.000000"
]
},
"execution_count": 48,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"transgressions = pulpo_worker_goal.extract_results()[\"Transgressions\"]\n",
"transgressions"
]
},
{
"cell_type": "code",
"execution_count": 49,
"id": "3afb5dd5",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"## Total Impact(s)"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Weight \n",
" Value \n",
" \n",
" \n",
" Method \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" ('my project', 'air quality') \n",
" 1 \n",
" 0.050000 \n",
" \n",
" \n",
" ('my project', 'climate change') \n",
" 1 \n",
" 2.387322 \n",
" \n",
" \n",
" ('my project', 'resources') \n",
" 1 \n",
" 0.001283 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Weight Value\n",
"Method \n",
"('my project', 'air quality') 1 0.050000\n",
"('my project', 'climate change') 1 2.387322\n",
"('my project', 'resources') 1 0.001283"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"## Goal Transgressions"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Impact \n",
" Goal \n",
" TL \n",
" Transgression \n",
" \n",
" \n",
" Method \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" ('my project', 'resources') \n",
" 0.001283 \n",
" 0.001 \n",
" 1.283437 \n",
" 0.283437 \n",
" \n",
" \n",
" ('my project', 'climate change') \n",
" 2.387322 \n",
" 2.000 \n",
" 1.193661 \n",
" 0.193661 \n",
" \n",
" \n",
" ('my project', 'air quality') \n",
" 0.050000 \n",
" 0.050 \n",
" 1.000000 \n",
" 0.000000 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Impact Goal TL Transgression\n",
"Method \n",
"('my project', 'resources') 0.001283 0.001 1.283437 0.283437\n",
"('my project', 'climate change') 2.387322 2.000 1.193661 0.193661\n",
"('my project', 'air quality') 0.050000 0.050 1.000000 0.000000"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"## Choices Made"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Electricity"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Value \n",
" Capacity \n",
" \n",
" \n",
" Metadata \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" wind electricity | electricity | GLO \n",
" 9.215547 \n",
" inf \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Value Capacity\n",
"Metadata \n",
"wind electricity | electricity | GLO 9.215547 inf"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Hydrogen"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Value \n",
" Capacity \n",
" \n",
" \n",
" Metadata \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" hydrogen electrolysis | hydrogen | GLO \n",
" 0.118906 \n",
" inf \n",
" \n",
" \n",
" hydrogen SMR | hydrogen | GLO \n",
" 0.071094 \n",
" inf \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Value Capacity\n",
"Metadata \n",
"hydrogen electrolysis | hydrogen | GLO 0.118906 inf\n",
"hydrogen SMR | hydrogen | GLO 0.071094 inf"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Oxygen"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Value \n",
" Capacity \n",
" \n",
" \n",
" Metadata \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
"Empty DataFrame\n",
"Columns: [Value, Capacity]\n",
"Index: []"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"## Constraints"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"### Constraints Lower"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Key \n",
" Metadata \n",
" Value \n",
" Limit \n",
" \n",
" \n",
" ID \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" 7 \n",
" (foreground_db, O2-byproduct) \n",
" O2-byproduct | oxygen | GLO \n",
" 0.951249 \n",
" 0 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Key Metadata Value \\\n",
"ID \n",
"7 (foreground_db, O2-byproduct) O2-byproduct | oxygen | GLO 0.951249 \n",
"\n",
" Limit \n",
"ID \n",
"7 0 "
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"pulpo_worker_goal.summarize_results(zeroes=True)"
]
},
{
"cell_type": "markdown",
"id": "e6881123",
"metadata": {},
"source": [
"The compromise is qualitatively different from every weighted-sum solution seen so far:\n",
"\n",
"- **Hydrogen is blended**: the optimizer runs electrolysis *and* SMR side by side — a split that no single-objective run produces — because fully committing to either technology would blow one of the budgets much further.\n",
"- **Air quality sits exactly at its budget** ($TL = 1.0$, transgression 0): the SMR share is expanded precisely up to the point where the air-quality budget becomes binding at the kink of $\\max(0, TL-1)$.\n",
"- **Climate change and resources are both mildly transgressed** (≈ 19% and ≈ 28%) instead of one of them being blown by > 70%: the average transgression drops to ≈ 0.159, compared to ≈ 0.237 if the climate-optimal mix from Section 3 were assessed against the same budgets.\n",
"\n",
"Tightening or relaxing individual budgets shifts this balance — e.g. lowering the resource budget pushes the mix back towards SMR until the climate budget takes over as the binding concern.\n",
"\n",
"### 11.3 Yearly Budgets in the Time-Indexed Model\n",
"\n",
"The same objective is available in the time-indexed formulation (`pulpo_time.PulpoOptimizerTime`, see the `elec_time_toy` notebook). There the goals apply to the impacts **aggregated over all timesteps** — the natural fit for e.g. an hourly-resolved dispatch problem (8760 steps) with a *total yearly* budget per category:\n",
"\n",
"```python\n",
"worker = pulpo_time.PulpoOptimizerTime(project, database, methods)\n",
"worker.get_lci_data()\n",
"worker.instantiate(\n",
" choices=choices, demand=demand,\n",
" time_steps=list(range(8760)), # hourly resolution\n",
" imp_goals={gwp_method: yearly_co2_budget}, # budget on sum over all hours\n",
" objective='goal',\n",
")\n",
"worker.solve()\n",
"```\n",
"\n",
"The transgression of each category is then evaluated on $\\sum_t \\text{Impact}_{t,h}$, i.e. the optimizer is free to exceed the *hourly-average* budget in some hours as long as the yearly total works out."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.13"
}
},
"nbformat": 4,
"nbformat_minor": 5
}