Ga naar hoofdinhoud

Optimaliseren met Pyomo: een complete stapsgewijze gids

Leer hoe je optimalisatieproblemen modelleert en oplost met Pyomo, een krachtige Python-bibliotheek. Verken praktische voorbeelden uit lineaire en niet-lineaire optimalisatie!
· 15 min lezen

Verken met AI

Optimalisatie is een fundamenteel hulpmiddel dat in allerlei sectoren en disciplines wordt gebruikt om de best mogelijke beslissingen te nemen binnen gegeven randvoorwaarden. Of het nu gaat om kosten minimaliseren in een supply chain, efficiëntie maximaliseren in energiesystemen of de optimale parameters vinden in machinelearningmodellen, optimalisatietechnieken zijn onmisbaar. 

Python, bekend om zijn eenvoud en veelzijdigheid, biedt krachtige bibliotheken voor optimalisatieproblemen. Daarvan springt Pyomo eruit als een uitgebreide en flexibele bibliotheek waarmee je naadloos complexe optimalisatiemodellen kunt definiëren en oplossen.

In deze tutorial verkennen we Pyomo vanaf de basis. We behandelen alles: van het installeren en instellen van solvers tot het formuleren en oplossen van verschillende optimalisatieproblemen!

An image visualization feasible region, constraints, and corner points in a linear programming optimization problem

De oplossingsruimte in lineaire programmering verkennen. Afbeelding door de auteur.

Wat is Pyomo?

Pyomo is een open-sourcebibliotheek voor het bouwen en oplossen van optimalisatiemodellen met Python. Je kunt optimalisatiemodellen definiëren op een manier die zowel wiskundig rigoureus is als syntactisch intuïtief voor Python-programmeurs. Het ondersteunt een breed scala aan probleemtypen, waaronder:

  1. Lineaire programmering (LP): LP draait om het optimaliseren van een lineaire doelfunctie onderworpen aan lineaire gelijkheids- en ongelijkheidsrestricties. Het wordt veel gebruikt voor probleemstellingen rond toewijzing van middelen, planning en financiële planning.
  2. Niet-lineaire programmering (NLP): NLP behandelt het optimaliseren van een niet-lineaire doelfunctie met niet-lineaire restricties. Het wordt vaak gebruikt in techniek en economie voor complexere systemen waarin relaties niet lineair zijn.
  3. Gemengd-gehele getallen programmeren (MIP): MIP omvat optimalisatieproblemen waarbij sommige variabelen integer moeten zijn terwijl andere continu mogen zijn. Dit is nuttig in scenario’s zoals supply chain-ontwerp of projectscheduling, waar beslissingen discreet kunnen zijn (bijv. aan/uit).
  4. Stochastische programmering: Stochastische programmering pakt optimalisatieproblemen aan waarbij sommige elementen onzeker zijn en als willekeurige variabelen worden gemodelleerd. Het wordt veel toegepast in finance en supply chain management om beslissingen onder onzekerheid te optimaliseren.
  5. Dynamische optimalisatie: Dynamische optimalisatie focust op het optimaliseren van beslissingsvariabelen in de tijd, meestal bij dynamisch evoluerende systemen. Het wordt gebruikt in bijvoorbeeld procesbesturing, robotica en economie om tijdsafhankelijke processen te sturen.

Functies van Pyomo

Nu we Pyomo beter begrijpen, bekijken we enkele van de belangrijkste functies. 

Flexibiliteit en uitbreidbaarheid

Pyomo’s flexibiliteit komt voort uit het vermogen om complexe relaties te modelleren met standaard Python-constructies. Het integreert met verschillende open-source- en commerciële solvers, waardoor je veel optimalisatieproblemen eenvoudig kunt oplossen. 

Pythonic syntax

Pyomo-modellen zijn gebouwd op Python en geschreven met standaard Python-syntax. Dit maakt de leercurve mild voor wie vertrouwd is met Python en laat je gebruikmaken van de uitgebreide Python-bibliotheken binnen je modellen.

Sterke community en documentatie

Pyomo heeft een sterke gebruikerscommunity en uitgebreide documentatie, inclusief voorbeelden en tutorials voor gebruikers op elk niveau.

