Calcoli scientifici con Julia/Ottimizzazione del budget personale
L’ottimizzazione del budget personale è un classico problema di ricerca operativa, in cui bisogna definire variabili di spesa, imporre vincoli di bilancio e scegliere una funzione obiettivo. In particolare si può costruire un modello lineare o non lineare con utilità logaritmica (funzione obiettivo) che deve essere massimizzata.
In termini matematici il problema lineare è con n categorie di spesa :
quello non lineare:
dove:
- è la spesa allocata alla categoria
- è il peso (importanza relativa) della categoria
- è il budget totale disponibile
- è la spesa minima obbligatoria per la categoria
- è la spesa massima ammissibile per la categoria
I pesi di utilità rappresentano quanto una certa spesa contribuisce al benessere o alla soddisfazione della persona. Ad esempio supponiamo tre categorie di spesa:
| Spesa | Peso di utilità | | ------ | --------------- | | cibo | 3 | | svago | 1 | | viaggi | 4 |
quindi:
- 1 € speso in viaggi dà più soddisfazione
- 1 € speso in cibo dà utilità media
- 1 € speso in svago dà meno utilità
Quindi il modello non lineare cercherà di allocare più budget nelle categorie con peso maggiore massimizzando:
con i relativi vincoli di bilancio del tipo :
nel modello lineare invece si massimizza :
con :
e
I pesi si scelgono per valutazione soggettiva oppure osservando dove si spende di più e cosa si preferisce sacrificare.
Nel modello non lineare si utilizza la funzione logaritmo perché si può dimostrare che la soluzione ottima del problema nel caso non vincolato risulta:
ovvero ogni categoria di spesa riceve una quota proporzionale al proprio peso indipendentemente dal budget totale B.
Nel modello lineare, la soluzione ottima è sempre ai vertici del poliedro dei vincoli, cioè ogni categoria viene portata al suo minimo o al suo massimo, mai nel mezzo. Questo è un risultato fondamentale della programmazione lineare.
Con l'utilità logaritmica invece la soluzione è interna cioè ogni categoria riceve un'allocazione intermedia.
Implementazione in Julia
[modifica | modifica sorgente]Innanzitutto installo le librerie di Julia che mi servono:
using Pkg
Pkg.add("JuMP")
Pkg.add("Ipopt")
Pkg.add("HiGHS")
Modello lineare
[modifica | modifica sorgente]Si calcolano le variabili di spesa che massimizzano l'utilità soggette ai vari vincoli mediante la libreria HiGHS:
using JuMP, HiGHS
budget_totale = 3000.0 # € mensili
model = Model(HiGHS.Optimizer)
@variable(model,800 <= affitto <= 1000)
@variable(model,300 <= cibo <= 600)
@variable(model,100 <= trasporti <= 300)
@variable(model,0 <= svago <= 400)
@variable(model,100 <= risparmio <= 800)
@variable(model,0 <= vestiti <= 200)
@constraint(model, affitto + cibo + trasporti + svago + risparmio + vestiti <= budget_totale)
@objective(model, Max, 0.8*affitto +1.5*cibo +1.2*trasporti +2*svago + 1.8*risparmio +0.4*vestiti )
optimize!(model)
println("______________________________________________________________")
println("Affitto = ", value(affitto))
println("Cibo = ",value(cibo))
println("Trasporti = ",value(trasporti)),
println("Svago = ",value(svago))
println("Risparmio = ", value(risparmio))
println("Vestiti = ", value(vestiti))
Running HiGHS 1.13.1 (git hash: 1d267d97c): Copyright (c) 2026 under Apache 2.0 license terms Using BLAS: blastrampoline LP has 1 row; 6 cols; 6 nonzeros Coefficient ranges: Matrix [1e+00, 1e+00] Cost [4e-01, 2e+00] Bound [1e+02, 1e+03] RHS [3e+03, 3e+03] Presolving model 1 rows, 1 cols, 1 nonzeros 0s 0 rows, 0 cols, 0 nonzeros 0s Presolve reductions: rows 0(-1); columns 0(-6); nonzeros 0(-6) - Reduced to empty Performed postsolve Solving the original LP from the solution after postsolve Model status : Optimal Objective value : 4.2200000000e+03 P-D objective error : 0.0000000000e+00 HiGHS run time : 0.00 ______________________________________________________________ Affitto = 900.0 Cibo = 600.0 Trasporti = 300.0 Svago = 400.0 Risparmio = 800.0 Vestiti = 0.0
Questi valori massimizzano la funzione di utilità soggetta ai vincoli.
Modello non lineare
[modifica | modifica sorgente]Si calcolano le variabili di spesa che massimizzano l'utilità logaritmica soggette ai vari vincoli mediante la libreria Ipopt:
using JuMP, Ipopt
budget_totale = 3000.0 # € mensili
model_nl = Model(Ipopt.Optimizer)
set_optimizer_attribute(model_nl, "print_level", 0)
@variable(model_nl,800 <= affitto <= 1000)
@variable(model_nl,300 <= cibo <= 600)
@variable(model_nl,100 <= trasporti <= 300)
@variable(model_nl,0 <= svago <= 400)
@variable(model_nl,100 <= risparmio <= 800)
@variable(model_nl,0 <= vestiti <= 200)
@constraint(model_nl, affitto + cibo + trasporti + svago + risparmio + vestiti <= budget_totale)
# Utilità logaritmica: U(x) = w_i * log(x_i)
@objective(model_nl, Max, 0.8*log(affitto) +1.5*log(cibo) +1.2*log(trasporti) +2*log(svago) + 1.8*log(risparmio) +0.4*log(vestiti) )
optimize!(model_nl)
println("Affitto = ", value(affitto))
println("Cibo = ",value(cibo))
println("Trasporti = ",value(trasporti)),
println("Svago = ",value(svago))
println("Risparmio = ", value(risparmio))
println("Vestiti = ", value(vestiti))
******************************************************************************
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
******************************************************************************
Affitto = 800.0086863353699
Cibo = 599.4405027557945
Trasporti = 299.9919466163567
Svago = 399.9950988314647
Risparmio = 736.8257493821642
Vestiti = 163.7329107226028
Questi valori massimizzano la funzione di utilità soggetta ai vincoli.