20
is y s Institut für Systemdynamik Univ.-Prof. Dr.-Ing. Dr. h. c. O. Sawodny JuMP-Kurzbeschreibung Dr.-Ing. Eckhard Arnold Universität Stuttgart Institut für Systemdynamik Waldburgstr. 17/19 D-70563 Stuttgart E-Mail: [email protected] Tel.: +49 (0)711/685-65928 Fax: +49 (0)711/685-66371 23. März 2020

JuMP-Kurzbeschreibung - Uni Stuttgart€¦ · JuMP-Kurzbeschreibung Dr.-Ing. Eckhard Arnold Universität Stuttgart Institut für Systemdynamik Waldburgstr. 17/19 D-70563 Stuttgart

  • Upload
    others

  • View
    8

  • Download
    0

Embed Size (px)

Citation preview

  • isys Institut für SystemdynamikUniv.-Prof. Dr.-Ing. Dr. h. c. O. Sawodny

    JuMP-Kurzbeschreibung

    Dr.-Ing. Eckhard Arnold

    Universität StuttgartInstitut für Systemdynamik

    Waldburgstr. 17/19D-70563 Stuttgart

    E-Mail: [email protected].: +49 (0)711/685-65928Fax: +49 (0)711/685-66371

    23. März 2020

    mailto:[email protected]

  • Inhaltsverzeichnis

    Inhaltsverzeichnis

    1 Übersicht 3

    2 Sprachbeschreibung 4

    3 Solver 6

    4 Installation 7

    5 Beispiel: Problem von Rosenbrock 10

    6 Beispiel: Transportproblem 11

    7 Beispiel: Optimalsteuerung van der Pol-Oszillator 14

    Literatur 20

    2

  • 1 Übersicht

    1 Übersicht

    JuMP (siehe https://github.com/JuliaOpt/JuMP.jl und [7], [4]) ist eine algebraische Model-lierungssprache für lineare, quadratische, gemischt-ganzzahlige und nichtlineare Optimierungspro-bleme, die die Formulierung von Optimierungsproblemen („mathematische Modelle“) in einer ab-strakten, der algebraischen Notation recht nahen Form ermöglicht. JuMP ist kein Solver, sonderneine Benutzer-Schnittstelle, die die Nutzung unterschiedlicher Solver vereinheitlicht. JuMP ist indie Programmiersprache Julia eingebettet.

    Julia (https://julialang.org) ist eine relativ junge Programmiersprache (erste öffentliche Ver-sion 2012, aktuell Version 1.4.0) für numerisches und wissenschaftliches Rechnen und allgemeineProgrammieraufgaben. Julia wurde und wird amMIT entwickelt und ist quelloffen mit MIT-Lizenz.Die wesentlichen Merkmale von Julia sind

    • dynamisches Typsystem: Typprüfungen (z. B. Datentyp von Variablen) zur Laufzeit einesProgramms

    • Multimethoden („multiple dispatch“): Methodenauswahl anhand der dynamischen Typenmehrerer Objekte; damit kann das Verhalten von Funktionen durch Kombination der Ar-gumenttypen bestimmt werden

    • just-in-time Compiler (basierend auf LLVM) zur Übersetzung der Julia-Programme in Ma-schinencode zur Laufzeit

    • sehr gute Performance (ähnlich C)

    • effiziente Unterstützung von Unicode

    • integrierte Paketverwaltung

    Der Sprachumfang von Julia kann durch Zusatzpakete (derzeit ca. 2800, siehe https://pkg.julialang.org/docs/) erweitert werden.

    Es gibt derzeit noch wenig Lehrbücher zu Julia, Ausnahmen sind [10], [2], [6], [3] und [5]. Aktu-elle Informationen finden sich im Internet, beispielsweise die Dokumentationen zu Julia https://docs.julialang.org/en/v1/ und JuMP https://www.juliaopt.org/JuMP.jl/v0.21/. Un-ter https://julialang.org/learning/ und https://julialang.org/community/ finden sichweitere Informationsquellen.

    Es soll zumindest erwähnt werden, dass die Verwendung von JuMP nicht die einzige Möglichkeitist, Optimierungsprobleme in Julia zu lösen, siehe https://www.juliaopt.org. Mit Convex.jlgibt es eine weitere eingebettete algebraische Modellierungssprache, die speziell für konvexe Op-timierungsprobleme geeignet ist. Im Paket Optim.jl sind Standardverfahren der unbeschränktennichtlinearen Optimierung in Julia implementiert.

    Im folgenden Kapitel wird eine kurze Beschreibung der wesentlichen Sprachelemente von JuMPgegeben. Kapitel 3 gibt eine Übersicht über Solver mit JuMP-Schnittstelle, und in Kapitel 4 folgenInstallationshinweise für Julia. In den Kapiteln 5 bis 7 wird an drei Beispielen mit wachsenderKomplexität die Lösung von Optimierungsaufgaben mit JuMP demonstriert.

    3

    https://github.com/JuliaOpt/JuMP.jlhttps://julialang.orghttps://pkg.julialang.org/docs/https://pkg.julialang.org/docs/https://docs.julialang.org/en/v1/https://docs.julialang.org/en/v1/https://www.juliaopt.org/JuMP.jl/v0.21/https://julialang.org/learning/https://julialang.org/community/https://www.juliaopt.org

  • 2 Sprachbeschreibung

    2 Sprachbeschreibung

    Die algebraische Modellierungssprache JuMP ist in Julia eingebettet, d. h. es steht der gesamteSprachumfang von Julia zur Verfügung, der durch Komponenten zur Beschreibung von Optimie-rungsvariablen, Beschränkungen und Zielfunktionen erweitert ist.

    Julia unterscheidet Groß- und Kleinschreibung. Die Indizes von Datenfeldern (Matrizen und Vek-toren) beginnen wie in Matlab mit 1, werden jedoch in eckigen Klammern angegeben. Ein wesent-licher semantischer Unterschied besteht in der Übergabe von Datenfeldern bei Zuweisungen oderFunktionsaufrufen: Julia übergibt Referenzen an Objekte („call by reference“), während Matlabdie Werte übergibt bzw. kopiert („call by value“). Im Unterschied zu Matlab werden 1×1-Matrizennicht als Skalare behandelt. Kommentare werden in Julia durch # eingeleitet, mehrzeilige Kom-mentare in #= . . . =# eingeschlossen. Fortsetzungszeilen (Matlab: ...) werden nicht gesondertgekennzeichnet, müssen aber für den Compiler erkennbar sein, beispielsweise durch entsprechendeKlammerung.

    Nach Einbindung des Zusatzpakets JuMP.jl kann ein Modell (hier m) initialisiert werden1:using JuMP, Ipopt , Cbcm = Model( opt imizer_with_attr ibutes ( Ipopt . Optimizer , " p r i n t_ l ev e l " => 0 , " t o l "=> 1e−6) )

    set_optimizer (m, Cbc . Optimizer )

    Die Auswahl des zu verwendenden Solvers kann bei der Initialisierung oder mit der Funktionset_optimizer() erfolgen, wobei zuvor die entsprechenden Zusatzpakete einzubinden sind. Solver-spezifische Parameter werden in der Form öption1-> value1, ... angegeben.

    Optimierungsvariable werden mit dem Makro @variable() definiert. Mit Hilfe von Indexmengen(ganzzahlig oder Vektoren von Zeichenketten) können mehrdimensionale Optimierungsvariable de-finiert werden. Der Variablentyp kann mit Int als ganzzahlig oder Bin als binär (für BoolescheVariable) angegeben werden. Komponentenbeschränkungen sind in der Form >= bzw. = 0) # Komponentenbeschränkung@variable (m, −1.0

  • 2 Sprachbeschreibung

    Lineare Beschränkungen werden mit dem Makro @constraint(), nichtlineare Beschränkungen mit@NLconstraint() unter Angabe der Relation = oder == definiert.@constraint (m, x+x3 == 5)@constraint (m, sum( x1 [ i , j ] for i =−10:5:15 , j in [ "A" , "B" , "C" ] ) = 4 . 0 )

    Der Operator sum() erlaubt die Summation über Indexmengen.

    Mehrdimensionale Beschränkungen können entweder mittels Schleifen oder durch Angabe einerzusätzlichen indizierten Variablen definiert werden.@variable (m, d [ 1 : 1 1 ] )for i = 1 :10

    @constraint (m, d [ i ]−d [ i +1]

  • 3 Solver

    Solver Problemklasse in Bemerkung,LP QP MILP NLP Zusatzpaket Lizenz

    Cbc 4 Cbc.jl EPLClp 4 Clp.jl EPLGLPK 4 4 GLPKMathProg GPL

    Interface.jlOSQP 4 4 OSQP.jl ApacheIpopt 4 4 4 Ipopt.jl [11], EPLGurobi 4 4 4 Gurobi.jl kommerziellaCPLEX 4 4 4 CPLEX.jl kommerziellaNLopt 4 NLopt.jl LGPLKnitro 4 4 4 4 KNITRO.jl kommerziellMINOS 4 4 4 AmplNLWriter.jl kommerziellbSNOPT 4 4 4 AmplNLWriter.jl kommerziellb

    Tabelle 1: Von JuMP unterstützte Solver (Auswahl).

    In JuMP werden solche Parameter als „nichtlineare Parameter“ bezeichnet und können nur in@NLconstraint() und @NLobjective() verwendet werden.

    Der Sprachumfang von JuMP kann durch benutzerdefinierte Julia-Funktionen mit skalaren Ar-gumenten erweitert werden. Diese sind mittels JuMP.register() für JuMP verfügbar zu machen,dabei ist die Anzahl der Argumente und die Art der Bereitstellung der Ableitungen anzugeben.mysquare (x ) = x∗xJuMP. r e g i s t e r (m, : mysquare , 1 , mysquare , a u t o d i f f=true )

    JuMP bietet noch viele weitere Funktionalitäten, auf die im Rahmen dieser Kurzanleitung nichteingegangen werden kann. Hierzu wird auf die Dokumentation unter https://www.juliaopt.org/JuMP.jl/v0.21/ verwiesen. Es gibt zahlreiche Beispielsammlungen, siehe z. B. https://github.com/JuliaOpt/JuMP.jl/tree/master/examples .

    Begrenzt wird die Leistungsfähigkeit von JuMP durch die Anforderung, dass die Optimierungsauf-gabe komplett in JuMP formuliert werden muss. Damit ergibt sich eine Einschränkung auf denvon der Sprache vorgegebenen Funktionsumfang, der beispielsweise keine numerische Lösung vonDifferentialgleichungen ermöglicht.

    3 Solver

    JuMP unterstützt zahlreiche Solver, siehe Tabelle 1. Die vollständige Liste ist unter https://www.juliaopt.org/JuMP.jl/v0.21/installation/#Getting-Solvers-1 zu finden.

    Weitere Solver mit AMPL-Schnittstelle können mit AmplNLWriter.jl eingebunden werden.

    Solver-spezifische Parameter werden bei der Solver-Auswahl in der Form öption1-> value1, ...angegeben, siehe Abschnitt 2.

    1kostenlose „Academic License“ verfügbar2in AMPL frei verfügbar mit eingeschränkter Lizenz, siehe Abschnitt 4

    6

    https://github.com/coin-or/Cbchttps://github.com/coin-or/Clphttps://www.gnu.org/software/glpk/https://osqp.orghttps://projects.coin-or.org/Ipopthttps://www.gurobi.comhttps://www.ibm.com/de-de/analytics/cplex-optimizerhttps://nlopt.readthedocs.io/en/latest/https://www.artelys.com/solvers/knitro/http://www.sbsi-sol-optimize.com/asp/sol_product_minos.htmhttp://scicomp.ucsd.edu/~peg/https://www.juliaopt.org/JuMP.jl/v0.21/https://www.juliaopt.org/JuMP.jl/v0.21/https://github.com/JuliaOpt/JuMP.jl/tree/master/exampleshttps://github.com/JuliaOpt/JuMP.jl/tree/master/exampleshttps://www.juliaopt.org/JuMP.jl/v0.21/installation/#Getting-Solvers-1https://www.juliaopt.org/JuMP.jl/v0.21/installation/#Getting-Solvers-1

  • 4 Installation

    Beschreibung Option Wertebereich StandardwertAusgabe print_level [0, 12] 5Abbruchbedingung tol (0, +∞) 1 · 10−8Max. Iterationen max_iter [0, +∞) 3000Max. Rechenzeit max_cpu_time (0, +∞) 1 · 106Test Ableitungen derivative_test {none, first-order, none

    second-order}

    Tabelle 2: Wichtige Optionen für Ipopt, siehe https://coin-or.github.io/Ipopt/OPTIONS.html

    Beschreibung Option Wertebereich StandardwertAusgabe LogLevel [0, 4] 0Abbruchbedingung PrimalTolerance (0, +∞) 1 · 10−7Abbruchbedingung DualTolerance (0, +∞) 1 · 10−7Max. Rechenzeit MaximumSeconds (0, +∞)Algorithmus SolveType [0, 5]

    0/1 – dualer/primaler Simplex3/4 – Barrieremethode

    5 – automatische Auswahl

    Tabelle 3: Wichtige Optionen für Clp, siehe https://github.com/JuliaOpt/Clp.jl

    Beschreibung Option Wertebereich StandardwertAusgabe logLevel {0, 1} 0Max. Rechenzeit seconds (0, +∞)Anzahl Prozesse threads

    Tabelle 4: Wichtige Optionen für Cbc, siehe https://github.com/JuliaOpt/Cbc.jl

    4 Installation

    Im Folgenden wird die Standard-Installation unter Windows (Windows 10, 64 Bit) beschrieben.

    Zunächst wird Julia von https://julialang-s3.julialang.org/bin/winnt/x64/1.4/julia-1.4.0-win64.exe heruntergeladen und in ein beliebiges Verzeichnis (im BeispielC:\Users\\AppData\Local\Programs\Julia\Julia-1.4.0) installiert.

    Die Umgebungsvariable JULIA_BINDIR sollte den Verzeichnispfad zu julia.exe enthalten, im Bei-spiel C:\Users\\AppData\Local\Programs\Julia\Julia-1.4.0\bin . Dieser ist auch zurUmgebungsvariablen Path hinzuzufügen: %JULIA_BINDIR%;... .

    julia.exe startet ein interaktives Kommandozeilenprogramm (REPL: Read-Evaluate-Print-Loop),mit dem beliebige Julia-Anweisungen ausgeführt werden können, beispielsweise

    julia> pwd() # Ausgabe des aktuellen Verzeichnissesjulia> cd("C:\\Users\\xyz\\HOME") # Verzeichniswechseljulia> ? # Hilfe zu Kommandos

    7

    https://coin-or.github.io/Ipopt/OPTIONS.htmlhttps://coin-or.github.io/Ipopt/OPTIONS.htmlhttps://github.com/JuliaOpt/Clp.jlhttps://github.com/JuliaOpt/Cbc.jlhttps://julialang-s3.julialang.org/bin/winnt/x64/1.4/julia-1.4.0-win64.exehttps://julialang-s3.julialang.org/bin/winnt/x64/1.4/julia-1.4.0-win64.exe

  • 4 Installation

    help?> cdjulia> ; # Ausführung von Shell-Kommandosshell> cmd /C dirjulia> using LinearAlgebra # Einbinden des Standardpakets LinearAlgebrajulia> eigen(randn(5,5)) # Berechnung der Eigenwerte und -vektoren einer

    # (5x5)-Matrix von normalverteilten Zufallszahlenjulia> exit() # REPL beenden

    Falls vor dem Start von Julia benutzerspezifische Einstellungen geladen werden sollen, so kanndazu eine Datei C:\Users\\.julia\config\startup.jl angelegt werden.

    Julia besitzt einen integrierten Paketmanager, der mit using Pkg eingebunden wird. Die wich-tigsten Befehle sind Pkg.add("paket") und Pkg.update(). Für die im Folgenden beschriebeneNutzung von JuMP werden benötigt:

    • Modellierungssprache und Solver: JuMP.jl, Ipopt.jl, Clp.jl

    • Grafik: Plots.jl, PyPlot.jl

    Weitere sinnvolle Pakete sind

    • Solver: Cbc.jl, OSQP.jl, AmplNLWiter.jl

    • LTI-Systeme: ControlSystems.jl

    • Matlab-Dateiformat: MAT.jl

    Die Installation dieser Zusatzpakete kann mit der Hilfsdatei inst.jl erfolgen

    julia> include("inst.jl")

    und zieht die automatische Installation weiterer Pakete nach sich.

    Mögliche Probleme:

    Keine bekannten Probleme mit Julia 1.4.0

    Mögliche Probleme mit älteren Julia-Versionen:

    In Julia 1.0.2 funktioniert die automatische Installation von MAT.jl u.U. nicht korrekt,und es muss ein aktualisiertes Paket installiert werden:

    julia> ] (v1.0) pkg> rm MAT (v1.0) pkg> addhttps://github.com/halleysfifthinc/MAT.jl#v0.7-update (v1.0) pkg> julia> using MAT

    in Julia 1.0.2 funktioniert die automatische Installation von Cbc.jl u.U.nicht korrekt. Im Verzeichnis .julia\packages\WinRPM\Y9QdZ\cache\2 mussdie Datei mingw64-libstdc++6-8.2.0-2.5.noarch.cpio von Hand aus dementsprechenden rpm-Archiv extrahiert werden. Danach wird das Paket mitusing Pkg; Pkg.build("Cbc") neu erstellt.

    Unter Umständen kommt es nach Installation von Julia 0.6.2, JuMP.jl und Ipopt.jlbeim ersten Aufruf von Ipopt.jl zu einem Fehler

    8

    # Pakete für JuMP in NMOO# E. Arnold 2016-05-11# 2018-10-04 Julia 1.0using PkgPkg.add("JuMP")Pkg.add("Ipopt")Pkg.add("Cbc")Pkg.add("AmplNLWriter")Pkg.add("Clp")Pkg.add("GLPK")Pkg.add("GLPKMathProgInterface")Pkg.add("OSQP")Pkg.add("Plots")Pkg.add("LaTeXStrings")Pkg.add("PyCall")Pkg.add("PyPlot")Pkg.add("ControlSystems")Pkg.add("MAT")Pkg.update()

  • 4 Installation

    ERROR: LoadError: ReadOnlyMemoryError()

    In diesem Fall sind die Dateien libgcc_s_seh-1.dll, libgfortran-4.dll,libquadmath-0.dll, libstdc++-6.dll und libwinpthread-1.dll aus dem Verzeich-nisC:\Users\\.julia\v0.6\WinRPM\deps\usr\x86_64-w64-mingw32\sys-root\mingw\binnach %JULIA_HOME% zu kopieren.

    Unter Umständen tritt beim ersten Aufruf einer plot()-Anweisung aus derPyPlot-Bibliothek ein Laufzeitfehler der Microsoft Visual C++ Laufzeit-BibliothekRuntime Error! R6034 auf. In diesem Fall ist in der InitialisierungsdateiC:\Users\\.juliarc.jl die Anweisung

    ENV["MPLBACKEND"]="qt4agg"

    zu ergänzen.

    JuMP kann mittels AmplNLWriter.jl beliebige Solver mit AMPL-Schnittstelle nutzen. Eine imFunktionsumfang eingeschränkte AMPL-Version („Studentenlizenz“: maximal 300-500 Variableund 300 Beschränkungen) ist frei verfügbar und kann zusammen mit mehreren Solvern als Archivda-tei https://ampl.com/demo/ampl.mswin64.zip heruntergeladen werden. ampl.mswin64.zip wirdin ein beliebiges Verzeichnis (z. B. C:\Program Files\ampl.mswin64) entpackt. Eine gesonderteInstallation ist nicht erforderlich.

    Editoren

    Zahlreiche Editoren unterstützen Julia, beispielsweise existiert für den Texteditor Notepad++ https://notepad-plus-plus.org/ eine Julia-Erweiterung mit Syntaxhervorhebung.

    Eine Sonderstellung nimmt Atom https://atom.io ein, für den mit Juno https://junolab.orgeine vollwertige Julia-Entwicklungsumgebung verfügbar ist.

    Alternativen zur Standard-Installation

    Einen einfachen Einstieg in die Arbeit mit Julia ohne Installation ermöglicht JuliaBox https://www.juliabox.com. Hier läuft Julia komplett im Browser. Mit dem Paketmanager (siehe unten)sind lediglich die entsprechenden Zusatzpakete zu installieren.

    JuliaPRO https://juliacomputing.com/products/juliapro ist ein Julia-Komplettpaket mitEntwicklungsumgebung(en), Debugger, Profiler und diversen Paketen.

    Die Nutzung von Jupyter-Notebooks https://jupyter.org ist eine weitere Alternative.

    9

    https://ampl.com/demo/ampl.mswin64.ziphttps://notepad-plus-plus.org/https://notepad-plus-plus.org/https://atom.iohttps://junolab.orghttps://www.juliabox.comhttps://www.juliabox.comhttps://juliacomputing.com/products/juliaprohttps://jupyter.org

  • 5 Beispiel: Problem von Rosenbrock

    5 Beispiel: Problem von Rosenbrock

    Das aus der Vorlesung [1] bekannte Problem von Rosenbrock, ein unbeschränktes nichtlinearesOptimierungsproblem mit zwei Variablen

    minx1, x2

    {Q(x1, x2) = 100 ·

    (x2 − x21

    )2+ (x1 − 1)2

    }(1)

    soll mit JuMP gelöst werden.

    julia.exe startet ein interaktives Kommandozeilenprogramm (REPL). Zunächst werden die zunutzenden Zusatzpakete JuMP und Ipopt geladen. Anschließend wird ein Modell m initialisiert, undder Solver Ipopt wird ausgewählt. Die Problembeschreibung (hier die Deklaration der Optimie-rungsvariablen und die Definition der Zielfunktion) sowie die Daten (hier die Startwerte für dieOptimierungsvariablen) werden hinzugefügt. Dann wird der Solver aufgerufen und (nach erfolgrei-chem Optimierungslauf) werden die Optimierungsergebnisse ausgegeben.

    julia> using JuMP, Ipoptjulia> m = Model(Ipopt.Optimizer)A JuMP ModelFeasibility problem with:Variables: 0Model mode: AUTOMATICCachingOptimizer state: EMPTY_OPTIMIZERSolver name: Ipoptjulia> @variable(m, x[1:2])2-element Array{VariableRef,1}:x[1]x[2]

    julia> set_start_value(x[1], -1.2)julia> set_start_value(x[2], -1.0)julia> @NLobjective(m, Min, 100*(x[2]-x[1]^2)^2+(x[1]-1)^2)julia> print(m)Min 100.0 * (x[2] - x[1] ^ 2.0) ^ 2.0 + (x[1] - 1.0) ^ 2.0Subject tojulia> optimize!(m)...julia> termination_status(m)LOCALLY_SOLVED::TerminationStatusCode = 4julia> objective_value(m)2.238160324149676e-17julia> value.(x)2-element Array{Float64,1}:0.99999999539645350.9999999906838674

    Es wird die bekannte Lösung x1 = x2 = 1 gefunden.

    10

  • 6 Beispiel: Transportproblem

    Dieser interaktive Modus ist für kleine Optimierungsaufgaben oder zur Fehlersuche geeignet. Beigrößeren Optimierungsproblemen empfiehlt sich die Nutzung von Julia-Funktionen und/oder Spei-cherung in eigenständigen Dateien.

    6 Beispiel: Transportproblem

    Das Transportproblem aus [9] (siehe Vorlesung [1])

    Q(x) =4∑

    i=1Kixi −→ min

    xi, i=1,...,4! (2a)

    0 ≤ xi ≤ Ci, i = 1, . . . , 4 (2b)V1 = x1 + x3 (2c)V2 = x2 − x3 + x4 (2d)

    ist eine lineare Optimierungsaufgabe.

    Eine einfache Formulierung des Problems in JuMP zeigt das folgende Listing .

    Listing 1: Transportproblem (einfache Formulierung).using JuMP, Clp , LinearAlgebra

    2 # ParameterC = [30 , 20 , 30 , 60 ]

    4 K = [40 , 20 , 10 , 10 ]V = [50 , 40 ]

    6 # Model lm = Model( Clp . Optimizer )

    8 # Opt imierungsvar iab l e@variable (m, 0

  • 6 Beispiel: Transportproblem

    dem Makro @objective() definiert, wobei das Symbol Min die Richtung der Optimierung angibt.Die Funktion dot() berechnet das Skalarprodukt.

    Mit der Anweisung optimize!() in Zeile 16 wird der Solver gestartet und in den Zeilen 18 bis22 wird das Optimierungsergebnis unter Nutzung der Funktionen objective_value() für denOptimalwert der Zielfunktion und value.() für die Optimalwerte der Optimierungsvariablen aus-gegeben.

    Eine allgemeinere Formulierung unter Verwendung von Indexmengen ist in der DateiPapageorgiou141_jump.jl gespeichert.

    Listing 2: Transportproblem: Datei Papageorgiou141_jump.mod.using JuMP, Clp

    2 # ParameterRohr le i tungen = [ "L1 " , "L2 " , "L3 " , "L4 " ]

    4 Verbraucher = [ "V1" , "V2" ]Kapazität = Dict ( zip ( Rohrle itungen , [ 3 0 , 20 , 30 , 6 0 ] ) )

    6 Kosten = Dict ( zip ( Rohrle itungen , [ 4 0 , 20 , 10 , 1 0 ] ) )Verbrauch = Dict ( zip ( Verbraucher , [ 5 0 , 4 0 ] ) )

    8 Zu f l u s s = Dict ( "V1" => ( "L1 " , "L3 " ) , "V2" => ( "L2 " , "L4 " ) )Abf luss = Dict ( "V1" => ( ) , "V2" => ( "L3 " , ) )

    10 # Model lm = Model( opt imizer_with_attr ibutes (Clp . Optimizer , " LogLevel " => 0) )

    12 # Opt imierungsvar iab l e@variable (m, 0 ("L2", "L4"))Abfluss = Dict("V1" => (), "V2" => ("L3",))

    # Modellm = Model(optimizer_with_attributes(Clp.Optimizer, "LogLevel" => 0))

    # Optimierungsvariable@variable(m, 0

  • 6 Beispiel: Transportproblem

    der Indexmenge Rohrleitungen mit den Komponentenbeschränkungen (2b) definiert. Die Kno-tengleichungen (2c), (2d) werden mit dem Makro @constraint() als Gleichungsbeschränkungen(Operator ==) definiert. Da mit der Anweisung in Zeile 15 mehrere Beschränkungen definiert werdensollen, ist die Indexmenge Verbraucher als 2. Argument anzugeben. Der Operator sum() erlaubtdie Summation über die zugehörigen Indexmengen (Tupel). In Zeile 17 wird schließlich die Ziel-funktion (2a) mit dem Makro @objective() definiert, wobei das Symbol Min die Richtung derOptimierung angibt.

    Der Aufruf des Solvers und die Ergebnisausgabe sind identisch zur oben beschriebenen einfachenFormulierung.

    Mit dem Befehl include("Papageorgiou141_jump.l") wird die Datei in REPL geladen und dieAusführung gestartet:

    julia> include("Papageorgiou141_jump.jl")Solver Status: OPTIMALGesamtkosten: 1900.0L1 : 20.0L2 : 10.0L3 : 30.0L4 : 60.0

    Das Optimierungsproblem kann zur Kontrolle ausgegeben werden:

    julia> print(m)Min 40 Durchfluss[L1] + 20 Durchfluss[L2] + 10 Durchfluss[L3] + 10 Durchfluss[L4]Subject tocon[V1] : Durchfluss[L1] + Durchfluss[L3] == 50.0con[V2] : Durchfluss[L2] + Durchfluss[L4] - Durchfluss[L3] == 40.0Durchfluss[L1] >= 0.0Durchfluss[L2] >= 0.0Durchfluss[L3] >= 0.0Durchfluss[L4] >= 0.0Durchfluss[L1]

  • 7 Beispiel: Optimalsteuerung van der Pol-Oszillator

    7 Beispiel: Optimalsteuerung van der Pol-Oszillator

    Das in diesem Abschnitt beschriebene Beispiel ist [8] entnommen. Betrachtet wird der gesteuertevan der Pol-Oszillator

    ẋ1(t) = x2(t) (3a)ẋ2(t) = −x1(t) + (1− x21(t)) · x2(t) + u(t) (3b)

    0 ≤ t ≤ tfx1(0) = 1, x2(0) = 1 (3c)

    x21(tf ) + x22(tf ) = r2 (3d)−1 ≤ u(t) ≤ 1, 0 ≤ t ≤ tf (3e)

    Der Parameter r ist zu r = 0.2 vorgegeben. Für das System sind vier Optimalsteuerungsaufgabenzu lösen.

    Problem 1: Bei fester Endzeit tf = 4 soll das Zielfunktional

    J1 =12

    ∫ tf0

    x21(t) + x22(t) + u2(t) dt (4)

    minimiert werden.

    Problem 2: Bei freier Endzeit tf soll das System durch Minimierung von

    J2 = tf (5)

    zeitoptimal gesteuert werden.

    Problem 3: Bei fester Endzeit tf = 4 soll das Zielfunktional (4) minimiert werden. Zusätzlich istdie Zustandsbeschränkung

    − 0.4 ≤ x2(t) (6)

    zu berücksichtigen.

    Problem 4: Bei fester Endzeit tf = 4 und geänderten Anfangsbedingungen x1(0) = 0, x2(0) = 1anstelle von (3c) ist das Zielfunktional

    J4 =12

    ∫ tf0

    x21(t) + x22(t) dt (7)

    zu minimieren. Die Endbedingung (3d) entfällt.

    Die Optimalsteuerungsaufgabe wird mittels direkter Kollokation (siehe Vorlesung [1]) unter Ver-wendung von JuMP gelöst.

    14

  • 7 Beispiel: Optimalsteuerung van der Pol-Oszillator

    Hierzu wird ein äquidistantes Zeitgitter

    tk = k ·∆t, k = 0, . . . N, ∆t = tfN

    (8)

    eingeführt. xk ≈ x(tk), k = 0, . . . , N bezeichnen die Näherungswerte für die Zustandsgrößen in denGitterpunkten und uk ≈ u(tk + 12∆t), k = 0, . . . , N − 1 die Näherungswerte für die Eingangsgrößeim Intervallmittelpunkt.

    Eine direkter Kollokationsansatz mittels impliziter Mittelpunktregel liefert die folgende diskreteApproximation des Optimalsteuerungsproblems (3a)–(4):

    xk+11 − xk1 = ∆t ·

    xk2 + xk+122 (9a)

    xk+12 − xk2 = ∆t ·

    −xk1 + xk+112 +1− (xk1 + xk+112

    )2 · xk2 + xk+122 + uk (9b)

    0 ≤ k ≤ N − 1x01 = 1, x02 = 1 (9c)(

    xN1

    )2+(xN2

    )2= r2 (9d)

    −1 ≤ uk ≤ 1, k = 0, . . . N − 1 (9e)

    J̃1 =∆t2

    N−1∑k=0

    (xk1 + xk+112

    )2+(

    xk2 + xk+122

    )2+(uk)2 (9f)

    Für die Probleme 2–4 ist die Aufgabe entsprechend zu modifizieren.

    Im folgenden Listing ist das JuMP-Modell der diskreten Approximation (9a)–(9f) angegeben (Dateivdp_jump.jl ).

    Listing 3: Optimalsteuerung: Problem 1 (Datei vdp_jump.jl).1 # Zusa t zpake te

    using JuMP, Ipopt , P lo t s3 pyplot ( ove rwr i t e_ f i gu r e=fa l se )

    # Model l und So l v e r5 mod = Model( opt imizer_with_attr ibutes ( Ipopt . Optimizer , " max_iter " => 1000) )

    # b e n u t z e r d e f i n i e r t e Funktion7 fun ( x1 , x2 ) = −x1+(1−x1^2)∗x2

    JuMP. r e g i s t e r (mod , : fun , 2 , fun , a u t o d i f f=true )9 # Model lparameter

    @NLparameter(mod , x10 == 1 . 0 )11 x20 = 1 .0

    t f f = 4 .013 r = 0 .2

    umin = −1.015 umax = 1 .0

    @NLparameter(mod , p4 == 1 . 0 )17 # D i s k r e t i s i e r u n g

    N = 9919 # Opt imierungsvar iab l e

    15

    # van der Pol-Oszillator## Maurer, H.: Tutorial on control and state constrained optimal# control problems. Part I: Examples.# SADCO Summer School, Imperial College London, 2011.## Direkte Kollokation (implizite Mittelpunktregel)## E. Arnold 2016-05-10# 2018-10-04 Julia 1.0# 2019-03-10 JuMP 0.19# 2020-03-16 JuMP 0.21.1

    # ergebnis(): Grafikenfunction ergebnis(nr, tf, x1, x2, u, koll_x1, koll_x2, x2min = Inf)N = length(value.(x1))-1t = collect(0:N)*value(tf)/N # ZeitHu = dual.(koll_x2).dataif nr != 4Hu = Hu .+ value.(u).dataendplot(t, [value.(x1) value.(x2)], width=2, label=["\$x_1\$" "\$x_2\$"], legend=true, framestyle=:box)if isfinite(x2min)plot!([0 value(tf)]', x2min*[1 1]', label="", style=:dash, color=:red)endplot!(title="van der Pol Oszillator, Problem "*string(nr)*": \$x_1(t),\\,x_2(t)\$", xlabel="Zeit \$t\$", ylabel="\$x_1(t),\\, x_2(t)\$")gui()savefig("vdp_res"*string(nr)*"_x12.pdf")plot(t, value.(u).data, line=:steppost, width=2, label="\$u\$", legend=true, framestyle=:box, ylim=(1.1*minimum(lower_bound.(u)), 1.1*maximum(upper_bound.(u))))plot!(t, lower_bound.(u).data, label="", style=:dash, color=:red)plot!(t, upper_bound.(u).data, label="", style=:dash, color=:red)plot!(title="van der Pol Oszillator, Problem "*string(nr)*": \$u(t)\$", xlabel="Zeit \$t\$", ylabel="\$u(t)\$")gui()savefig("vdp_res"*string(nr)*"_u.pdf")plot(t[1:N], Hu, line=:steppost, width=2, label="\$H_u\$", framestyle=:box, title="van der Pol Oszillator, Problem "*string(nr)*": \$H_u(t)\$", xlabel="Zeit \$t\$", ylabel="\$H_u(t)\$")gui()end

    # Zusatzpaketeusing JuMP, Ipopt, Plotspyplot(overwrite_figure=false)

    # Modell und Solvermod = Model(optimizer_with_attributes(Ipopt.Optimizer, "max_iter" => 1000))

    # benutzerdefinierte Funktionfun(x1, x2) = -x1+(1-x1^2)*x2JuMP.register(mod, :fun, 2, fun, autodiff=true)

    # Modellparameter@NLparameter(mod, x10 == 1.0)x20 = 1.0tff = 4.0r = 0.2umin = -1.0umax = 1.0@NLparameter(mod, p4 == 1.0)

    # DiskretisierungN = 99

    # Optimierungsvariable@variable(mod, umin

  • 7 Beispiel: Optimalsteuerung van der Pol-Oszillator

    @variable (mod , umin

  • 7 Beispiel: Optimalsteuerung van der Pol-Oszillator

    Der Aufruf des Solvers erfolgt in Zeile 34, anschließend werden die Ergebnisse ausgewertet und mitder Funktion ergebnis() grafisch dargestellt.

    Nun wird das Modell entsprechend Problem 2, 3 und 4 modifiziert und die optimale Lösung wirdjeweils erneut berechnet und ausgewertet.

    Listing 4: Optimalsteuerung: Problem 2 (Datei vdp_jump.jl).# Problem 2 : f r e i e Endzeit , z e i t o p t i m a l

    2 set_lower_bound( t f , 0 . 0 )set_upper_bound( t f , Inf )

    4 set_start_value ( t f , t f f )@NLobjective (mod , Min, t f )

    6 # Aufruf So l v e roptimize ! (mod)

    Für Problem 2 wird die Endzeit tf als Optimierungsvariable freigegeben, indem die Schranken(Komponentenbeschränkungen) für die Variable tf auf 0 bzw. Inf (entsprechend +∞) gesetztwerden. Gemäß (5) ist nun die Endzeit tf zu minimieren.

    Listing 5: Optimalsteuerung: Problem 3 (Datei vdp_jump.jl).1 # Problem 3 : f e s t e Endzeit , Zustandsbeschränkung

    set_lower_bound( t f , t f f )3 set_upper_bound( t f , t f f )

    @NLobjective (mod , Min, 0 .5∗ t f /N∗sum( ( ( x1 [ k]+x1 [ k+1]) /2 . 0 ) ^2 + ( ( x2 [ k]+x2 [ k+1])/2 . 0 ) ^2 + (u [ k ] ) ^2 for k=0:N−1) )

    5 # Zustandsbeschränkung@NLparameter(mod , x2min == −0.4)

    7 @NLconstraint (mod , c_x2min [ k=0:N−1] , ( x2 [ k+1]+x2 [ k ] ) /2 .0 >= x2min )# Aufruf So l v e r

    9 optimize ! (mod)

    Für Problem 3 werden die Komponentenbeschränkungen für die nun wieder feste Endzeit tf = 4auf die ursprünglichen Werte zurückgesetzt. Ebenso wird wieder die Zielfunktion von Problem 1verwendet. In Zeile 99 wird die untere Schranke (6) für die Zustandsgröße x2 an den Kollokations-punkten (Intervallmittelpunkten) ausgewertet. Der Wert der unteren Schranke wird als Parameterx2min eingeführt.

    Listing 6: Optimalsteuerung: Problem 4 (Datei vdp_jump.jl).1 # Problem 4 : f e s t e Endzeit , f r e i e r Endzustand

    set_value ( x2min , −1000.0)3 set_value ( x10 , 0 . 0 )

    set_value ( p4 , 0 . 0 )5 @NLobjective (mod , Min, 0 .5∗ t f /N∗sum( ( ( x1 [ k]+x1 [ k+1]) /2 . 0 ) ^2 + ( ( x2 [ k]+x2 [ k+1])

    /2 . 0 ) ^2 for k=0:N−1) + 1e−6/( t f /N) ∗sum( ( u [ k+1]−u [ k ] ) ^2 for k=0:N−2) )# Aufruf So l v e r

    7 optimize ! (mod)

    Für Problem 4 wird der Wert des Parameters x2min so gewählt, dass die Beschränkungen nichtmehr aktiv werden. Anschließend wird der Anfangswert x10 modifiziert. Da für Problem 4 die

    17

  • 7 Beispiel: Optimalsteuerung van der Pol-Oszillator

    0 1 2 3 4Zeit t

    -0.5

    0.0

    0.5

    1.0

    x 1(t)

    ,x2(

    t)

    van der Pol Oszillator, Problem 1: x1(t), x2(t)x1x2

    0 1 2 3 4Zeit t

    -1.0

    -0.5

    0.0

    0.5

    1.0

    u(t)

    van der Pol Oszillator, Problem 1: u(t)

    u

    0.0 0.5 1.0 1.5 2.0 2.5Zeit t

    -0.5

    0.0

    0.5

    1.0

    x 1(t)

    ,x2(

    t)

    van der Pol Oszillator, Problem 2: x1(t), x2(t)x1x2

    0.0 0.5 1.0 1.5 2.0 2.5Zeit t

    -1.0

    -0.5

    0.0

    0.5

    1.0

    u(t)

    van der Pol Oszillator, Problem 2: u(t)

    u

    Abbildung 1: Gesteuerter van der Pol-Oszillator: optimale Lösungen Problem 1 und 2.

    Endzustandsbeschränkung (3d) entfallen soll, wird diese mit p4=0 multipliziert. Die Zielfunktionist nun (7) in zeitlich diskretisierter Form.

    Der Regularisierungsterm10−6

    ∆t

    N−2∑k=0

    (uk+1 − uk

    )2reduziert numerisch bedingte Oszillationen der Steuergröße im singulären Lösungsabschnitt t ∈ [≈ 2.45, 4].

    Mit dem Befehl include() wird die Datei in REPL geladen und die Ausführung gestartet:

    julia> include("vdp_jump.jl")

    Die Abbildungen 1 und 2 zeigen die Lösungen der vier Probleme für N = 99 Diskretisierungsinter-valle.

    18

  • 7 Beispiel: Optimalsteuerung van der Pol-Oszillator

    0 1 2 3 4Zeit t

    -0.25

    0.00

    0.25

    0.50

    0.75

    1.00

    1.25

    x 1(t)

    ,x2(

    t)

    van der Pol Oszillator, Problem 3: x1(t), x2(t)x1x2

    0 1 2 3 4Zeit t

    -1.0

    -0.5

    0.0

    0.5

    1.0

    u(t)

    van der Pol Oszillator, Problem 3: u(t)

    u

    0 1 2 3 4Zeit t

    -0.3

    0.0

    0.3

    0.6

    0.9

    x 1(t)

    ,x2(

    t)

    van der Pol Oszillator, Problem 4: x1(t), x2(t)x1x2

    0 1 2 3 4Zeit t

    -1.0

    -0.5

    0.0

    0.5

    1.0

    u(t)

    van der Pol Oszillator, Problem 4: u(t)

    u

    Abbildung 2: Gesteuerter van der Pol-Oszillator: optimale Lösungen Problem 3 und 4.

    19

  • Literatur

    Literatur

    [1] E. Arnold. Numerische Methoden der Optimierung und Optimalen Steuerung. VorlesungUniversität Stuttgart. 2020. url: https://www.isys.uni-stuttgart.de/lehre/lehrveranstaltungen/nmopt (siehe S. 10, 11, 14).

    [2] F. Bornemann. Numerische lineare Algebra: Eine konzise Einführung mit MATLAB undJulia. Wiesbaden: Springer, 2016. doi: 10.1007/978-3-658-12884-5 (siehe S. 3).

    [3] S. Boyd und L. Vandenberghe. Introduction to Applied Linear Algebra - Vectors, Matrices,and Least Squares - Julia language companion. 2018. url: https://web.stanford.edu/~boyd/vmls/vmls-julia-companion.pdf (siehe S. 3).

    [4] I. Dunning, J. Huchette und M. Lubin. “JuMP: A modeling language for mathematicaloptimization”. In: arXiv:1508.01982 [math.OC] (2015). url: https://arxiv.org/abs/1508.01982 (siehe S. 3).

    [5] M. J. Kochenderfer und T. A. Wheeler. Algorithms for Optimization. Cambridge, MA,USA: MIT Press, 2019 (siehe S. 3).

    [6] C. Kwon. Julia programming for Operations Research. Kwon, 2016. isbn: 978-1533328793(siehe S. 3).

    [7] M. Lubin und I. Dunning. “Computing in Operations Research Using Julia”. In: INFORMSJournal on Computing 27.2 (2015), S. 238–248. doi: 10.1287/ijoc.2014.0623 (siehe S. 3).

    [8] H. Maurer. Tutorial on control and state constrained optimal control problems. Part I: Ex-amples. SADCO Summer School, Imperial College London. 2011. url: https://hal.inria.fr/inria-00629518/PDF/Maurer_Part1.pdf (siehe S. 14).

    [9] M. Papageorgiou, M. Leibold und M. Buss. Optimierung: statische, dynamische, stocha-stische Verfahren für die Anwendung. Berlin: Springer, 2012. doi: 10.1007/978-3-540-34013-3 (siehe S. 11).

    [10] M. Sherrington. Mastering Julia. Packt Publishing, 2015 (siehe S. 3).[11] A. Wächter und L. T. Biegler. “On the implementation of a primal-dual interior point

    filter line search algorithm for large-scale nonlinear programming”. In: Mathematical Pro-gramming 106.1 (2006), S. 25–57. doi: 10.1007/s10107-004-0559-y. url: http://cepac.cheme.cmu.edu/pasilectures/biegler/ipopt.pdf (siehe S. 6).

    20

    https://www.isys.uni-stuttgart.de/lehre/lehrveranstaltungen/nmopthttps://www.isys.uni-stuttgart.de/lehre/lehrveranstaltungen/nmopthttps://doi.org/10.1007/978-3-658-12884-5https://web.stanford.edu/~boyd/vmls/vmls-julia-companion.pdfhttps://web.stanford.edu/~boyd/vmls/vmls-julia-companion.pdfhttps://arxiv.org/abs/1508.01982https://arxiv.org/abs/1508.01982https://doi.org/10.1287/ijoc.2014.0623https://hal.inria.fr/inria-00629518/PDF/Maurer_Part1.pdfhttps://hal.inria.fr/inria-00629518/PDF/Maurer_Part1.pdfhttps://doi.org/10.1007/978-3-540-34013-3https://doi.org/10.1007/978-3-540-34013-3https://doi.org/10.1007/s10107-004-0559-yhttp://cepac.cheme.cmu.edu/pasilectures/biegler/ipopt.pdfhttp://cepac.cheme.cmu.edu/pasilectures/biegler/ipopt.pdf

    ÜbersichtSprachbeschreibungSolverInstallationBeispiel: Problem von RosenbrockBeispiel: TransportproblemBeispiel: Optimalsteuerung van der Pol-OszillatorLiteratur