Use-cases voor Pyomo

Pyomo kent een breed scala aan toepassingen in de praktijk. Enkele voorbeelden:

1. Supply chain-optimalisatie

Supply chain-optimalisatie omvat het verbeteren van logistiek, het beheren van voorraden en het opstellen van efficiënte productieplanningen. 

Dit kan inhouden: transportkosten minimaliseren, magazijnlocaties optimaliseren of vraag en aanbod in balans brengen. 

Zo kan een bedrijf klantvraag in meerdere regio’s willen bedienen, met minimale verzendkosten en voldoende voorraad in elk distributiecentrum.

2. Financiële modellering

In financiële modellering helpt optimalisatie om middelen, zoals kapitaal, zo te alloceren dat het rendement wordt gemaximaliseerd en het risico geminimaliseerd. 

Dit kan gaan om portefeuille-optimalisatie, waarbij beleggers risico en rendement afwegen door een combinatie van activa te kiezen onder beperkingen zoals budgetten, regelgeving of risicotolerantie. 

Financiële modellering zorgt ervoor dat financiële strategieën aansluiten op langetermijndoelen, terwijl potentiële risico’s worden beperkt.

3. Energiesystemen

Optimalisatie in energiesystemen richt zich op het maximaliseren van efficiëntie in opwekking, distributie en verbruik.

Dit kan betekenen: de optimale mix van energiebronnen bepalen (bijv. hernieuwbaar vs. niet-hernieuwbaar) terwijl brandstofkosten worden geminimaliseerd, emissielimieten worden gehaald en wordt ingespeeld op schommelende vraag. 

Dit type optimalisatie speelt een centrale rol in netbeheer, centrales en het verminderen van milieu-impact.

4. Machine learning en data science

Optimalisatie staat centraal in veel machine learning- en datasciencetaken, zoals hyperparametertuning en featureselectie. 

Bij hyperparametertuning helpen optimalisatie-algoritmen de beste modelconfiguratie te vinden om de voorspellende prestaties te verbeteren. 

Featureselectie, een andere cruciale taak, draait om het identificeren van de belangrijkste features die bijdragen aan de nauwkeurigheid van een model, wat de complexiteit verlaagt en de efficiëntie verbetert.

Nu de context duidelijk is, gaan we hands-on aan de slag en passen we Pyomo toe op enkele voorbeeldmodellen!

Pyomo instellen

Voordat we gaan modelleren, moeten we onze omgeving inrichten door Pyomo te installeren en een geschikte solver te kiezen.

1. Vereisten

Om pyomo te gebruiken, heb je Python 3.6 of hoger nodig. Pyomo kan met pip worden geïnstalleerd.

pip install pyomo

Deze tutorial is gemaakt met pyomo-versie 6.8.0.

import pyomo
print(pyomo.__version__)

Output:

>>> 6.8.0

2. De juiste solver kiezen en installeren

Bij optimalisatie zijn solvers essentieel: dit zijn de algoritmen die de optimale oplossing vinden voor het gedefinieerde probleem. Afhankelijk van het type probleem (bijv. lineair, niet-lineair, integer) zijn verschillende solvers beter geschikt. Pyomo is een modelleertool die vertrouwt op externe solvers voor de eigenlijke berekening.

Laten we enkele van de meest gebruikte solvers doornemen.

Open-source solvers

1. GLPK (GNU Linear Programming Kit)

GLPK is een populaire tool voor het oplossen van lineaire programmerings- (LP) en gemengd-gehele getallen- (MIP) problemen. 

Het is een uitstekende keuze voor basis lineaire optimalisatietaken en wordt veel gebruikt in academische en industriële toepassingen.

Installatie

brew install glpk
  • Linux: 
sudo apt-get install glpk-utils
2. CBC (Coin-or Branch and Cut)

CBC is een open-source solver voor LP- en MIP-problemen. 

Het biedt geavanceerde functies en in sommige gevallen betere prestaties dan GLPK, wat het een sterke optie maakt voor complexere optimalisatietaken. 

CBC kan worden geïnstalleerd via de conda package manager.

conda install -c conda-forge coincbc
3. IPOPT (Interior Point OPTimizer)

