11: Optimalizační problémy
Tento notebook je výukovým materiálem v předmětu BI-JUL.21 vyučovaném v zimním semestru akademického roku 2021/2022 Tomášem Kalvodou. Tvorba těchto materiálů byla podpořena NVS FIT.
Hlavní stránkou předmětu, kde jsou i další notebooky a zajímavé informace, je jeho Course Pages stránka.
1. Úvod
Nejprve je nutné učinit několik úvodních vysvětlujících poznámek. Co přesně znamená slovní spojení "optimalizačním problémem"?
1.1 Matematická formulace optimalizačního problému
Pod "optimalizačním problémem" máme na mysli následující matematickou úlohu:
Najděte extrém (minimum či maximum) funkce , kde množina je popsána pomocí funkcí , , a , , následovně
Mluvíme o "rovnostních" a "nerovnostních" podmínkách, v některých problémech mohou být podmínky jen jednoho druhu nebo dokonce nemusíme mít podmínky žádné.
Množina může být otevřená podmnožina , nebo třeba podmnožina , či dokonce podmnožina .
Množina je množina tzv. "přípustných" řešení. Součástí úlohy je i nalezení nějakého jejího prvku (je neprázdná?). Přípustné řešení splňující (případně ) se nazývá "optimální řešení" a "optimální hodnota" daného problému (optimální hodnota je právě jedna - existuje-li; optimálních řešení může být více).
Nejčastější kategorizace těchto problémů je podle charakteru používaných funkcí a charakteru proměnných, používají se tyto zkratky:
- MI: Mixed Integer, některé proměnné mohou být omezeny na celočíselné hodnoty (pouze binární hodnoty 0 a 1 se většionu počítají do této kategorie),
- LP: Linear programming, objektivní funkce a omezení jsou lineární (affinní) funkce,
- QP: Quadratic programming, objektivní funkce kvadratická, ale omezení stále lineární (affinní) funkce,
- CP: Convex programming, objektivní funkce a nerovnostní omezení konvexní, rovnostní omezení lineární (affinní) funkce.
1.2 Historická perspektiva
Optimalizační úlohy se nejprve objevily ve fyzice. Příroda má totiž tendenci minimalizovat různé veličiny (energii, čas, vzdálenost,...). Z computer science perspektivy je první zajímavý SIMPLEX algoritmus (Dantzig, 40. léta dvacátého století) řešící optimalizační úlohu s lineárními objektivními funkcemi a omezeními. SIMPLEX současně dává algoritmické řešení soustavy lineárních nerovnic. Optimalizační úlohy během dvacátého století vzkvétaly a nacházely další uplatnění například ve strojovém učení a plánování (v tomto smyslu se zde používá slovíčko programming). Často už ovšem nejde pouze o lineární problémy!
1.3 Julia nástroje
V Julia je asi nejpoužívanějším nástrojem na řešení optimalizačních úloh balíček JuMP.jl
.
Jde o zkratku Julia for Mathematical Programming.
Tento balíček poskytuje výrazivo umožňující optimalizační problém snadno formulovat.
K samotnému řešení problému pak používá některou z existujících knihoven nebo Julia balíčků.
Těch přirozeně existuje celá řada a každá umí řešit různé typy problémů, JuMP se je snaží všechny zastřešit a odstínit uživatele od práce s API samotných knihoven/balíčků.
Některé z těchto knihoven jsou open source, některé jsou komerční.
Kompletní přehled podporovaných "řešičů" naleznete v dokumentaci zde.
K zprovoznění tohoto notebooku budeme potřebovat balíček JuMP.jl
samotný, nainstalujte ho standardně pomocí ] add JuMP
a poté nainstalujte i některý z "řešičů" (viz níže).
using JuMP, PyPlot
JuMP.jl
2. Základní formulace problému ("modelu") v Formulace problému (také bývá zvykem hovořit o "modelu") v JuMP velmi věrně kopíruje jeho matematickou strukturu. Musíme vytvořit proměnné, omezení, objektivní funkci a případně nastavit další parametry. JuMP k tomu velmi šikovně využívá Julia makra. Poté, co takovýto model vytvoříme, může ho JuMP samostatně poslat zvolenému řešiči. O tuto práci se už jako uživatelé starat nemusíme a JuMP ji udělá za nás (není to triviální, každý řešič může mít jiné API, JuMP se snaží i naše funkce optimalizovat nebo i dopočítává derivace, pokud je řešič vyžaduje).
Ukažme si tento proces na jednoduchém a snadno představitelném příkladě. Zájemcům doporučuji projít si velmi dobře sepsanou dokumentaci JuMP.
Minimalizujme funkci na obdélníku . Tuto situaci si můžeme velmi snadno vizualizovat (vzhledem k malému počtu proměnných).
xs = LinRange(-1, 1, 50)
ys = LinRange(-1, 1, 50)
fs = [ x^2 - x*y - y^2 for y in ys, x in xs ]
plt.xlabel("x")
plt.ylabel("y")
plot_surface(xs, ys, fs);
Ačkoliv tento graf vypadá atraktivně, není moc přehledný. Daleko lepší je contour plot nebo heat map.
plt.xlabel("x")
plt.ylabel("y")
contourf(xs, ys, fs, 20)
plt.colorbar()
PyObject <matplotlib.colorbar.Colorbar object at 0x7fb7a5a02c50>
Z grafů se zdá, že minimum bude nabyto někde na hranici obdélníku. Pojďme to prověřit.
Nejprve musíme vytvořit Model
, při tom můžeme specifikovat jaký řešič se použije.
Nejprve ale musíme importovat balíček s řešičem, zde Ipopt, (] add Ipopt
).
using Ipopt
Poté můžeme vytvořit náš model a předat mu řešič.
model = Model(Ipopt.Optimizer);
Náš problém má dvě proměnné a .
Ukážeme si dva způsoby jak definovat omezení.
K definici proměnných se používá makro @variable
, kterému můžeme přidat i jednoduchá omezení na rozsah:
@variable(model, -1 <= x <= 1)
@variable(model, y);
Případná další, potenciální výrazně komplikovanější, omezení můžeme definovat pomocí makra @constraint
.
Omezme pomocí něho tedy i druhou proměnnou (proměnná by v těchto zápisech měla být na levé straně nerovnosti).
@constraint(model, y >= -1)
@constraint(model, y <= 1);
V proměnné x
je uložen JuMP objekt typu VariableRef
, který nám umožňuje vytvářet různé symbolické výrazy a pomocí něhož poté budeme získávat řešení.
typeof(x)
VariableRef (alias for GenericVariableRef{Float64})
2 * x
A konečně k definici objektivní funkce slouží makro @objective
:
@objective(model, Min, x^2 - x * y - y^2);
Makro @objective
si poradí s lineární nebo kvadratickou objektivní funkcí. Pokud bychom chtěli pracovat s "výrazněji" nelineárními podmínkami nebo objektivními funkcemi, musíme explicitně použít makra @NLconstraint
a @NLobjective
.
Než se pustíme do řešení, můžeme si nechat model zobrazit (toto se hodí jen pro menší modely):
print(model)
latex_formulation(model)
Případně:
model
A JuMP Model Minimization problem with: Variables: 2 Objective function type: QuadExpr `AffExpr`-in-`MathOptInterface.GreaterThan{Float64}`: 1 constraint `AffExpr`-in-`MathOptInterface.LessThan{Float64}`: 1 constraint `VariableRef`-in-`MathOptInterface.GreaterThan{Float64}`: 1 constraint `VariableRef`-in-`MathOptInterface.LessThan{Float64}`: 1 constraint Model mode: AUTOMATIC CachingOptimizer state: EMPTY_OPTIMIZER Solver name: Ipopt Names registered in the model: x, y
Řešení spustíme metodou optimize!
:
optimize!(model)
****************************************************************************** This program contains Ipopt, a library for large-scale nonlinear optimization. Ipopt is released as open source code under the Eclipse Public License (EPL). For more information visit https://github.com/coin-or/Ipopt ****************************************************************************** This is Ipopt version 3.14.13, running with linear solver MUMPS 5.6.1. Number of nonzeros in equality constraint Jacobian...: 0 Number of nonzeros in inequality constraint Jacobian.: 2 Number of nonzeros in Lagrangian Hessian.............: 3 Total number of variables............................: 2 variables with only lower bounds: 0 variables with lower and upper bounds: 1 variables with only upper bounds: 0 Total number of equality constraints.................: 0 Total number of inequality constraints...............: 2 inequality constraints with only lower bounds: 1 inequality constraints with lower and upper bounds: 0 inequality constraints with only upper bounds: 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 0 0.0000000e+00 0.00e+00 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0 1 0.0000000e+00 0.00e+00 2.00e-07 -1.7 0.00e+00 0.0 1.00e+00 1.00e+00 0 2 0.0000000e+00 0.00e+00 1.50e-09 -3.8 0.00e+00 0.4 1.00e+00 1.00e+00 0 3 0.0000000e+00 0.00e+00 1.84e-11 -5.7 0.00e+00 -0.1 1.00e+00 1.00e+00 0 4 0.0000000e+00 0.00e+00 2.51e-14 -8.6 0.00e+00 0.4 1.00e+00 1.00e+00T 0 Number of Iterations....: 4 (scaled) (unscaled) Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00 Dual infeasibility......: 2.5059035640133008e-14 2.5059035640133008e-14 Constraint violation....: 0.0000000000000000e+00 0.0000000000000000e+00 Variable bound violation: 0.0000000000000000e+00 0.0000000000000000e+00 Complementarity.........: 2.5059035596800808e-09 2.5059035596800808e-09 Overall NLP error.......: 2.5059035596800808e-09 2.5059035596800808e-09 Number of objective function evaluations = 5 Number of objective gradient evaluations = 5 Number of equality constraint evaluations = 0 Number of inequality constraint evaluations = 5 Number of equality constraint Jacobian evaluations = 0 Number of inequality constraint Jacobian evaluations = 1 Number of Lagrangian Hessian evaluations = 1 Total seconds in IPOPT = 0.006 EXIT: Optimal Solution Found.
Tento log výpočtu nepochází z JuMP, ale přímo z Ipopt, nebo i jiných řešičů. Potlačit ho můžeme zavolání set_silent(model)
.
Pojďme prozkoumat výsledek:
solution_summary(model)
* Solver : Ipopt * Status Result count : 1 Termination status : LOCALLY_SOLVED Message from the solver: "Solve_Succeeded" * Candidate solution (result #1) Primal status : FEASIBLE_POINT Dual status : FEASIBLE_POINT Objective value : 0.00000e+00 Dual objective value : -5.01176e-09 * Work counters Solve time (sec) : 7.32994e-03 Barrier iterations : 4
K optimálnímu řešení se dostaneme pomocí metody value
.
value(x)
0.0
value(y)
0.0
value.([x, y])
2-element Vector{Float64}: 0.0 0.0
A k optimální hodnotě pomocí objective_value
:
objective_value(model)
0.0
Vidíme, že se Ipopt řešič nedokázal dostat ze stacionárního bodu , kde pravděpodobně začal. Tento bod dokonce není ani bodem lokálního extrému! Musíme do řešiče malinko kopnout (alternativně by mohlo pomoci změnit optimalizační metodu / zkusit jiný řešič).
set_start_value(x, 0.23)
Optimalizujme znovu!
optimize!(model)
This is Ipopt version 3.14.13, running with linear solver MUMPS 5.6.1. Number of nonzeros in equality constraint Jacobian...: 0 Number of nonzeros in inequality constraint Jacobian.: 2 Number of nonzeros in Lagrangian Hessian.............: 3 Total number of variables............................: 2 variables with only lower bounds: 0 variables with lower and upper bounds: 1 variables with only upper bounds: 0 Total number of equality constraints.................: 0 Total number of inequality constraints...............: 2 inequality constraints with only lower bounds: 1 inequality constraints with lower and upper bounds: 0 inequality constraints with only upper bounds: 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 0 5.2900000e-02 0.00e+00 4.60e-01 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0 1 1.0828786e-02 0.00e+00 9.04e-02 -1.0 9.04e-02 0.0 1.00e+00 1.00e+00f 1 2 -3.9823732e-03 0.00e+00 1.12e-01 -2.5 4.21e-02 0.4 1.00e+00 1.00e+00f 1 3 -6.2968265e-01 0.00e+00 5.66e-01 -2.5 6.36e-01 -0.1 1.00e+00 1.00e+00f 1 4 -1.2314300e+00 0.00e+00 7.84e-01 -2.5 3.52e-01 0.4 1.00e+00 8.11e-01f 1 5 -1.2289751e+00 0.00e+00 1.54e+00 -2.5 1.05e-01 - 1.00e+00 3.12e-02f 6 6 -1.2472887e+00 0.00e+00 2.83e-08 -2.5 1.23e-01 - 1.00e+00 1.00e+00f 1 7 -1.2498526e+00 0.00e+00 1.50e-09 -3.8 2.23e-03 - 1.00e+00 1.00e+00f 1 8 -1.2499982e+00 0.00e+00 1.84e-11 -5.7 1.41e-04 - 1.00e+00 1.00e+00f 1 9 -1.2500000e+00 0.00e+00 2.53e-14 -8.6 1.64e-06 - 1.00e+00 1.00e+00f 1 Number of Iterations....: 9 (scaled) (unscaled) Objective...............: -1.2500000224957013e+00 -1.2500000224957013e+00 Dual infeasibility......: 2.5313084961453569e-14 2.5313084961453569e-14 Constraint violation....: 0.0000000000000000e+00 0.0000000000000000e+00 Variable bound violation: 0.0000000000000000e+00 0.0000000000000000e+00 Complementarity.........: 2.5121111717748235e-09 2.5121111717748235e-09 Overall NLP error.......: 2.5121111717748235e-09 2.5121111717748235e-09 Number of objective function evaluations = 16 Number of objective gradient evaluations = 10 Number of equality constraint evaluations = 0 Number of inequality constraint evaluations = 16 Number of equality constraint Jacobian evaluations = 0 Number of inequality constraint Jacobian evaluations = 1 Number of Lagrangian Hessian evaluations = 1 Total seconds in IPOPT = 0.006 EXIT: Optimal Solution Found.
Optimální řešení:
value.([x, y])
2-element Vector{Float64}: 0.500000002821662 1.0000000089982806
Kdybychom se vychýlili na druhou stranu, tak dokonvergujeme do jiného lokálního minima:
set_start_value(x, -0.1)
optimize!(model)
This is Ipopt version 3.14.13, running with linear solver MUMPS 5.6.1. Number of nonzeros in equality constraint Jacobian...: 0 Number of nonzeros in inequality constraint Jacobian.: 2 Number of nonzeros in Lagrangian Hessian.............: 3 Total number of variables............................: 2 variables with only lower bounds: 0 variables with lower and upper bounds: 1 variables with only upper bounds: 0 Total number of equality constraints.................: 0 Total number of inequality constraints...............: 2 inequality constraints with only lower bounds: 1 inequality constraints with lower and upper bounds: 0 inequality constraints with only upper bounds: 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 0 1.0000000e-02 0.00e+00 2.00e-01 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0 1 2.0086300e-03 0.00e+00 3.99e-02 -1.0 3.99e-02 0.0 1.00e+00 1.00e+00f 1 2 -7.3425290e-04 0.00e+00 4.79e-02 -2.5 1.80e-02 0.4 1.00e+00 1.00e+00f 1 3 -1.1931993e-01 0.00e+00 2.46e-01 -2.5 2.77e-01 -0.1 1.00e+00 1.00e+00f 1 4 -2.6651816e-01 0.00e+00 3.66e-01 -2.5 1.54e-01 0.4 1.00e+00 1.00e+00f 1 5 -1.2275584e+00 0.00e+00 7.84e-01 -2.5 4.86e+01 -0.1 3.01e-02 1.10e-02f 1 6 -1.2298807e+00 0.00e+00 1.84e+00 -2.5 1.66e-01 - 1.00e+00 1.20e-02f 2 7 -1.2472209e+00 0.00e+00 2.83e-08 -2.5 1.33e-01 - 1.00e+00 1.00e+00f 1 8 -1.2498528e+00 0.00e+00 1.50e-09 -3.8 2.31e-03 - 1.00e+00 1.00e+00f 1 9 -1.2499982e+00 0.00e+00 1.84e-11 -5.7 1.42e-04 - 1.00e+00 1.00e+00f 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 10 -1.2500000e+00 0.00e+00 2.51e-14 -8.6 1.64e-06 - 1.00e+00 1.00e+00f 1 Number of Iterations....: 10 (scaled) (unscaled) Objective...............: -1.2500000224957013e+00 -1.2500000224957013e+00 Dual infeasibility......: 2.5059035640133008e-14 2.5059035640133008e-14 Constraint violation....: 0.0000000000000000e+00 0.0000000000000000e+00 Variable bound violation: 0.0000000000000000e+00 0.0000000000000000e+00 Complementarity.........: 2.5121141971489301e-09 2.5121141971489301e-09 Overall NLP error.......: 2.5121141971489301e-09 2.5121141971489301e-09 Number of objective function evaluations = 16 Number of objective gradient evaluations = 11 Number of equality constraint evaluations = 0 Number of inequality constraint evaluations = 16 Number of equality constraint Jacobian evaluations = 0 Number of inequality constraint Jacobian evaluations = 1 Number of Lagrangian Hessian evaluations = 1 Total seconds in IPOPT = 0.008 EXIT: Optimal Solution Found.
Optimální řešení:
value.([x,y])
2-element Vector{Float64}: -0.5000000028216589 -1.0000000089982806
objective_value(model)
-1.2500000224957013
Najít globální minima a maxima je těžká úloha, pokud o daných funkcích nic více nevíme (typicky potřebujeme alespoň konvexitu). Řešiče v jednom běhu hledají lokální extrémy.
Pro demonstraci ukažme použití i komerčního nástroje Gurobi (pro akademické účely volně k použití; je potřeba nainstalovat balíček ] add Gurobi
a získat licenci, viz oficiální web):
using Gurobi
model = Model(Gurobi.Optimizer)
set_optimizer_attribute(model, "NonConvex", 2)
@variable(model, -1 <= x <= 1)
@variable(model, -1 <= y <= 1)
@objective(model, Min, x^2 - x*y - y^2);
optimize!(model)
Set parameter Username -------------------------------------------- Warning: your license will expire in 5 days -------------------------------------------- Academic license - for non-commercial use only - expires 2023-12-11 Set parameter NonConvex to value 2 Set parameter NonConvex to value 2 Gurobi Optimizer version 10.0.0 build v10.0.0rc2 (linux64) CPU model: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz, instruction set [SSE2|AVX|AVX2] Thread count: 4 physical cores, 8 logical processors, using up to 8 threads Optimize a model with 0 rows, 2 columns and 0 nonzeros Model fingerprint: 0x29307fce Model has 3 quadratic objective terms Coefficient statistics: Matrix range [0e+00, 0e+00] Objective range [0e+00, 0e+00] QObjective range [2e+00, 2e+00] Bounds range [1e+00, 1e+00] RHS range [0e+00, 0e+00] Continuous model is non-convex -- solving as a MIP Found heuristic solution: objective -1.0000000 Presolve time: 0.00s Presolved: 0 rows, 2 columns, 0 nonzeros Presolved model has 3 quadratic objective terms Variable types: 1 continuous, 1 integer (1 binary) Root relaxation: objective -1.250000e+00, 2 iterations, 0.00 seconds (0.00 work units) Nodes | Current Node | Objective Bounds | Work Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time * 0 0 0 -1.2500000 -1.25000 0.00% - 0s Explored 1 nodes (2 simplex iterations) in 0.01 seconds (0.00 work units) Thread count was 8 (of 8 available processors) Solution count 1: -1.25 No other solutions better than -1.25 Optimal solution found (tolerance 1.00e-04) Best objective -1.250000000000e+00, best bound -1.250000000000e+00, gap 0.0000% User-callback calls 98, time in user-callback 0.00 sec
Opět získáváme jedno z možných optimálních řešení:
value.([x,y])
2-element Vector{Float64}: -0.5 -1.0
objective_value(model)
-1.25
3. Cvičení / Úlohy
Po tomto rychlém úvodu do JuMP si ukážeme několik zajímavých a zejména různorodých optimalizačních úloh.
3.1 "Tradiční" zemědělská úloha
Takřka v každé učebnici lineárního programování narazíte na úlohu následujícího typu:
Mějme farmáře, který obdělává pole o rozloze . Pole plánuje osít třemi plodinami (1., 2. a 3., nebudeme se pouštět do konkrétního pojmenování).
- Cena osetí jednotky plochy danou plodinou je popořadě , a .
- Péče o jednotku plochy oseté danou plodinou ho bude stát , a .
- Výnos z jednotky plochy oseté danou plodinou bude , a .
Jak má náš zemědělec využít své pole, aby maximalizoval zisk? Ani v tomto kurzu si nedovolíme tento typ úlohy nezmínit!
Rozeberme situaci podrobně. Neznámými jsou zřejmě plochy oseté jednotlivými plodinami. Označme si je , a . Jistě musí platit následující čtyři nerovnosti:
Snažíme se maximalizovat objektivní funkci (profit; k zjednodušení zápisu jsme přešli k vektorové notaci)
Skutečně jde o lineární program: omezující funkce i objektivní funkce jsou lineární funkce (stačí affinní -- tj. lineární plus konstanta).
Poznámka: Úlohu by šlo samozřejmě dále komplikovat, například přidat horní limit rozpočtu atp. Analogické úlohy lze formulovat také pro dietologické problémy (nastavení jídelníčku s požadovými nutričními požadavky). Opět vidíme, v že název lineární programování by bylo bývalo možná lepší překládat jako lineární plánování.
Zafixujme nějaké konkrétní hodnoty a pokusme se problém vyřešit pomocí Ipopt a JuMP.
using JuMP, Ipopt
S = 10
v1, v2, v3 = 5.5, 6, 6.5
p1, p2, p3 = 1, 1.5, 2
o1, o2, o3 = 1, 0.9, 1.5;
Sestavení modelu:
model = Model(Ipopt.Optimizer)
@variable(model, x[1:3] >= 0)
@constraint(model, x[1] + x[2] + x[3] <= 10)
@objective(model, Max, (v1 - p1 - o1) * x[1] + (v2 - p2 - o2) * x[2] + (v3 - p3 - o3) * x[3])
print(model)
Spusťme řešení!
optimize!(model)
This is Ipopt version 3.14.13, running with linear solver MUMPS 5.6.1. Number of nonzeros in equality constraint Jacobian...: 0 Number of nonzeros in inequality constraint Jacobian.: 3 Number of nonzeros in Lagrangian Hessian.............: 0 Total number of variables............................: 3 variables with only lower bounds: 3 variables with lower and upper bounds: 0 variables with only upper bounds: 0 Total number of equality constraints.................: 0 Total number of inequality constraints...............: 1 inequality constraints with only lower bounds: 0 inequality constraints with lower and upper bounds: 0 inequality constraints with only upper bounds: 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 0 1.0099990e-01 0.00e+00 2.52e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0 1 1.4480398e+00 0.00e+00 3.56e+00 -1.0 3.99e-01 - 2.18e-01 1.00e+00f 1 2 3.5160296e+01 0.00e+00 2.78e+00 -1.0 3.19e+01 - 1.03e-02 2.97e-01f 1 3 3.5560614e+01 0.00e+00 2.35e+00 -1.0 8.39e+00 - 1.00e+00 1.57e-01f 2 4 3.5711258e+01 0.00e+00 1.00e-06 -1.0 3.67e-01 - 1.00e+00 1.00e+00f 1 5 3.5979796e+01 0.00e+00 9.21e-04 -2.5 9.66e-01 - 9.23e-01 1.00e+00f 1 6 3.5999547e+01 0.00e+00 1.50e-09 -3.8 1.30e-01 - 1.00e+00 1.00e+00f 1 7 3.5999995e+01 0.00e+00 1.84e-11 -5.7 1.79e-03 - 1.00e+00 1.00e+00f 1 8 3.6000000e+01 0.00e+00 2.49e-14 -8.6 2.22e-05 - 1.00e+00 1.00e+00f 1 Number of Iterations....: 8 (scaled) (unscaled) Objective...............: -3.6000000359478250e+01 3.6000000359478250e+01 Dual infeasibility......: 2.4900169555147560e-14 2.4900169555147560e-14 Constraint violation....: 0.0000000000000000e+00 0.0000000000000000e+00 Variable bound violation: 5.8225627789055691e-09 5.8225627789055691e-09 Complementarity.........: 2.5092896506099746e-09 2.5092896506099746e-09 Overall NLP error.......: 2.5092896506099746e-09 2.5092896506099746e-09 Number of objective function evaluations = 11 Number of objective gradient evaluations = 9 Number of equality constraint evaluations = 0 Number of inequality constraint evaluations = 11 Number of equality constraint Jacobian evaluations = 0 Number of inequality constraint Jacobian evaluations = 1 Number of Lagrangian Hessian evaluations = 1 Total seconds in IPOPT = 0.005 EXIT: Optimal Solution Found.
Optimální řešení a hodnota:
value.(x)
3-element Vector{Float64}: 1.5092896443320668e-8 10.000000090033556 -5.822562778905569e-9
objective_value(model)
36.00000035947825
Naše doporučení zemědělci by bylo: osej pomocí první a druhé plodiny půl na půl. Očekávaný zisk pak budeš mít "".
Když se podíváte na vstupní data, tak toto zcela jistě není na první pohled patrné!
3.2 Řetězovka
Představte si řetěz délky , který je zavěšen v bodech a , , v homogenním gravitačním poli (v záporném směru osy ). Jak se tento řetěz prověsí? Představte si třeba různé řetězové ploty nebo závěsy mostů. Fyzika (klasická mechanika, detaily vynecháváme) bude tlačit řetěz do stavu s minimální potenciální energií. Pojďme tuto minimalizaci popsat pomocí JuMP.
using JuMP, Ipopt, Gurobi
Řetěz budeme idealizovat jako hmotných bodů spojených nehmotným segmentem. Zajímá nás samozřejmě limita , resp. její aproximace. Zvolíme následující parametry:
n = 10
D = 5
a = 2
L = 8
Δ = L / n
if D > L
@warn "Tohle neprověsíš!"
end
Poté definujeme model. Všimněte si, že objektivní funkce je lineární a netriviální podmínky jsou kvadratické, jde ale o nelineární problém.
model = Model(Ipopt.Optimizer)
# set_optimizer_attribute(model, "NonConvex", 2) # Gurobi
# neznámé jsou souřadnice bodů (x[i], y[i]), i = 1,...,n
@variable(model, x[1:n])
@variable(model, y[1:n])
# okrajové podmínky
@constraints(model, begin
x[1] == 0
x[n] == D
y[1] == a
y[n] == a
end)
# spojky řetězu, resp. vzdálenosti sousedních bodů
for i=1:(n-1)
@constraint(model, (x[i] - x[i+1])^2 + (y[i] - y[i+1])^2 == Δ^2)
end
# objektivní funkce: vynecháváme fyzikální konstanty, které by jen škálovaly celkovou
# funkční hodnotu (krát hmotnost hmotného bodu krát gravitační zrychlení).
# Efekt těžšího dílu řetězu by se projevil násobením příslušeného členu větší konstantou než 1.
@objective(model, Min, sum(y[i] for i=1:n));
print(model)
Pokusme se nalézt řešení.
optimize!(model)
This is Ipopt version 3.14.13, running with linear solver MUMPS 5.6.1. Number of nonzeros in equality constraint Jacobian...: 76 Number of nonzeros in inequality constraint Jacobian.: 0 Number of nonzeros in Lagrangian Hessian.............: 54 Total number of variables............................: 20 variables with only lower bounds: 0 variables with lower and upper bounds: 0 variables with only upper bounds: 0 Total number of equality constraints.................: 13 Total number of inequality constraints...............: 0 inequality constraints with only lower bounds: 0 inequality constraints with lower and upper bounds: 0 inequality constraints with only upper bounds: 0 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 0 0.0000000e+00 5.00e+00 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0 1 -7.9600000e+02 1.04e+04 2.32e+10 -1.0 1.00e+02 -2.0 1.00e+00 1.00e+00f 1 2 -7.9474186e+02 2.61e+03 9.52e+10 -1.0 2.62e+01 9.8 1.00e+00 1.00e+00h 1 3 -7.8410906e+02 6.53e+02 2.06e+11 -1.0 2.02e+01 9.4 1.00e+00 1.00e+00h 1 4 -7.8320856e+02 1.95e+02 3.09e+11 -1.0 1.13e+01 10.7 1.00e+00 1.00e+00h 1 5 -7.7907489e+02 6.67e+01 1.57e+11 -1.0 1.05e+01 10.2 1.00e+00 1.00e+00h 1 6 -7.6201336e+02 7.24e+01 5.34e+10 -1.0 8.76e+00 9.7 1.00e+00 1.00e+00h 1 7 -6.9753737e+02 6.88e+01 1.91e+10 -1.0 9.62e+00 9.3 1.00e+00 1.00e+00h 1 8 -4.7690385e+02 4.69e+01 1.38e+10 -1.0 2.25e+01 8.8 1.00e+00 1.00e+00h 1 9 1.8685030e+01 1.54e+00 3.29e+09 -1.0 4.32e+02 - 1.00e+00 1.00e+00H 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 10 1.9976826e+01 1.45e+00 5.88e+07 -1.0 1.97e-01 - 1.00e+00 1.00e+00H 1 11 1.9999793e+01 1.43e+00 1.11e+07 -1.0 2.61e-02 - 1.00e+00 1.00e+00h 1 12 1.9999999e+01 1.39e+00 2.58e+06 -1.0 3.29e-02 - 1.00e+00 1.00e+00h 1 13 2.0000001e+01 1.36e+00 2.51e+06 -1.0 3.53e-02 - 1.00e+00 1.00e+00h 1 14 2.0000001e+01 1.32e+00 2.48e+06 -1.0 3.73e-02 - 1.00e+00 1.00e+00h 1 15 2.0000001e+01 1.28e+00 2.44e+06 -1.0 3.82e-02 - 1.00e+00 1.00e+00h 1 16 2.0000001e+01 1.25e+00 2.41e+06 -1.0 3.87e-02 - 1.00e+00 1.00e+00h 1 17 2.0000001e+01 1.21e+00 2.37e+06 -1.0 3.88e-02 - 1.00e+00 1.00e+00h 1 18 2.0000001e+01 1.17e+00 2.33e+06 -1.0 3.88e-02 - 1.00e+00 1.00e+00h 1 19 2.0000001e+01 1.13e+00 2.29e+06 -1.0 3.86e-02 - 1.00e+00 1.00e+00h 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 20 2.0000001e+01 1.09e+00 2.25e+06 -1.0 3.83e-02 - 1.00e+00 1.00e+00h 1 21 2.0000001e+01 1.05e+00 2.20e+06 -1.0 3.79e-02 - 1.00e+00 1.00e+00h 1 22 2.0000001e+01 1.02e+00 2.16e+06 -1.0 3.75e-02 - 1.00e+00 1.00e+00h 1 23 2.0000001e+01 9.78e-01 2.11e+06 -1.0 3.71e-02 - 1.00e+00 1.00e+00h 1 24 2.0000001e+01 9.25e-01 4.52e+06 -1.7 5.36e-02 - 1.00e+00 1.00e+00h 1 25 2.0000000e+01 8.72e-01 4.40e+06 -1.7 5.30e-02 - 1.00e+00 1.00e+00h 1 26 2.0000000e+01 8.20e-01 4.25e+06 -1.7 5.18e-02 - 1.00e+00 1.00e+00h 1 27 2.0000000e+01 7.69e-01 4.09e+06 -1.7 5.05e-02 - 1.00e+00 1.00e+00h 1 28 2.0000000e+01 7.20e-01 3.94e+06 -1.7 4.91e-02 - 1.00e+00 1.00e+00h 1 29 2.0000000e+01 6.73e-01 3.78e+06 -1.7 4.77e-02 - 1.00e+00 1.00e+00h 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 30 2.0000000e+01 6.26e-01 3.62e+06 -1.7 4.62e-02 - 1.00e+00 1.00e+00h 1 31 2.0000000e+01 5.98e-01 3.47e+06 -1.7 4.47e-02 - 1.00e+00 1.00e+00h 1 32 2.0000000e+01 5.96e-01 3.32e+06 -1.7 4.31e-02 - 1.00e+00 1.00e+00h 1 33 2.0000000e+01 5.93e-01 3.17e+06 -1.7 4.16e-02 - 1.00e+00 1.00e+00h 1 34 2.0000000e+01 5.91e-01 3.02e+06 -1.7 4.00e-02 - 1.00e+00 1.00e+00h 1 35 2.0000000e+01 5.88e-01 2.87e+06 -1.7 3.84e-02 - 1.00e+00 1.00e+00h 1 36 2.0000000e+01 5.86e-01 2.73e+06 -1.7 3.67e-02 - 1.00e+00 1.00e+00h 1 37 2.0000000e+01 5.83e-01 2.60e+06 -1.7 3.51e-02 - 1.00e+00 1.00e+00h 1 38 2.0000000e+01 5.81e-01 2.47e+06 -1.7 3.35e-02 - 1.00e+00 1.00e+00h 1 39 2.0000000e+01 5.79e-01 2.34e+06 -1.7 3.19e-02 - 1.00e+00 1.00e+00h 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 40 2.0000000e+01 5.77e-01 2.21e+06 -1.7 3.04e-02 - 1.00e+00 1.00e+00h 1 41 2.0000000e+01 5.74e-01 2.10e+06 -1.7 2.89e-02 - 1.00e+00 1.00e+00h 1 42 2.0000000e+01 5.72e-01 1.98e+06 -1.7 2.74e-02 - 1.00e+00 1.00e+00h 1 43 2.0000000e+01 5.70e-01 1.87e+06 -1.7 2.60e-02 - 1.00e+00 1.00e+00h 1 44 2.0000000e+01 5.68e-01 1.77e+06 -1.7 2.46e-02 - 1.00e+00 1.00e+00h 1 45 2.0000000e+01 5.66e-01 1.67e+06 -1.7 2.32e-02 - 1.00e+00 1.00e+00h 1 46 2.0000000e+01 5.64e-01 1.57e+06 -1.7 2.20e-02 - 1.00e+00 1.00e+00h 1 47 2.0000000e+01 5.62e-01 1.48e+06 -1.7 2.07e-02 - 1.00e+00 1.00e+00h 1 48 2.0000000e+01 5.60e-01 1.40e+06 -1.7 1.96e-02 - 1.00e+00 1.00e+00h 1 49 2.0000000e+01 5.58e-01 1.32e+06 -1.7 1.85e-02 - 1.00e+00 1.00e+00h 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 50 2.0000000e+01 5.57e-01 1.24e+06 -1.7 1.74e-02 - 1.00e+00 1.00e+00h 1 51 2.0000000e+01 5.55e-01 1.16e+06 -1.7 1.64e-02 - 1.00e+00 1.00e+00h 1 52 2.0000000e+01 5.53e-01 1.10e+06 -1.7 1.55e-02 - 1.00e+00 1.00e+00h 1 53 2.0000000e+01 5.51e-01 1.08e+06 -1.7 1.46e-02 - 1.00e+00 1.00e+00h 1 54 2.0000000e+01 5.50e-01 1.05e+06 -1.7 1.37e-02 - 1.00e+00 1.00e+00h 1 55 2.0000000e+01 5.48e-01 1.03e+06 -1.7 1.29e-02 - 1.00e+00 1.00e+00h 1 56 2.0000000e+01 5.47e-01 9.99e+05 -1.7 1.22e-02 - 1.00e+00 1.00e+00h 1 57 2.0000000e+01 5.45e-01 9.72e+05 -1.7 1.15e-02 - 1.00e+00 1.00e+00h 1 58 2.0000000e+01 5.43e-01 9.44e+05 -1.7 1.08e-02 - 1.00e+00 1.00e+00h 1 59 2.0000000e+01 5.42e-01 9.17e+05 -1.7 1.02e-02 - 1.00e+00 1.00e+00h 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 60 2.0000000e+01 5.40e-01 8.90e+05 -1.7 9.59e-03 - 1.00e+00 1.00e+00h 1 61 2.0000000e+01 5.39e-01 8.63e+05 -1.7 9.04e-03 - 1.00e+00 1.00e+00h 1 62 2.0000000e+01 5.37e-01 8.37e+05 -1.7 8.52e-03 - 1.00e+00 1.00e+00h 1 63 2.0000000e+01 5.36e-01 8.12e+05 -1.7 8.03e-03 - 1.00e+00 1.00e+00h 1 64 2.0000000e+01 5.34e-01 7.87e+05 -1.7 7.58e-03 - 1.00e+00 1.00e+00h 1 65 2.0000000e+01 5.33e-01 7.64e+05 -1.7 7.15e-03 - 1.00e+00 1.00e+00h 1 66 2.0000000e+01 5.32e-01 7.41e+05 -1.7 6.75e-03 - 1.00e+00 1.00e+00h 1 67 2.0000000e+01 5.31e-01 5.50e+05 -1.7 6.37e-03 - 1.00e+00 5.00e-01h 2 68r 2.0000000e+01 5.31e-01 9.99e+02 -0.3 0.00e+00 - 0.00e+00 4.77e-07R 22 69r 2.0000001e+01 6.19e-01 9.94e+02 -0.3 8.13e+01 - 6.47e-03 5.11e-03f 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 70r 2.0000001e+01 6.08e-01 9.91e+02 -0.3 5.06e+00 2.0 1.00e+00 4.27e-03f 1 71r 2.0000001e+01 5.81e-01 8.68e+02 -0.3 8.22e-01 2.4 1.00e+00 1.60e-01f 1 72r 1.9999982e+01 6.06e-01 4.46e+02 -0.3 3.59e-01 2.9 1.00e+00 6.88e-01f 1 73r 1.9999981e+01 6.10e-01 1.15e+03 -0.3 8.67e-02 4.2 1.00e+00 8.09e-01f 1 74r 1.9999961e+01 6.13e-01 4.07e+02 -0.3 3.27e-02 3.7 1.00e+00 7.54e-01f 1 75r 1.9999946e+01 6.15e-01 1.42e+02 -0.3 1.05e-02 4.1 1.00e+00 1.00e+00f 1 76r 1.9999748e+01 6.21e-01 9.71e+01 -0.3 2.11e-02 3.7 1.00e+00 1.00e+00f 1 77r 1.9999653e+01 6.23e-01 1.04e+02 -0.3 8.71e-03 4.1 1.00e+00 1.00e+00f 1 78r 1.9995991e+01 6.22e-01 1.69e+02 -0.3 4.14e-02 3.6 1.00e+00 1.00e+00f 1 79r 1.9994578e+01 6.16e-01 2.13e+02 -0.3 2.10e-02 4.0 1.00e+00 1.00e+00f 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 80r 1.9974084e+01 3.21e-01 6.87e+02 -0.3 3.39e-01 3.6 1.00e+00 1.00e+00f 1 81 1.9962279e+01 1.09e-01 2.77e+07 -1.7 8.25e-02 8.3 1.00e+00 1.00e+00h 1 82 1.9953554e+01 8.16e-02 1.65e+07 -1.7 2.88e-02 8.7 1.00e+00 1.00e+00h 1 83 1.9927126e+01 9.51e-02 1.32e+07 -1.7 7.26e-02 8.3 1.00e+00 1.00e+00h 1 84 1.9919068e+01 7.82e-02 1.60e+07 -1.7 3.31e-02 8.7 1.00e+00 1.00e+00h 1 85 1.9902171e+01 2.33e-02 1.45e+07 -1.7 8.97e-02 8.2 1.00e+00 1.00e+00h 1 86 1.9897614e+01 1.28e-02 1.30e+07 -1.7 3.01e-02 8.6 1.00e+00 1.00e+00h 1 87 1.9836231e+01 1.05e-01 2.01e+07 -1.7 1.58e-01 8.2 1.00e+00 1.00e+00h 1 88 1.9799203e+01 6.53e-02 1.78e+07 -1.7 5.00e-02 8.6 1.00e+00 1.00e+00h 1 89 1.9690072e+01 1.14e-01 1.03e+07 -1.7 9.44e-02 8.1 1.00e+00 1.00e+00h 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 90 1.9624383e+01 1.12e-01 2.30e+06 -1.7 4.11e-02 7.6 1.00e+00 1.00e+00h 1 91 1.9803196e+01 1.03e-01 1.61e+06 -1.7 1.59e-01 7.2 1.00e+00 1.00e+00h 1 92 1.9866256e+01 2.15e-02 1.94e+06 -1.7 6.12e-02 7.6 1.00e+00 1.00e+00h 1 93 1.9882079e+01 6.97e-03 2.02e+06 -1.7 2.03e-02 8.0 1.00e+00 1.00e+00h 1 94 1.9888607e+01 4.59e-03 3.59e+05 -1.7 1.66e-01 7.5 1.00e+00 1.00e+00H 1 95 1.9894974e+01 4.93e-03 1.26e+05 -1.7 1.13e-02 7.0 1.00e+00 1.00e+00h 1 96 1.9893199e+01 2.47e-03 1.13e+04 -1.7 3.06e-03 6.6 1.00e+00 1.00e+00h 1 97 1.9889481e+01 7.21e-05 6.75e+03 -1.7 5.46e-03 6.1 1.00e+00 1.00e+00h 1 98 1.9889320e+01 1.37e-04 8.79e+01 -1.7 2.17e-04 5.6 1.00e+00 1.00e+00h 1 99 1.9889453e+01 2.44e-06 3.70e+01 -1.7 2.68e-04 5.1 1.00e+00 1.00e+00h 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 100 1.9889291e+01 7.77e-07 1.17e+00 -1.7 2.54e-05 4.7 1.00e+00 1.00e+00h 1 101 1.9888791e+01 8.43e-09 1.03e+00 -1.7 6.72e-05 4.2 1.00e+00 1.00e+00h 1 102 1.9887294e+01 4.08e-08 1.04e+00 -1.7 2.03e-04 3.7 1.00e+00 1.00e+00f 1 103 1.9882803e+01 3.70e-07 1.04e+00 -1.7 6.10e-04 3.2 1.00e+00 1.00e+00f 1 104 1.9869322e+01 3.34e-06 1.04e+00 -1.7 1.83e-03 2.8 1.00e+00 1.00e+00f 1 105 1.9828829e+01 3.02e-05 1.04e+00 -1.7 5.49e-03 2.3 1.00e+00 1.00e+00f 1 106 1.9706903e+01 2.75e-04 1.04e+00 -1.7 1.65e-02 1.8 1.00e+00 1.00e+00f 1 107 1.9337358e+01 2.57e-03 1.06e+00 -1.7 5.04e-02 1.3 1.00e+00 1.00e+00f 1 108 1.8202727e+01 2.37e-02 1.03e+00 -1.7 1.54e-01 0.8 1.00e+00 1.00e+00f 1 109 1.4758607e+01 2.13e-01 1.16e+00 -1.7 4.75e-01 0.4 1.00e+00 1.00e+00f 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 110 3.7168507e+00 3.35e+00 4.10e+00 -1.7 2.09e+00 -0.1 1.00e+00 1.00e+00f 1 111 5.5254855e+00 7.47e-01 1.22e+01 -1.7 8.38e-01 1.2 1.00e+00 1.00e+00h 1 112 6.6807345e+00 2.67e-01 1.31e+01 -1.7 4.69e-01 1.6 1.00e+00 1.00e+00h 1 113 7.8533879e+00 2.14e-02 2.79e+00 -1.7 2.41e-01 - 1.00e+00 1.00e+00h 1 114 7.1452945e+00 4.82e-02 5.16e-01 -1.7 3.33e-01 - 1.00e+00 1.00e+00f 1 115 7.2255909e+00 3.28e-02 1.05e-01 -1.7 1.37e-01 - 1.00e+00 1.00e+00h 1 116 7.3670454e+00 2.07e-03 3.04e-03 -2.5 5.64e-02 - 1.00e+00 1.00e+00h 1 117 7.3730869e+00 1.90e-06 1.40e-05 -3.8 1.35e-03 - 1.00e+00 1.00e+00h 1 118 7.3730955e+00 4.85e-12 5.15e-11 -8.6 2.86e-06 - 1.00e+00 1.00e+00h 1 Number of Iterations....: 118 (scaled) (unscaled) Objective...............: 7.3730955000157827e+00 7.3730955000157827e+00 Dual infeasibility......: 5.1451620741715942e-11 5.1451620741715942e-11 Constraint violation....: 4.8540060859636469e-12 4.8540060859636469e-12 Variable bound violation: 0.0000000000000000e+00 0.0000000000000000e+00 Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00 Overall NLP error.......: 5.1451620741715942e-11 5.1451620741715942e-11 Number of objective function evaluations = 148 Number of objective gradient evaluations = 108 Number of equality constraint evaluations = 148 Number of inequality constraint evaluations = 0 Number of equality constraint Jacobian evaluations = 120 Number of inequality constraint Jacobian evaluations = 0 Number of Lagrangian Hessian evaluations = 118 Total seconds in IPOPT = 0.059 EXIT: Optimal Solution Found.
solution_summary(model)
* Solver : Ipopt * Status Result count : 1 Termination status : LOCALLY_SOLVED Message from the solver: "Solve_Succeeded" * Candidate solution (result #1) Primal status : FEASIBLE_POINT Dual status : FEASIBLE_POINT Objective value : 7.37310e+00 Dual objective value : 1.87720e+01 * Work counters Solve time (sec) : 6.00870e-02 Barrier iterations : 118
Pojďme se výslednou křivku nakreslit!
using PyPlot
Souřadnice bodů:
xs = value.(x)
ys = value.(y);
A graf:
fig, ax = plt.subplots()
ax.axis("equal")
ax.grid()
scatter([0, D], [a, a], 50, color="red")
plot(xs, ys)
1-element Vector{PyCall.PyObject}: PyObject <matplotlib.lines.Line2D object at 0x7fb7a5937950>
Tato křivka se dá popsat analyticky pomocí kosinu hyperbolického a má dokonce jméno, jde o catenarii, česky "řetězovku". Sice připomíná parabolu, ale není to parabola!
Dále k této lekci přikládáme Pluto notebook, kde si s touto úlohou můžete interaktivněji pohrát.
3.3 Sudoku
Populární hlavolam Sudoku asi není potřeba představovat.
Zde si ukážeme, jak problém nalezení řešení Sudoku hlavolamu lze zformulovat jakožto lineární program s binárními proměnnými. Objektivní funkci bychom mohli formálně zadat třeba konstantní, není potřeba. Budeme hledat pouze nějaké přípustné řešení.
Použijeme GLPK řešič, který umí řešit úlohy lineární programování i s celočíselnými proměnnými (binární proměnné do této škatulky také spadnou).
Nezapomeňte nainstalovat Julia balíček poskytující tento řešič, tj. ] add GLPK
.
using JuMP, GLPK
Klíčem k úspěchu je následující pohled na sudoku problém: místo čísel až v matici si představme jedničky a nuly v krychli . Krychle je vyplněna nulami, jen a pouze je-li v původní matici hodnota , pak tomu odpovídá hodnota .
Nyní se stačí zamyslet jak popsat podmínky na správné Sudoku řešení (cifry se nesmí opakovat v řádcích, sloupcích a v devíti podblocích. Zároveň musíme ctít zadání.
function sudoku_solver(puzzle::Matrix{Int64})
if size(puzzle, 1) != 9 || size(puzzle, 2) != 9
error("Sudoku puzzle has to be a 9x9 matrix!")
end
# let's use the GLPK solver
model = Model(GLPK.Optimizer)
# now we define our variables, 9^3 of them, do not be afraid!
@variable(model, x[i=1:9, j=1:9, k=1:9], Bin)
for i in 1:9, j in 1:9
# only one digit at each site
@constraint(model, sum(x[i, j, k] for k=1:9) == 1)
# fix prescribed variables
if puzzle[i, j] != 0
fix(x[i, j, puzzle[i, j]], 1, force=true)
end
end
for i=1:9, k=1:9
@constraint(model, sum(x[i, j, k] for j=1:9) == 1)
@constraint(model, sum(x[j, i, k] for j=1:9) == 1)
end
for i=0:2, j=0:2, k=1:9
@constraint(model, sum(x[3i+l, 3j+m, k] for l=1:3, m=1:3) == 1)
end
# solve it!
optimize!(model)
@info solution_summary(model)
# extract a solution a return it in the matrix form
solution = value.(x)
return Int64[ findfirst(isone, solution[i, j, :]) for i=1:9, j=1:9 ]
end
sudoku_solver (generic function with 1 method)
Zkusme vyřešit nějaké Sudoku a nebuďme přízemní. Následující zadání je Evil obtížnost z webu sudoku.com:
Sudoku evil is a 9×9 grid sudoku puzzle with the highest possible level of difficulty. It’s an advanced level only for experienced sudoku solvers. Simple logic and basic knowledge of sudoku rules won’t cut it – you as a player should know advanced sudoku solving techniques and understand how to apply them in practice.
🤘 = [
4 0 0 0 7 8 0 0 3
0 0 0 2 0 0 0 0 0
0 0 9 0 0 0 0 1 0
0 1 0 0 6 2 0 3 0
0 0 0 4 0 0 0 0 2
6 0 0 5 0 0 0 0 0
0 4 0 0 0 0 7 0 0
7 0 0 0 3 6 0 0 8
0 0 0 0 5 0 0 0 0
];
sudoku_solver(🤘)
┌ Info: * Solver : GLPK │ │ * Status │ Result count : 1 │ Termination status : OPTIMAL │ Message from the solver: │ "Solution is optimal" │ │ * Candidate solution (result #1) │ Primal status : FEASIBLE_POINT │ Dual status : NO_SOLUTION │ Objective value : 0.00000e+00 │ Objective bound : 0.00000e+00 │ Relative gap : 0.00000e+00 │ │ * Work counters └ Solve time (sec) : 3.97990e-02
9×9 Matrix{Int64}: 4 5 1 6 7 8 9 2 3 3 7 6 2 9 1 4 8 5 2 8 9 3 4 5 6 1 7 5 1 7 9 6 2 8 3 4 9 3 8 4 1 7 5 6 2 6 2 4 5 8 3 1 7 9 1 4 3 8 2 9 7 5 6 7 9 5 1 3 6 2 4 8 8 6 2 7 5 4 3 9 1
multi = zeros(Int64, 9, 9)
9×9 Matrix{Int64}: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
sudoku_solver(multi)
┌ Info: * Solver : GLPK │ │ * Status │ Result count : 1 │ Termination status : OPTIMAL │ Message from the solver: │ "Solution is optimal" │ │ * Candidate solution (result #1) │ Primal status : FEASIBLE_POINT │ Dual status : NO_SOLUTION │ Objective value : 0.00000e+00 │ Objective bound : 0.00000e+00 │ Relative gap : 0.00000e+00 │ │ * Work counters └ Solve time (sec) : 4.52404e-01
9×9 Matrix{Int64}: 5 2 7 6 4 1 8 3 9 1 9 3 5 7 8 4 2 6 6 8 4 2 9 3 7 1 5 4 5 8 3 1 7 9 6 2 7 6 1 8 2 9 3 5 4 9 3 2 4 6 5 1 8 7 2 7 6 1 3 4 5 9 8 8 1 9 7 5 6 2 4 3 3 4 5 9 8 2 6 7 1
3.4 Exponenciální fit
V poslední době jste jistě zaslechli o exponenciálním růstu, resp. funkci, a odhadu parametrů tohoto růstu z dat. Jak v časové řadě (posloupnost číselných dat) takovéto chování odhalit a jak odhadnout jeho parametry?
K tomu lze využít metodu nejmenších čtverců (není to jediný způsob). Předpokládejme, že máme naměřené hodnoty nějaké veličiny v časových okamžicích (nezávisle proměnná nutně nemusí být čas ). Dále máme podezření, že hypotetická závislost se chová exponenciálně, obecně třeba ve tvaru , kde je trojice neznámých reálných parametrů.
Naším cílem je nalézt hodnoty těchto neznámých parametrů tak, aby výsledná funkční závislost co nejlépe vystihovala naměřená data. Ve smyslu metody nejmenších čtverců tím máme na mysli, aby funkce nabývala své minimální hodnoty (tj. aby součet kvadrátů odchylek byl nejmenší možný, odtud název metody).
Očividně se jedná o nelineární problém. Použijeme Ipopt řešič (] add Ipopt
).
using JuMP, Ipopt, PyPlot
function expfit(ts, ys; max_iter=100, optimizer=Ipopt.Optimizer)
model = Model(optimizer)
if optimizer == Ipopt.Optimizer
set_optimizer_attribute(model, "max_iter", max_iter)
end
if max_iter > 100
set_silent(model)
end
# variables
@variable(model, a[i = 1:3])
# non-linear objective function
@NLobjective(model, Min, sum((a[1] * exp(a[2] * ts[j]) + a[3] - ys[j])^2 for j=1:length(ts)))
# solve it!
optimize!(model)
@info solution_summary(model)
return objective_value(model), value.(a)
end
expfit (generic function with 1 method)
Příklad č. 1
Testovací data, exponenciální růst plus šum.
ts = LinRange(-1, 4, 50)
ys = [ 0.323 * exp(1.56 * t) - 2.453 + 4*(rand() - 0.5) for t in ts ];
Grafické znázornění.
fig, ax = plt.subplots()
ax.grid()
ax.set_xlabel(raw"$t$")
ax.set_ylabel(raw"$y$")
scatter(ts, ys, s=2);
_, params = expfit(ts, ys)
This is Ipopt version 3.14.13, running with linear solver MUMPS 5.6.1. Number of nonzeros in equality constraint Jacobian...: 0 Number of nonzeros in inequality constraint Jacobian.: 0 Number of nonzeros in Lagrangian Hessian.............: 6 Total number of variables............................: 3 variables with only lower bounds: 0 variables with lower and upper bounds: 0 variables with only upper bounds: 0 Total number of equality constraints.................: 0 Total number of inequality constraints...............: 0 inequality constraints with only lower bounds: 0 inequality constraints with lower and upper bounds: 0 inequality constraints with only upper bounds: 0 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 0 9.4883746e+04 0.00e+00 1.00e+02 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0 1 9.4843691e+04 0.00e+00 1.00e+02 -1.0 1.00e-02 4.0 1.00e+00 1.00e+00f 1 2 9.4721840e+04 0.00e+00 1.01e+02 -1.0 3.04e-02 3.5 1.00e+00 1.00e+00f 1 3 9.4266579e+04 0.00e+00 1.21e+02 -1.0 1.08e-01 3.0 1.00e+00 1.00e+00f 1 4 9.4034657e+04 0.00e+00 1.35e+02 -1.0 4.54e-02 3.5 1.00e+00 1.00e+00f 1 5 8.8372276e+04 0.00e+00 1.07e+03 -1.0 4.01e-01 3.0 1.00e+00 1.00e+00f 1 6 8.6343648e+04 0.00e+00 1.42e+03 -1.0 6.53e-02 4.3 1.00e+00 1.00e+00f 1 7 8.2231820e+03 0.00e+00 6.69e+03 -1.0 1.32e+00 3.8 1.00e+00 5.00e-01f 2 8 1.0388952e+03 0.00e+00 2.98e+03 -1.0 1.27e+01 - 1.00e+00 5.00e-01f 2 9 4.8095098e+02 0.00e+00 2.06e+02 -1.0 4.02e-02 3.4 1.00e+00 1.00e+00f 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 10 4.3889466e+02 0.00e+00 8.87e+01 -1.0 4.84e-02 2.9 1.00e+00 1.00e+00f 1 11 3.1322960e+02 0.00e+00 8.60e+02 -1.0 3.89e+00 - 1.00e+00 2.50e-01f 3 12 1.6657525e+02 0.00e+00 2.44e+02 -1.0 1.30e+00 - 1.00e+00 1.00e+00f 1 13 1.2526119e+02 0.00e+00 3.89e+02 -1.0 7.23e-01 - 1.00e+00 5.00e-01f 2 14 8.7824846e+01 0.00e+00 2.55e+02 -1.0 3.56e-01 - 1.00e+00 1.00e+00f 1 15 7.1082224e+01 0.00e+00 1.53e+02 -1.0 2.67e-01 - 1.00e+00 1.00e+00f 1 16 6.5362405e+01 0.00e+00 6.72e+01 -1.0 1.72e-01 - 1.00e+00 1.00e+00f 1 17 6.4220130e+01 0.00e+00 1.98e+01 -1.0 9.13e-02 - 1.00e+00 1.00e+00f 1 18 6.4140205e+01 0.00e+00 1.69e+00 -1.0 2.66e-02 - 1.00e+00 1.00e+00f 1 19 6.4139585e+01 0.00e+00 1.60e-02 -1.0 2.57e-03 - 1.00e+00 1.00e+00f 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 20 6.4139584e+01 0.00e+00 1.11e-06 -3.8 2.15e-05 - 1.00e+00 1.00e+00f 1 21 6.4139584e+01 0.00e+00 4.03e-12 -8.6 1.72e-09 - 1.00e+00 1.00e+00f 1 Number of Iterations....: 21 (scaled) (unscaled) Objective...............: 3.2020008477137938e+00 6.4139584474420630e+01 Dual infeasibility......: 4.0296176091009870e-12 8.0717654782347381e-11 Constraint violation....: 0.0000000000000000e+00 0.0000000000000000e+00 Variable bound violation: 0.0000000000000000e+00 0.0000000000000000e+00 Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00 Overall NLP error.......: 4.0296176091009870e-12 8.0717654782347381e-11 Number of objective function evaluations = 43 Number of objective gradient evaluations = 22 Number of equality constraint evaluations = 0 Number of inequality constraint evaluations = 0 Number of equality constraint Jacobian evaluations = 0 Number of inequality constraint Jacobian evaluations = 0 Number of Lagrangian Hessian evaluations = 21 Total seconds in IPOPT = 2.111 EXIT: Optimal Solution Found.
┌ Info: * Solver : Ipopt │ │ * Status │ Result count : 1 │ Termination status : LOCALLY_SOLVED │ Message from the solver: │ "Solve_Succeeded" │ │ * Candidate solution (result #1) │ Primal status : FEASIBLE_POINT │ Dual status : FEASIBLE_POINT │ Objective value : 6.41396e+01 │ Dual objective value : 0.00000e+00 │ │ * Work counters │ Solve time (sec) : 2.11231e+00 └ Barrier iterations : 21
(64.13958447442063, [0.3376676953938057, 1.5474475912708303, -2.5111244132467])
Prostým porovnáním čísel, která jsme k vygenerování dat použili je vidět, že jsme dostali asi docela rozumné řešení. Znázorněme ho graficky.
fig, ax = plt.subplots()
ax.grid()
ax.set_xlabel(raw"$t$")
ax.set_ylabel(raw"$y$")
scatter(ts, ys, s=3);
plot(ts, [ params[1] * exp(params[2] * t) + params[3] for t in ts ], "r");
Příklad č. 2
Testovací data, exponenciála nemusí nutně jenom růst!
ts = LinRange(0, 7, 100)
ys = [ -2.111 * exp(-0.687 * t) + 8.453 + (rand() - 0.5) / (t^2 + 1) for t in ts ];
Grafické znázornění.
fig, ax = plt.subplots()
ax.grid()
ax.set_xlabel(raw"$t$")
ax.set_ylabel(raw"$y$")
scatter(ts, ys, s=2);
_, params = expfit(ts, ys)
This is Ipopt version 3.14.13, running with linear solver MUMPS 5.6.1. Number of nonzeros in equality constraint Jacobian...: 0 Number of nonzeros in inequality constraint Jacobian.: 0 Number of nonzeros in Lagrangian Hessian.............: 6 Total number of variables............................: 3 variables with only lower bounds: 0 variables with lower and upper bounds: 0 variables with only upper bounds: 0 Total number of equality constraints.................: 0 Total number of inequality constraints...............: 0 inequality constraints with only lower bounds: 0 inequality constraints with lower and upper bounds: 0 inequality constraints with only upper bounds: 0 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 0 6.4439446e+03 0.00e+00 1.00e+02 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0 1 6.4119880e+03 0.00e+00 9.99e+01 -1.0 9.99e-03 4.0 1.00e+00 1.00e+00f 1 2 6.3155368e+03 0.00e+00 1.01e+02 -1.0 3.02e-02 3.5 1.00e+00 1.00e+00f 1 3 5.9643211e+03 0.00e+00 1.18e+02 -1.0 1.05e-01 3.0 1.00e+00 1.00e+00f 1 4 5.7841892e+03 0.00e+00 1.32e+02 -1.0 4.43e-02 3.5 1.00e+00 1.00e+00f 1 5 3.3149795e+03 0.00e+00 5.61e+02 -1.0 6.18e-01 3.0 1.00e+00 5.00e-01f 2 6 2.6092943e+03 0.00e+00 1.51e+02 -1.0 6.41e-01 2.5 1.00e+00 1.25e-01f 4 7 1.1571382e+02 0.00e+00 1.27e+02 -1.0 7.22e+00 - 1.00e+00 1.00e+00f 1 8 4.4635213e+01 0.00e+00 4.98e+01 -1.0 3.42e-02 2.9 1.00e+00 1.00e+00f 1 9 2.0833417e+01 0.00e+00 1.55e+01 -1.0 3.52e-02 2.5 1.00e+00 1.00e+00f 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 10 1.6540143e+01 0.00e+00 4.38e+00 -1.0 1.72e-02 2.0 1.00e+00 1.00e+00f 1 11 1.5510315e+01 0.00e+00 1.10e+00 -1.0 3.35e-02 1.5 1.00e+00 1.00e+00f 1 12 1.4711122e+01 0.00e+00 2.38e+00 -1.0 7.62e+00 - 1.00e+00 1.56e-02f 7 13 1.3886177e+01 0.00e+00 1.40e+00 -1.0 7.94e-02 - 1.00e+00 1.00e+00f 1 14 1.3223782e+01 0.00e+00 2.83e+00 -1.0 1.67e-01 - 1.00e+00 1.00e+00f 1 15 1.2535867e+01 0.00e+00 9.29e-01 -1.0 1.49e-01 - 1.00e+00 1.00e+00f 1 16 1.2250846e+01 0.00e+00 6.19e+00 -1.7 2.96e-01 - 1.00e+00 1.00e+00f 1 17 1.1474913e+01 0.00e+00 1.01e+00 -1.7 1.74e-01 - 1.00e+00 1.00e+00f 1 18 1.1149344e+01 0.00e+00 4.64e+00 -1.7 2.66e+00 - 1.00e+00 1.25e-01f 4 19 1.0728972e+01 0.00e+00 7.36e-01 -1.7 2.17e-01 - 1.00e+00 1.00e+00f 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 20 1.0509706e+01 0.00e+00 3.79e+00 -1.7 6.65e-01 - 1.00e+00 5.00e-01f 2 21 1.0229961e+01 0.00e+00 1.92e+00 -1.7 3.45e-01 - 1.00e+00 1.00e+00f 1 22 1.0069532e+01 0.00e+00 6.99e+00 -1.7 5.80e-01 - 1.00e+00 1.00e+00f 1 23 9.8138907e+00 0.00e+00 2.99e-01 -1.7 3.38e-01 - 1.00e+00 1.00e+00f 1 24 9.7529347e+00 0.00e+00 9.50e+00 -1.7 1.49e+00 - 1.00e+00 5.00e-01f 2 25 9.5239960e+00 0.00e+00 1.54e-01 -1.7 3.71e-01 - 1.00e+00 1.00e+00f 1 26 9.4366815e+00 0.00e+00 5.31e+00 -2.5 2.65e+00 - 1.00e+00 2.50e-01f 3 27 9.3246406e+00 0.00e+00 2.48e+00 -2.5 6.01e-01 - 1.00e+00 1.00e+00f 1 28 9.2750008e+00 0.00e+00 1.06e+01 -2.5 1.09e+00 - 1.00e+00 1.00e+00f 1 29 9.1552349e+00 0.00e+00 2.51e-01 -2.5 5.21e-01 - 1.00e+00 1.00e+00f 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 30 9.1074542e+00 0.00e+00 4.83e+00 -2.5 3.22e+00 - 1.00e+00 2.50e-01f 3 31 9.0472471e+00 0.00e+00 4.95e+00 -2.5 9.77e-01 - 1.00e+00 1.00e+00f 1 32 8.9950178e+00 0.00e+00 5.31e+00 -2.5 1.07e+00 - 1.00e+00 1.00e+00f 1 33 8.9488758e+00 0.00e+00 5.23e+00 -2.5 1.13e+00 - 1.00e+00 1.00e+00f 1 34 8.9091114e+00 0.00e+00 6.00e+00 -2.5 1.26e+00 - 1.00e+00 1.00e+00f 1 35 8.8728955e+00 0.00e+00 5.17e+00 -2.5 1.26e+00 - 1.00e+00 1.00e+00f 1 36 8.8431673e+00 0.00e+00 7.54e+00 -2.5 1.53e+00 - 1.00e+00 1.00e+00f 1 37 8.8134638e+00 0.00e+00 4.04e+00 -2.5 1.28e+00 - 1.00e+00 1.00e+00f 1 38 8.7983196e+00 0.00e+00 1.39e+01 -2.5 2.18e+00 - 1.00e+00 1.00e+00f 1 39 8.7662438e+00 0.00e+00 1.06e+00 -2.5 1.01e+00 - 1.00e+00 1.00e+00f 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 40 8.7530068e+00 0.00e+00 5.86e+00 -2.5 5.66e+00 - 1.00e+00 2.50e-01f 3 41 8.7360734e+00 0.00e+00 9.33e+00 -2.5 2.09e+00 - 1.00e+00 1.00e+00f 1 42 8.7181458e+00 0.00e+00 4.13e+00 -2.5 1.61e+00 - 1.00e+00 1.00e+00f 1 43 8.7143049e+00 0.00e+00 2.00e+01 -2.5 3.17e+00 - 1.00e+00 1.00e+00f 1 44 8.6890793e+00 0.00e+00 4.80e-01 -2.5 1.13e+00 - 1.00e+00 1.00e+00f 1 45 8.6815982e+00 0.00e+00 1.34e+01 -2.5 1.09e+01 - 1.00e+00 2.50e-01f 3 46 8.6680113e+00 0.00e+00 2.64e+00 -2.5 1.63e+00 - 1.00e+00 1.00e+00f 1 47 8.6617196e+00 0.00e+00 1.37e+01 -2.5 5.78e+00 - 1.00e+00 5.00e-01f 2 48 8.6504190e+00 0.00e+00 2.93e+00 -2.5 1.81e+00 - 1.00e+00 1.00e+00f 1 49 8.6449297e+00 0.00e+00 1.36e+01 -2.5 6.14e+00 - 1.00e+00 5.00e-01f 2 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 50 8.6356082e+00 0.00e+00 3.48e+00 -2.5 2.04e+00 - 1.00e+00 1.00e+00f 1 51 8.6306724e+00 0.00e+00 1.25e+01 -2.5 6.17e+00 - 1.00e+00 5.00e-01f 2 52 8.6231507e+00 0.00e+00 4.88e+00 -2.5 2.44e+00 - 1.00e+00 1.00e+00f 1 53 8.6188679e+00 0.00e+00 9.53e+00 -2.5 5.41e+00 - 1.00e+00 5.00e-01f 2 54 8.6129752e+00 0.00e+00 9.43e+00 -2.5 3.34e+00 - 1.00e+00 1.00e+00f 1 55 8.6076206e+00 0.00e+00 1.03e+01 -2.5 3.58e+00 - 1.00e+00 1.00e+00f 1 56 8.6025576e+00 0.00e+00 9.30e+00 -2.5 3.55e+00 - 1.00e+00 1.00e+00f 1 57 8.5981256e+00 0.00e+00 1.20e+01 -2.5 4.08e+00 - 1.00e+00 1.00e+00f 1 58 8.5936404e+00 0.00e+00 7.79e+00 -2.5 3.51e+00 - 1.00e+00 1.00e+00f 1 59 8.5906353e+00 0.00e+00 1.88e+01 -2.5 5.28e+00 - 1.00e+00 1.00e+00f 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 60 8.5860120e+00 0.00e+00 3.40e+00 -2.5 2.74e+00 - 1.00e+00 1.00e+00f 1 61 8.5842791e+00 0.00e+00 2.15e+01 -2.5 1.12e+01 - 1.00e+00 5.00e-01f 2 62 8.5799147e+00 0.00e+00 2.80e+00 -2.5 2.72e+00 - 1.00e+00 1.00e+00f 1 63 8.5796677e+00 0.00e+00 3.04e+01 -2.5 1.41e+01 - 1.00e+00 5.00e-01f 2 64 8.5742860e+00 0.00e+00 1.19e+00 -2.5 2.33e+00 - 1.00e+00 1.00e+00f 1 65 8.5728722e+00 0.00e+00 2.20e+01 -2.5 2.54e+01 - 1.00e+00 2.50e-01f 3 66 8.5696422e+00 0.00e+00 3.39e+00 -2.5 3.20e+00 - 1.00e+00 1.00e+00f 1 67 8.5689457e+00 0.00e+00 2.85e+01 -2.5 1.51e+01 - 1.00e+00 5.00e-01f 2 68 8.5654018e+00 0.00e+00 2.00e+00 -2.5 2.87e+00 - 1.00e+00 1.00e+00f 1 69 8.5640113e+00 0.00e+00 1.60e+01 -2.5 2.34e+01 - 1.00e+00 2.50e-01f 3 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 70 8.5619278e+00 0.00e+00 8.32e+00 -2.5 4.92e+00 - 1.00e+00 1.00e+00f 1 71 8.5611434e+00 0.00e+00 3.04e+01 -2.5 8.94e+00 - 1.00e+00 1.00e+00f 1 72 8.5583459e+00 0.00e+00 2.16e+00 -2.5 3.22e+00 - 1.00e+00 1.00e+00f 1 73 8.5572556e+00 0.00e+00 1.74e+01 -2.5 2.67e+01 - 1.00e+00 2.50e-01f 3 74 8.5555962e+00 0.00e+00 8.48e+00 -2.5 5.43e+00 - 1.00e+00 1.00e+00f 1 75 8.5551914e+00 0.00e+00 3.51e+01 -2.5 1.05e+01 - 1.00e+00 1.00e+00f 1 76 8.5527232e+00 0.00e+00 1.85e+00 -2.5 3.38e+00 - 1.00e+00 1.00e+00f 1 77 8.5519591e+00 0.00e+00 2.40e+01 -2.5 3.48e+01 - 1.00e+00 2.50e-01f 3 78 8.5504641e+00 0.00e+00 5.22e+00 -2.5 4.89e+00 - 1.00e+00 1.00e+00f 1 79 8.5498032e+00 0.00e+00 2.57e+01 -2.5 1.84e+01 - 1.00e+00 5.00e-01f 2 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 80 8.5484141e+00 0.00e+00 4.89e+00 -2.5 4.96e+00 - 1.00e+00 1.00e+00f 1 81 8.5479288e+00 0.00e+00 3.02e+01 -2.5 2.09e+01 - 1.00e+00 5.00e-01f 2 82 8.5465284e+00 0.00e+00 3.72e+00 -2.5 4.68e+00 - 1.00e+00 1.00e+00f 1 83 8.5459104e+00 0.00e+00 1.39e+01 -2.5 2.77e+01 - 1.00e+00 2.50e-01f 3 84 8.5450608e+00 0.00e+00 1.99e+01 -2.5 9.65e+00 - 1.00e+00 1.00e+00f 1 85 8.5441303e+00 0.00e+00 1.03e+01 -2.5 7.36e+00 - 1.00e+00 1.00e+00f 1 86 8.5438094e+00 0.00e+00 3.80e+01 -2.5 1.36e+01 - 1.00e+00 1.00e+00f 1 87 8.5425029e+00 0.00e+00 2.68e+00 -2.5 4.63e+00 - 1.00e+00 1.00e+00f 1 88 8.5420163e+00 0.00e+00 2.34e+01 -2.5 4.19e+01 - 1.00e+00 2.50e-01f 3 89 8.5412187e+00 0.00e+00 8.66e+00 -2.5 7.37e+00 - 1.00e+00 1.00e+00f 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 90 8.5407538e+00 0.00e+00 1.89e+01 -2.5 1.82e+01 - 1.00e+00 5.00e-01f 2 91 8.5400777e+00 0.00e+00 1.42e+01 -2.5 9.43e+00 - 1.00e+00 1.00e+00f 1 92 8.5395436e+00 0.00e+00 2.58e+01 -2.5 1.26e+01 - 1.00e+00 1.00e+00f 1 93 8.5388629e+00 0.00e+00 8.18e+00 -2.5 7.72e+00 - 1.00e+00 1.00e+00f 1 94 8.5384782e+00 0.00e+00 2.26e+01 -2.5 2.18e+01 - 1.00e+00 5.00e-01f 2 95 8.5378889e+00 0.00e+00 1.15e+01 -2.5 9.20e+00 - 1.00e+00 1.00e+00f 1 96 8.5377193e+00 0.00e+00 4.41e+01 -2.5 1.74e+01 - 1.00e+00 1.00e+00f 1 97 8.5368490e+00 0.00e+00 2.85e+00 -2.5 5.60e+00 - 1.00e+00 1.00e+00f 1 98 8.5365587e+00 0.00e+00 2.97e+01 -2.5 5.63e+01 - 1.00e+00 2.50e-01f 3 99 8.5360129e+00 0.00e+00 7.56e+00 -2.5 8.25e+00 - 1.00e+00 1.00e+00f 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 100 8.5357394e+00 0.00e+00 2.97e+01 -2.5 2.83e+01 - 1.00e+00 5.00e-01f 2 Number of Iterations....: 100 (scaled) (unscaled) Objective...............: 5.3291095876669436e-01 8.5357393719049774e+00 Dual infeasibility......: 2.9676242223953846e+01 4.7533019352317166e+02 Constraint violation....: 0.0000000000000000e+00 0.0000000000000000e+00 Variable bound violation: 0.0000000000000000e+00 0.0000000000000000e+00 Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00 Overall NLP error.......: 2.9676242223953846e+01 4.7533019352317166e+02 Number of objective function evaluations = 266 Number of objective gradient evaluations = 101 Number of equality constraint evaluations = 0 Number of inequality constraint evaluations = 0 Number of equality constraint Jacobian evaluations = 0 Number of inequality constraint Jacobian evaluations = 0 Number of Lagrangian Hessian evaluations = 100 Total seconds in IPOPT = 0.080 EXIT: Maximum Number of Iterations Exceeded.
┌ Info: * Solver : Ipopt │ │ * Status │ Result count : 1 │ Termination status : ITERATION_LIMIT │ Message from the solver: │ "Maximum_Iterations_Exceeded" │ │ * Candidate solution (result #1) │ Primal status : UNKNOWN_RESULT_STATUS │ Dual status : UNKNOWN_RESULT_STATUS │ Objective value : 8.53574e+00 │ Dual objective value : 0.00000e+00 │ │ * Work counters │ Solve time (sec) : 8.12089e-02 └ Barrier iterations : 100
(8.535739371904977, [385.0462934776301, 0.0005896836512244834, -377.8348304333786])
Znázorněme ho graficky.
fig, ax = plt.subplots()
ax.grid()
ax.set_xlabel(raw"$t$")
ax.set_ylabel(raw"$y$")
scatter(ts, ys, s=3);
plot(ts, [ params[1] * exp(params[2] * t) + params[3] for t in ts ], "r");
To nevypadá příliš dobře, dejme řešiči více možnost více iterací.
_, params = expfit(ts, ys, max_iter=10_000)
┌ Info: * Solver : Ipopt │ │ * Status │ Result count : 1 │ Termination status : ITERATION_LIMIT │ Message from the solver: │ "Maximum_Iterations_Exceeded" │ │ * Candidate solution (result #1) │ Primal status : UNKNOWN_RESULT_STATUS │ Dual status : UNKNOWN_RESULT_STATUS │ Objective value : 8.52269e+00 │ Dual objective value : 0.00000e+00 │ │ * Work counters │ Solve time (sec) : 1.48282e+01 └ Barrier iterations : 10000
(8.522694557267773, [-1.2425073844388234e6, -1.8350810198451365e-7, 1.2425145950016542e6])
fig, ax = plt.subplots()
ax.grid()
ax.set_xlabel(raw"$t$")
ax.set_ylabel(raw"$y$")
scatter(ts, ys, s=3);
plot(ts, [ params[1] * exp(params[2] * t) + params[3] for t in ts ], "r");
Chování Ipopt je v tomto případě lehce náhodné!
_, params = expfit(ts, ys, optimizer=Gurobi.Optimizer)
Set parameter Username -------------------------------------------- Warning: your license will expire in 5 days -------------------------------------------- Academic license - for non-commercial use only - expires 2023-12-11
The solver does not support nonlinear problems (i.e., NLobjective and NLconstraint). Stacktrace: [1] error(s::String) @ Base ./error.jl:35 [2] optimize!(model::Model; ignore_optimize_hook::Bool, _differentiation_backend::MathOptInterface.Nonlinear.SparseReverseMode, kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}) @ JuMP ~/.julia/packages/JuMP/R53zo/src/optimizer_interface.jl:454 [3] optimize! @ ~/.julia/packages/JuMP/R53zo/src/optimizer_interface.jl:409 [inlined] [4] expfit(ts::LinRange{Float64, Int64}, ys::Vector{Float64}; max_iter::Int64, optimizer::Type) @ Main ./In[79]:19 [5] top-level scope @ In[80]:1
Řešení některých úloh
"Zemědělské" podmínky.
@variable(model, x[1:3] >= 0)
@constraint(model, x[1] + x[2] + x[3] == S)
@objective(model, Max, (v1 - p1 - o1) * x[1] + (v2 - p2 - o2) * x[2] - (v3 - p3 - o3) * x[3])
Sudoku solver.
function sudoku_solver(puzzle::Matrix{Int64})
if size(puzzle, 1) != 9 || size(puzzle, 2) != 9
error("Sudoku puzzle has to be a 9x9 matrix!")
end
# let's use the GLPK solver
model = Model(GLPK.Optimizer)
# now we define our variables, 9^3 of them, do not be afraid!
@variable(model, x[i=1:9, j=1:9, k=1:9], Bin)
for i in 1:9, j in 1:9
# only one digit at each site
@constraint(model, sum(x[i, j, k] for k=1:9) == 1)
# fix prescribed variables
if puzzle[i, j] != 0
fix(x[i, j, puzzle[i, j]], 1, force=true)
end
end
for i in 1:9, k in 1:9
# constraint rows
@constraint(model, sum(x[i, j, k] for j=1:9) == 1)
# constraint columns
@constraint(model, sum(x[j, i, k] for j=1:9) == 1)
end
# constraint boxes
for is in (1,4,7), js in (1,4,7), k in 1:9
@constraint(model, sum(x[i, j, k] for i=is:(is+2), j=js:(js+2)) == 1)
end
# solve it!
optimize!(model)
# @info solution_summary(model) ???
# extract a solution a return it in the matrix form
solution = value.(x)
return Int64[ findfirst(isone, solution[i, j, :]) for i=1:9, j=1:9 ]
end
Objektivní funkce v prokládání exponenciálou.
@NLobjective(model, Min, sum((a[1] * exp(a[2] * ts[j]) + a[3] - ys[j])^2 for j = axes(ts, 1)))
Reference
Hlavní stránku balíčku JuMP naleznete zde. K prozkoumání doporučuji podívat se na obsáhlou dokumentaci.
Pro nadšené studenty FIT zajímající se o optimalizační problémy by mohla být relativně přístupná přehledná monografie Boyd, Vandenberghe: Convex Optimization, Cambridge University Press, 2004.