Sto lavorando ad un programma in Python in cui una piccola parte comporta l'ottimizzazione di un sistema di equazioni/disuguaglianze. Idealmente, avrei voluto fare come si può fare in Modelica, scrivere le equazioni e lasciare che il risolutore si prenda cura di esso.Python - Ottimizza il sistema di disuguaglianza
L'operazione di risolutori e programmazione lineare è un po 'fuori dalla mia zona di comfort, ma ho deciso di provare comunque. Il problema è che il design generale del programma è orientato agli oggetti, e ci sono molte diverse possibilità di combinazioni per formare le equazioni, così come alcune non-linearità, quindi non sono stato in grado di tradurre questo in una programmazione lineare problema (ma potrei sbagliarmi).
Dopo alcune ricerche ho scoperto che il risolutore Z3 sembrava fare ciò che volevo. Sono venuto con questo (questo appare come un tipico caso di quello che vorrei per ottimizzare):
from z3 import *
a = Real('a')
b = Real('b')
c = Real('c')
d = Real('d')
e = Real('e')
g = Real('g')
f = Real('f')
cost = Real('cost')
opt = Optimize()
opt.add(a + b - 350 == 0)
opt.add(a - g == 0)
opt.add(c - 400 == 0)
opt.add(b - d * 0.45 == 0)
opt.add(c - f - e - d == 0)
opt.add(d <= 250)
opt.add(e <= 250)
opt.add(cost == If(f > 0, f * 50, f * 0.4) + e * 40 + d * 20 +
If(g > 0, g * 50, g * 0.54))
h = opt.minimize(cost)
opt.check()
opt.lower(h)
opt.model()
Ora questo funziona, e mi dà il risultato che voglio, nonostante non sia estremamente veloce (ho bisogno di risolvere tali sistemi diverse migliaia di volte). Ma non sono sicuro di utilizzare lo strumento giusto per il lavoro (Z3 è un "dimostratore di teoremi").
L'API è fondamentalmente esattamente ciò di cui ho bisogno, ma sarei curioso se altri pacchetti consentano una sintassi simile. O dovrei provare a formulare il problema in un modo diverso per consentire un approccio LP standard? (anche se non ho idea di come)
Un solutore LP dovrebbe essere in grado di risolvere questo in circa 0 secondi, in quanto questo è veramente piccolo. –
Sì, ma come posso gestire un numero di condizioni "se" nella funzione? Le soluzioni che ho visto sembrano un po '"hackish" e non funzionerebbero nel mio caso. –
Penso che questo possa essere implementato usando la divisione variabile. Vale a dire. introdurre variabili non negative 'fplus, fmin'. Aggiungi il vincolo 'f = fplus-fmin'. Il primo 'if' diventa:' 50 fplus-0.4 fmin'. –