IPOPT is een krachtige solver ontworpen voor grootschalige niet-lineaire programmeringsproblemen (NLP). 

Het is bijzonder geschikt voor complexe, niet-lineaire modellen en daarmee een uitstekende keuze voor problemen buiten lineaire optimalisatie. 

IPOPT kan worden geïnstalleerd via de conda package manager.

!conda install -c conda-forge ipopt

Commerciële solvers

1. CPLEX

CPLEX is een state-of-the-art optimalisatiesolver die efficiënt LP-, MIP- en QP-problemen aankan. 

Hiervoor is een IBM-licentie vereist, maar voor academische gebruikers is het gratis beschikbaar, wat het een uitstekende keuze maakt voor onderzoek en onderwijs.

2. Gurobi

Gurobi is een toonaangevende commerciële solver die bekendstaat om snelheid en efficiëntie bij het oplossen van LP-, MIP-, QP- en niet-lineaire (NLP) problemen. 

Net als CPLEX vereist het een licentie maar biedt het gratis toegang voor academische gebruikers. Het is dus een industriestandaard voor geavanceerde optimalisatie.

Open-source vs. commerciële solvers

Open-source solvers zoals GLPK en CBC zijn gratis en voldoen aan de meeste basisbehoeften. Ze zijn uitstekende keuzes voor kleinschalige projecten en educatieve doeleinden. 

Commerciële solvers zoals CPLEX en Gurobi bieden echter doorgaans superieure prestaties, vooral voor grotere, complexere problemen. Deze solvers beschikken over geavanceerde functies, waaronder betere ondersteuning voor kwadratische en niet-lineaire programmering, en zijn geoptimaliseerd voor grootschalige industriële toepassingen.

Hoewel open-source solvers veel routine-optimalisatietaken aankunnen, zijn commerciële solvers vaak de betere keuze bij complexere vereisten met hoge prestatie-eisen. 

Houd er rekening mee dat commerciële solvers een licentie vereisen, al zijn ze gratis beschikbaar voor academische gebruikers.

Laten we nu bekijken hoe je een solver in Pyomo configureert. Ik gebruik hier GLPK. 

3. Een solver configureren in Pyomo

Zorg er eerst voor dat het uitvoerbare bestand van de solver na installatie in je systeem-PATH staat. 

Maak daarna een Python-script en voeg het volgende toe:

from pyomo.environ import SolverFactory
solver = SolverFactory('glpk')

Om te bevestigen dat zowel Pyomo als je solver correct zijn geïnstalleerd, lossen we een eenvoudige testopgave op.

Testprobleem: eenvoudige lineaire programmatie

Doel: Minimaliseer Z=x+y

Onder restricties:

  • x + 2y ≥ 4
  • x - y ≤ 1
  • x ≥ 0
  • y ≥ 0

Dit probleem gaat om het vinden van de kleinst mogelijke waarde van Z, de som van twee variabelen, x en y.

Ten eerste moet x plus tweemaal y minstens 4 zijn. Ten tweede moet x min y kleiner dan of gelijk aan 1 zijn. Tot slot moeten zowel x als y nul of positief zijn (niet negatief). 

Het doel is waarden voor x en y te vinden die aan deze voorwaarden voldoen en Z zo klein mogelijk maken.

Implementatie met Pyomo:

import pyomo.environ as pyo
# Create a model
model = pyo.ConcreteModel()
# Define variables
model.x = pyo.Var(within=pyo.NonNegativeReals)
model.y = pyo.Var(within=pyo.NonNegativeReals)
# Define objective
model.obj = pyo.Objective(expr=model.x + model.y, sense=pyo.minimize)
# Define constraints
model.con1 = pyo.Constraint(expr=model.x + 2 * model.y >= 4)
model.con2 = pyo.Constraint(expr=model.x - model.y <= 1)
# Select solver
solver = pyo.SolverFactory('glpk')
# Solve the problem
result = solver.solve(model)
# Display results
print('Status:', result.solver.status)
print('Termination Condition:', result.solver.termination_condition)
print('Optimal x:', pyo.value(model.x))
print('Optimal y:', pyo.value(model.y))
print('Optimal Objective:', pyo.value(model.obj))

Als alles correct werkt, is de verwachte output:

Status: ok
Termination Condition: optimal
Optimal x: 0.0
Optimal y: 2.0
Optimal Objective: 2.0

Laten we de code doorlopen: eerst definieert deze twee variabelen, x en y, die alleen niet-negatieve waarden mogen aannemen. De doelstelling van het model is de som van x en y (x + y) te minimaliseren. De code definieert de solver als glpk om de optimale waarden van x en y te vinden die aan de restricties voldoen en de doelstelling minimaliseren.

Na het uitvoeren blijken de optimale waarden voor de variabelen x = 0.0 en y = 2.0 te zijn, wat de doelfunctie Z = x + y minimaliseert. De minimale waarde van de doelfunctie is dus 2.0, en dit voldoet aan de gegeven restricties.

Basis van modelleren met Pyomo

Om optimalisatieproblemen effectief op te zetten en op te lossen in Pyomo, is het nodig om de basisonderdelen van een optimalisatiemodel te kunnen definiëren.

1. Variabelen definiëren

Variabelen vertegenwoordigen de beslissingen die in een optimalisatieprobleem genomen moeten worden. In Pyomo zijn variabelen de grootheden die de solver aanpast om de doelfunctie te optimaliseren binnen alle restricties.

Scalairen

Een scalair is een enkele variabele die niet is geïndexeerd over een set. Om in Pyomo een scalair te definiëren, gebruik je de klasse Var uit het module pyomo.environ.

from pyomo.environ import Var
model.x = Var()

We importeren eerst Var en maken een variabele x met Var(). Deze variabele heeft geen grenzen, dus kan elke reële waarde aannemen, tenzij elders in het model beperkt.

Grenzen toevoegen

Je kunt beperken welke waarden een variabele mag aannemen door grenzen te specificeren. Grenzen worden gedefinieerd als een tuple (ondergrens, bovengrens):

from pyomo.environ import Var
model.x = Var(bounds=(0, None))

Domeinen specificeren

Pyomo biedt vooraf gedefinieerde domeinen om aan te geven welk type waarden een variabele mag aannemen, zoals NonNegativeReals, Integers of Binary: 

from pyomo.environ import Var, NonNegativeReals
model.x = Var(domain=NonNegativeReals)

Geïndexeerde variabelen

Als je te maken hebt met meerdere vergelijkbare variabelen, zoals variabelen per periode of per item, is het efficiënt om geïndexeerde variabelen te gebruiken. Geïndexeerde variabelen zijn gedefinieerd over een set.

import pyomo.environ as pyo
model.I = pyo.Set(initialize=[1, 2, 3])
model.y = pyo.Var(model.I, domain=pyo.NonNegativeReals)

Stel dat je de productiehoeveelheden voor drie producten modelleert. Dan kun je definiëren:

model.Products = pyo.Set(initialize=['A', 'B', 'C'])
model.production = pyo.Var(model.Products, domain=pyo.NonNegativeReals)

Nu staan model.production['A'], model.production['B'] en model.production['C'] voor de productiehoeveelheden van respectievelijk product A, B en C.

2. Doelfuncties definiëren

De doelfunctie is wat we proberen te optimaliseren (minimaliseren of maximaliseren). Het definieert het doel van het model, zoals kosten minimaliseren of winst maximaliseren, en wordt meestal uitgedrukt als een wiskundige vergelijking met de beslissingsvariabelen. 

Deze worden gedefinieerd met de klasse Objective:

from pyomo.environ import ConcreteModel, Var, Objective, minimize, maximize, NonNegativeReals
# Create a model
model = ConcreteModel()
# Define variables
model.x = Var(within=NonNegativeReals)
model.y = Var(within=NonNegativeReals)
# Minimization (cost)
model.cost = Objective(expr=2 * model.x + 3 * model.y, sense=minimize)
# When Maximization profit - (can have one objective at a time)
# model.profit = Objective(expr=5 * model.x + 4 * model.y, sense=maximize)

3. Restricties toevoegen

Restricties definiëren de beperkingen of vereisten van het probleem:

from pyomo.environ import Constraint
model.con1 = Constraint(expr=model.x + model.y >= 10)

Bovenstaand voorbeeld definieert een restrictie in het Pyomo-model met de klasse Constraint. De restrictie model.con1 specificeert dat de som van de variabelen x en y groter dan of gelijk aan 10 moet zijn.

4. Modellen parametriseren

Parameters zijn vaste waarden in het model die bekende grootheden of constanten vertegenwoordigen en tijdens het optimalisatieproces niet veranderen. 

Ze helpen de relaties tussen variabelen en restricties te definiëren en geven structuur aan het model door echte data of aannames op te nemen:

from pyomo.environ import Param
model.p = Param(initialize=5)

De bovenstaande code definieert een parameter p in het Pyomo-model met de klasse Param en initialiseert deze met de vaste waarde 5. De parameter p kan nu in het model worden gebruikt als constante waarde die tijdens de optimalisatie niet verandert.

Nu gaan we aan de slag met een end-to-end optimalisatieprobleem!

Pyomo end-to-end voorbeeld

Laten we een end-to-end voorbeeld bekijken van het oplossen van een optimalisatieprobleem met Pyomo. We modelleren een realistisch scenario waarin een fabriek twee producten maakt en de winst wil maximaliseren, rekening houdend met machine-uren.

1. Probleembeschrijving

Een fabriek produceert twee producten, P1 en P2. De winst per eenheid is:

  • P1: $40
  • P2: $50

Beschikbare machine-uren:

  • Machine A: 100 uur
  • Machine B: 80 uur
  • Machine C: 90 uur

Benodigde tijd per eenheid:

Product

Machine A (uur)

Machine B (uur)

Machine C (uur)

P1

1

2

0

P2

2

1

3

Doel: Maximaliseer de winst.

Beslissingsvariabelen:

  • x₁: Aantal te produceren eenheden van P1.
  • x₂: Aantal te produceren eenheden van P2.

2. Wiskundige formulering

Doelfunctie:

Maximaliseer Z = 40x₁ + 50x₂

Restricties:

  1. Capaciteit A: 1x₁ + 2x₂ ≤ 100
  2. Capaciteit B: 2x₁ + 1x₂ ≤ 80
  3. Capaciteit C: 3x₂ ≤ 90
  4. Niet-negativiteit: x₁, x₂ ≥ 0

3. Implementatie

Op basis van het doel en de restricties van het probleem volgt hier de Python-code om het te modelleren, opnieuw met GLPK.

# Step 1: Import Libraries
import pyomo.environ as pyo
# Step 2: Create a Concrete Model
model = pyo.ConcreteModel()
# Step 3: Define Decision Variables (Units of P1 and P2 to produce)
model.x1 = pyo.Var(within=pyo.NonNegativeReals)
model.x2 = pyo.Var(within=pyo.NonNegativeReals)
# Step 4: Define the Objective Function (Maximize profit)
model.profit = pyo.Objective(expr=40 * model.x1 + 50 * model.x2, sense=pyo.maximize)
# Step 5: Define Constraints
# Machine A capacity constraint: 1x1 + 2x2 <= 100
model.machine_a = pyo.Constraint(expr=1 * model.x1 + 2 * model.x2 <= 100)
# Machine B capacity constraint: 2x1 + 1x2 <= 80
model.machine_b = pyo.Constraint(expr=2 * model.x1 + 1 * model.x2 <= 80)
# Machine C capacity constraint: 3x2 <= 90
model.machine_c = pyo.Constraint(expr=3 * model.x2 <= 90)
# Step 6: Solve the Model using GLPK solver
solver = pyo.SolverFactory('glpk')
result = solver.solve(model)
# Step 7: Analyze Results
# Display Solver Status and Termination Condition
print('Solver Status:', result.solver.status)
print('Termination Condition:', result.solver.termination_condition)
# Get and display the optimal values for x1, x2, and the maximum profit
x1_opt = pyo.value(model.x1)
x2_opt = pyo.value(model.x2)
profit_opt = pyo.value(model.profit)
print(f'Optimal production of P1 (x1): {x1_opt}')
print(f'Optimal production of P2 (x2): {x2_opt}')
print(f'Maximum Profit: ${profit_opt}')

Output:

>>> Solver Status: ok
>>> Termination Condition: optimal
>>> Optimal production of P1 (x1): 25.0
>>> Optimal production of P2 (x2): 30.0
>>> Maximum Profit: $2500.0

In de bovenstaande code definiëren we een lineair optimalisatiemodel om de winst uit de productie van twee producten (P1 en P2) te maximaliseren. De doelfunctie maximaliseert winst: elke eenheid P1 levert $40 op en elke eenheid P2 $50.

We leggen drie restricties op die de beschikbare machine-uren voor machines A, B en C representeren. 

Tot slot lossen we het probleem op met de GLPK-solver. 

Het eindoordeel is dat je 25 eenheden P1 en 30 eenheden P2 produceert, waarmee de maximale winst $2.500 bedraagt.

Geavanceerde functies in Pyomo

In de vorige sectie zagen we hoe eenvoudig het is om een end-to-end optimalisatieprobleem met Pyomo te implementeren. In de praktijk zijn problemen echter vaak minder rechttoe rechtaan.

In deze sectie laat ik enkele geavanceerde functies zien die je kunt gebruiken voor complexere scenario’s.

1. Niet-lineaire optimalisatie

Niet-lineaire optimalisatie minimaliseert of maximaliseert een niet-lineaire doelfunctie onder niet-lineaire restricties. We bekijken een voorbeeld waarin we de som van kwadratische afwijkingen minimaliseren onder een cirkelrestrictie.

Probleembeschrijving

Minimaliseer de doelfunctie: Z = (x - 1)² + (y - 2)²

Onder restricties:

  • x² + y² ≤ 4
  • x, y ≥ 0

In Pyomo kunnen we de beslissingsvariabelen x en y met ondergrens 0 definiëren om niet-negativiteit te waarborgen. De doelfunctie is de som van de gekwadrateerde afwijkingen van specifieke punten, en de restrictie zorgt dat de oplossing binnen een cirkel met straal 2 ligt.

In dit geval is de IPOPT-solver geschikt vanwege zijn vermogen om niet-lineaire optimalisatieproblemen op te lossen:

import pyomo.environ as pyo
model = pyo.ConcreteModel()
# Define variables with lower bounds
model.x = pyo.Var(bounds=(0, None))
model.y = pyo.Var(bounds=(0, None))
# Objective function: minimize (x - 1)² + (y - 2)²
model.obj = pyo.Objective(expr=(model.x - 1)**2 + (model.y - 2)**2, sense=pyo.minimize)
# Constraint: x² + y² ≤ 4 (circle of radius 2)
model.circle = pyo.Constraint(expr=model.x**2 + model.y**2 <= 4)
solver = pyo.SolverFactory('ipopt')
result = solver.solve(model)
print('Optimal x:', pyo.value(model.x))
print('Optimal y:', pyo.value(model.y))
print('Minimum Z:', pyo.value(model.obj))

2. Gemengd-gehele getallen (MIP)

Gemengd-gehele getallen programmeren gebruik je wanneer sommige beslissingsvariabelen integer (vaak binair) zijn en andere continu. Het is waardevol voor besluitvormingsproblemen zoals locatiekeuze en productieplanning.

Probleembeschrijving

Een bedrijf moet beslissen of het magazijnen opent op locaties A, B en C. Het doel is de totale kosten te minimaliseren, inclusief vaste openingskosten en transportkosten.

We beginnen met het initialiseren van de data, inclusief vaste kosten voor opening, transportkosten, capaciteitslimieten en totale vraag: 

locations = ['A', 'B', 'C']
FixedCost = {'A': 1000, 'B': 1200, 'C': 1500}
TransportCost = {'A': 5, 'B': 4, 'C': 6}
Capacity = {'A': 100, 'B': 80, 'C': 90}
Demand = 150
model = pyo.ConcreteModel()
# Binary variable: 1 if warehouse is open, 0 otherwise
model.y = pyo.Var(locations, domain=pyo.Binary)
# Continuous variable: amount of goods transported
model.x = pyo.Var(locations, domain=pyo.NonNegativeReals)
model.cost = pyo.Objective(
    expr=sum(FixedCost[i] * model.y[i] + TransportCost[i] * model.x[i] for i in locations),
    sense=pyo.minimize
)
# Demand constraint
model.demand = pyo.Constraint(expr=sum(model.x[i] for i in locations) >= Demand)
# Capacity constraints
def capacity_rule(model, i):
    return model.x[i] <= Capacity[i] * model.y[i]
model.capacity = pyo.Constraint(locations, rule=capacity_rule)
solver = pyo.SolverFactory('cbc')
result = solver.solve(model)
for i in locations:
    print(f"Warehouse {i}: Open={pyo.value(model.y[i])}, Transported={pyo.value(model.x[i])}")
print('Minimum Total Cost:', pyo.value(model.cost))

Het model bevat twee soorten beslissingsvariabelen: een binaire variabele y die aangeeft of een magazijn open is (1 als open, 0 anders), en een continue variabele x die de hoeveelheid getransporteerde goederen per magazijn representeert. 

De doelfunctie telt per magazijn de vaste kosten en transportkosten op en minimaliseert het totaal. De restricties zorgen dat aan de totale vraag wordt voldaan en dat de capaciteit van elk open magazijn niet wordt overschreden. 

3. Omgaan met meerdere doelen

Soms bevatten optimalisatieproblemen meerdere, mogelijk conflicterende doelen, zoals winst maximaliseren en milieu-impact minimaliseren. Een veelgebruikte aanpak is de gewogen som-methode, waarbij elk doel een gewicht krijgt naar belang.

Probleembeschrijving

We willen winst maximaliseren en milieu-impact minimaliseren:

  • Winst: Z₁ = 3x + 5y
  • Milieu-impact: Z₂ = 2x + y

We kunnen deze doelen combineren met gewichten w1=0.6, w2=0.4, waarbij het totale doel een gewogen som wordt:

w1 = 0.6
w2 = 0.4
model.obj = pyo.Objective(
    expr=w1 * (3 * model.x + 5 * model.y) - w2 * (2 * model.x + model.y),
    sense=pyo.maximize
)

In deze gecombineerde doelfunctie maximaliseren we winst en minimaliseren we milieu-impact door de gewichten te variëren.

4. Externe databronnen gebruiken

Bij grote datasets is het vaak handig om data uit externe bronnen zoals CSV-bestanden te importeren. Pyomo werkt goed samen met Pandas om externe data in te lezen en te gebruiken.

We kunnen een CSV inlezen met Pandas en de data gebruiken om sets en parameters in ons model te initialiseren:

import pandas as pd
data = pd.read_csv('parameters.csv')
# Define set from CSV data
model.I = pyo.Set(initialize=data['index'].unique())
# Define parameter initialized from CSV data
param_dict = data.set_index('index')['value'].to_dict()
model.param = pyo.Param(model.I, initialize=param_dict)

Tips en best practices voor Pyomo

Wanneer je met Pyomo werkt, is het belangrijk je modellen efficiënt, goed gedocumenteerd en eenvoudig te troubleshooten te houden. 

1. Debuggen en troubleshooten

Bij het bouwen van optimalisatiemodellen in Pyomo kom je vaak issues tegen, zoals onhaalbare oplossingen, solverfouten of onjuiste resultaten. Enkele best practices voor debuggen:

  • Controleer restricties: Als je model geen haalbare oplossing geeft, bekijk dan je restricties. Te strakke restricties kunnen een probleem onhaalbaar maken. Gebruik Pyomo’s .display()-methode om waarden van variabelen en restricties te printen en te verifiëren dat ze zich gedragen zoals verwacht.
  • Solveroutput: Schakel gedetailleerde solverlogs in door tee=True mee te geven aan de solve()-methode. Dit kan inzicht geven waar de solver moeite mee heeft, zoals onbegrensde variabelen of onhaalbaarheid.
  • Test eerst eenvoudige modellen: Test bij complexe modellen eerst een vereenvoudigde variant. Zo kun je mogelijke problemen isoleren zonder de overhead van een volledig gespecificeerd model.

Troubleshooten gaat veel makkelijker als je het systematisch aanpakt en restricties, doelfunctie en solverfeedback analyseert.

2. Modellefficiëntie

Optimalisatieproblemen kunnen computationeel duur worden naarmate het model groter wordt. Voor efficiënte modellering, overweeg het volgende:

  • Gebruik sparsity: Vermijd onnodige lussen over indexen bij het definiëren van restricties of doelen. Profiteer van de schaarste (sparsity) in je probleem om rekentijd te verminderen.
  • Binaire vs. continue variabelen: Verminder waar mogelijk het aantal binaire of integer variabelen. Continue variabelen zijn eenvoudiger voor solvers en leiden tot snellere oplossingen.
  • Formulering van restricties: Houd restricties zo simpel mogelijk, zowel wiskundig als in implementatie. Vermijd onnodige niet-lineariteiten en splits complexe restricties op in kleinere, beheersbare delen.

Efficiënte modellen lossen sneller op en zijn makkelijker te debuggen en te onderhouden.

3. Documentatie en onderhoud

Goed gedocumenteerde Pyomo-modellen zijn een goede gewoonte voor langdurig gebruik en samenwerking. Goede documentatie maakt het ook makkelijker om modellen later te herzien en bij te werken:

  • Gebruik inline commentaar: Voeg altijd commentaar toe om het doel van variabelen, restricties en de doelfunctie uit te leggen. Dit is vooral belangrijk bij optimalisatiemodellen waarvan de logica niet meteen duidelijk is.
  • Modulariseer je code: Verdeel je model in logische secties of zelfs aparte functies. Deze modulaire aanpak verbetert de leesbaarheid en maakt het makkelijker om specifieke delen te debuggen en aan te passen.
  • Houd modelwijzigingen bij: Houd een versieschema bij, zeker als het model evolueert. Gebruik versiebeheer zoals Git om wijzigingen te tracken en te zorgen dat updates of verbeteringen herleidbaar zijn.

Goede documentatie en gestructureerde code maken je Pyomo-modellen toegankelijker voor toekomstige samenwerkingen en eenvoudiger schaalbaar of aanpasbaar als je behoeften veranderen.

Conclusie

Pyomo is een krachtig en flexibel hulpmiddel voor het bouwen en oplossen van optimalisatiemodellen in Python. In deze tutorial zagen we hoe Pyomo gebruikers in staat stelt uiteenlopende optimalisatieproblemen te modelleren, van lineaire programmering tot niet-lineair en gemengd-gehele getallen.

Dankzij de gebruiksvriendelijke syntax en integratie met solvers maakt Pyomo het formuleren en oplossen van realistische optimalisatieproblemen toegankelijk voor zowel beginners als gevorderden.

Wil je meer leren over het oplossen van echte problemen met optimalisatie? Bekijk dan de gratis cursus Introduction to Optimization in Python op DataCamp!

FAQs

Waarvoor wordt Pyomo gebruikt?

Pyomo is een open-source Python-bibliotheek voor het definiëren en oplossen van complexe optimalisatieproblemen, waaronder lineaire, niet-lineaire en gemengd-gehele getallen programmering.

Hoe installeer ik Pyomo en de bijbehorende solvers?

Je kunt Pyomo installeren met pip install pyomo. Solvers zoals GLPK en CBC kun je installeren via pakketbeheerders zoals Homebrew, apt-get of Conda.

Welke soorten optimalisatieproblemen kan Pyomo oplossen?

 Pyomo ondersteunt een breed scala aan optimalisatieproblemen, waaronder lineaire programmering (LP), niet-lineaire programmering (NLP), gemengd-gehele getallen (MIP) en stochastische programmering.

Kan ik Pyomo gebruiken voor toepassingen in de praktijk, zoals supply chain-optimalisatie?

Ja, Pyomo wordt veel gebruikt voor toepassingen in de praktijk, zoals supply chain-optimalisatie, financiële modellering, optimalisatie van energiesystemen en machinelearningtaken.

Wat is het verschil tussen open-source en commerciële solvers in Pyomo?

Open-source solvers zoals GLPK en CBC zijn gratis en volstaan voor veel problemen, terwijl commerciële solvers zoals Gurobi en CPLEX betere prestaties en geavanceerde functies bieden voor complexere, grootschalige optimalisatietaken.

Moez Ali

Auteur

Moez Ali

Data scientist, oprichter en maker van PyCaret

Onderwerpen

Gerelateerd