2009-07-24 23 views
6

Mi chiedevo se qualcuno avesse qualche suggerimento per minimizzare una funzione, f (x, y), dove x e y sono numeri interi. Ho ricercato molte tecniche di minimizzazione e ottimizzazione, come BFGS e altri di GSL, e cose da ricette numeriche. Finora, ho provato a impiantare un paio di schemi diversi. Il primo funziona selezionando la direzione della più grande discesa f (x + 1, y), f (x-1, y), f (x, y + 1), f (x, y-1) e segui quella direzione con minimizzazione della linea. Ho anche provato a usare un metodo downhill simplex (Nelder-Mead). Entrambi i metodi rimangono bloccati lontano dal minimo. Entrambi sembrano lavorare su funzioni più semplici, come trovare il minimo di un paraboloide, ma penso che entrambi, e specialmente il primo, siano progettati per funzioni in cui xey sono valori reali (doppi). Un altro problema è che ho bisogno di chiamare f (x, y) il minor numero possibile di volte. Parla con l'hardware esterno e impiega un paio di secondi per ogni chiamata. Qualsiasi idea per questo sarebbe molto apprezzata.Minimizzazione di f (x, y) dove x e y sono interi

Ecco un esempio della funzione di errore. Mi spiace di non averlo postato prima. Questa funzione richiede un paio di secondi per valutare. Inoltre, le informazioni che query dal dispositivo non aggiunge all'errore se è sotto il nostro valore desiderato, solo se è al di sopra

double Error(x,y) 
{ 
    SetDeviceParams(x,y); 
    double a = QueryParamA(); 
    double b = QueryParamB(); 
    double c = QueryParamC(); 
    double _fReturnable = 0; 
    if(a>=A_desired) 
    { 
    _fReturnable+=(A_desired-a)*(A_desired-a); 
    } 
    if(b>=B_desired) 
    { 
    _fReturnable+=(B_desired-b)*(B_desired-b); 
    } 
    if(c>=C_desired) 
    { 
    _fReturnable+=(C_desired-c)*(C_desired-c); 
    } 
    return Math.sqrt(_fReturnable) 
} 
+1

Anche le idee relative alla classe e al comportamento della tua funzione saranno apprezzate. – EFraim

+1

Interessante domanda. È divertente come la matematica diventi prima difficile quando hai iniziato a conoscere le frazioni e i numeri reali, e di nuovo difficile dopo averli rimossi e tornare ai numeri naturali. =) –

+1

Conosci l'equazione per f (x, y)? – Noldorin

risposta

2

Come si definisce f (x, y)? La minimizzazione è un problema difficile, a seconda della complessità della tua funzione.

Algoritmi genetici potrebbero essere un buon candidato.

Risorse:

Genetic Algorithms in Search, Optimization, and Machine Learning

Implementing a Genetic Algorithms in C#

Simple C# GA

+0

Hai qualche suggerimento su buone risorse per iniziare con gli algoritmi genetici? – Tim

+1

Ci sono un sacco di libri su questo argomento. Quello che mi ha fatto iniziare è stato il libro di Goldberg. http://www.amazon.com/Genetic-Algorithms-Optimization-Machine-Learning/dp/0201157675 – Indy9000

3

Hai guardato algoritmi genetici? Sono molto, molto bravi a trovare minimi e massimi, evitando i minimi/massimi locali.

+0

Beh, stanno gradualmente migliorando, una generazione alla volta! –

+0

Tuttavia non sono lineari :) – Indy9000

2

Se si tratta di una funzione arbitraria, non esiste un modo preciso per farlo.

Supponiamo di avere una funzione definita come:

f(x, y) = 0 for x==100, y==100 
      100 otherwise 

Come può qualsiasi algoritmo realisticamente trovare (100, 100) come il minimo? Potrebbe essere una qualsiasi combinazione possibile di valori.

Sai qualcosa sulla sulla funzione che stai testando?

+0

f (x, y) è una funzione di errore di calibrazione. Ci sono due parametri che mi interessano. Entrambi sono influenzati dalle modifiche in x e y. La funzione è abbastanza continua, ma la sua derivata potrebbe non essere perché non appena uno dei parametri è in spec, l'ho appena impostato a 0 – Tim

+2

@Jon Skeet: Ovviamente si suppone che la funzione possa essere * qualsiasi cosa *, che infatti ti costringe a provare ogni combinazione di (x, y). Se sai che la funzione è pseudo-continua, le cose vengono semplificate enormemente. – Noldorin

+0

@Noldorin: Ecco perché ho chiesto cosa sapesse l'OP in merito alla funzione. Nel momento in cui ho postato, la funzione che ho dato avrebbe soddisfatto tutto ciò che sapevamo. –

4

Ci sono molte, molte soluzioni qui. In effetti, ci sono interi libri e discipline accademiche basati sull'argomento. Ne sto leggendo uno eccellente adesso: How to Solve It: Modern Heuristics.

Non esiste una soluzione corretta: soluzioni diverse presentano vantaggi diversi in base alla conoscenza specifica della funzione. È stato anche dimostrato che non esiste un'euristica che offra il meglio in tutte le attività di ottimizzazione.

Se sai che la tua funzione è quadratica, è possibile utilizzare Newton-Gauss per trovare il minimo in un unico passaggio. Un algoritmo genetico può essere un ottimo strumento per scopi generali, oppure puoi provare la ricottura simulata, che è meno complicata.

+0

Perché i miei collegamenti sono interrotti? Non sembra così nell'anteprima. –

1

Quello che state generalmente cercando è chiamato un optimisation technique in matematica.In generale, si applicano alle funzioni con valori reali, ma molte possono essere adattate per funzioni a valori interi.

In particolare, consiglierei di esaminare non-linear programming e gradient descent. Entrambi sembrerebbero abbastanza adatti alla tua applicazione.

Se potessi fornire ulteriori dettagli, potrei essere in grado di suggerire qualcosa di più specifico.

+0

Come ho detto prima di essere utilizzato in un programma di calibrazione, quindi ci saranno molti dispositivi che hanno forme simili ma non identiche per la loro funzione di errore. Non so esattamente come sia la forma, perché ci sono molti dati che ho bisogno di ottenere. sia x che y sono compresi tra 0 e 65535 e ci vogliono un paio di secondi per raccogliere un pezzo di dati. – Tim

+0

@Tim: abbastanza giusto. Potresti forse darci la forma di questa funzione di errore? Non sono terribilmente ottimista riguardo al successo qui, se una richiesta richiede pochi secondi! – Noldorin

+0

Questo è fondamentalmente ciò che accade. Mi scuso se è un po 'ambiguo. doppio Errore (x, y) { SetDeviceParams (x, y); double a = QueryParamA(); double b = QueryParamB(); double c = QueryParamC(); doppia _fReturnable = 0 if (a> = A_desired) { _fReturnable + = (A_desired-a) * (A_desired-a); } if (b> = B_desired) { _fReturnable + = (B_desired-b) * (B_desired-b); } if (c> = C_desired) { _fReturnable + = (C_desired-c) * (C_desired-c); } ritorno Math.sqrt (_fReturnable) } – Tim

1

La risposta di Jon Skeet è corretta. Hai davvero bisogno di informazioni su f e sui suoi derivati ​​anche se f è ovunque continua.

Il modo più semplice per apprezzare le difficoltà di ciò che si chiede (minimizzazione di f solo a valori interi) è solo pensare a un f: R-> R (f è una funzione di valore reale dei reali) di una variabile che fa grandi escursioni tra interi individuali. È possibile costruire facilmente tale funzione in modo che NON ci sia alcuna correlazione tra i minimi locali sulla linea reale e i minimi ai numeri interi e non abbia alcuna relazione con la prima derivata.

Per una funzione arbitraria non vedo alcun modo tranne la forza bruta.

+0

Sulla base del test che ho fatto, il gradiente è piccolo ovunque, quindi la funzione non cambia molto tra i valori interi, ma non posso prevedere in quale direzione cambierà. La forza bruta non funzionerà, perché ci vuole così tanto tempo per ottenere un singolo pezzo di dati – Tim

+0

quindi stai dicendo che oltre al problema di guardare solo i valori interi che non conosci l'evento f e stai solo andando a campionare un sottoinsieme di {(x, y)} e tenta di trarre conclusioni da un sottoinsieme limitato? –

+0

@pgast Sfortunatamente, questo è più o meno quello che sto dicendo. Ho abbastanza dati che ho una buona ipotesi di un punto di partenza, ma questo è tutto. La buona notizia è che non mi interessa necessariamente la "migliore soluzione", a patto che la soluzione che ottengo soddisfi le specifiche – Tim

0

Siamo spiacenti che la formattazione sia stata così brutta in precedenza. Ecco un esempio della funzione di errore

double Error(x,y) 
{ 
SetDeviceParams(x,y); 
double a = QueryParamA(); 
double b = QueryParamB(); 
double c = QueryParamC(); 
double _fReturnable = 0; 
if(a>=A_desired) 
{ 
    _fReturnable+=(A_desired-a)*(A_desired-a); 
} 
if(b>=B_desired) 
{ 
_fReturnable+=(B_desired-b)*(B_desired-b); 
} 
if(c>=C_desired) 
{ 
    _fReturnable+=(C_desired-c)*(C_desired-c); 
} 
return Math.sqrt(_fReturnable) 
} 
+0

Tim, modifica la tua DOMANDA per postare questo. –

+0

Ah, bene, l'ho fatto per te. La formattazione è risultata diversa, poiché ho copiato stupidamente il testo visualizzato anziché il testo di modifica. –

+0

Fatto. Mi dispiace per il fatto che – Tim

1

Quindi diamo un'occhiata al tuo problema in matematica. Tutto ciò presuppone che capisco perfettamente il tuo problema . Sentiti libero di correggermi se mi sbaglio.

vogliamo ridurre al minimo il seguente:

\ sqrt ((a-a_desired)^2 + (b-b_desired)^2 + (c-c_desired)^2)

o in altra notazione || Pos (x - x_desired) || _2

dove x = (a, b, c) e Pos (y) = max (y, 0) significa che vogliamo che la "parte positiva" (questo spiega per le tue dichiarazioni if). Infine, desideriamo restringere noi stessi a soluzioni in cui x è valutato intero.

A differenza dei poster di cui sopra, non credo che gli algoritmi genetici siano ciò che si desidera.
In effetti, penso che la soluzione sia molto più semplice (supponendo che io comprenda il tuo problema).

1) Eseguire qualsiasi procedura di ottimizzazione sulla funzione precedente. Questo ti darà la soluzione x^* = (a^*, b^*, c^*). Poiché questa funzione è in aumento rispetto alle variabili , la migliore soluzione per intero che si possa sperare è (ceil (a^*), ceil (b^*), ceil (c^*)).

Ora dici che la tua funzione è forse difficile da valutare. Esistono strumenti per questo che non sono basati sull'euristica. Il go sotto il nome di Derivative-Free Ottimizzazione. Le persone usano questi strumenti per ottimizzare obiettivo sulla base di simulazioni (ho nemmeno sentito parlare di un caso in cui la funzione obiettivo si basa sulle rese delle colture canto!)

Ciascuno di questi metodi hanno proprietà diverse, ma in generale tentano di minimizzare non solo l'obiettivo, ma il numero di valutazioni delle funzioni oggettive.

+0

+1 per l'ottimizzazione senza derivati, ma la riformulazione matematica potrebbe utilizzare una menzione esplicita del fatto che "x" è una funzione, e forse rinominare "x" in modo che non entri in conflitto con le variabili di la fonte pubblicata – outis

+0

x non è una funzione, ma solo la raccolta delle variabili a, b, c in un singolo vettore. – SplittingField

+1

Tim non vuole minimizzare 'Err_A (x) = || Pos (x - A) || ₂', ma piuttosto' Err_A (Dev (u)) ', dove' Dev (u): Z² -> R³ '. Se la soln. è in 'x', non ha bisogno di essere in numeri interi. Inoltre, 'ceil · x'' potrebbe non essere una soluzione valida. in 'x', poiché potrebbe non esserci un' u'tale che 'ceil · x '= Dev (u')'. Per le estensioni di 'Dev' a qualche' Dev '(u): R² -> R³' Posso immaginare (terrazze, mesh), solns. in 'u' sarebbe a valori interi. Se un 'Dev '(u)' esotico ha un minimo in' u'∉Z²', gli elementi di '{ceil, floor} ² · u'' potrebbero non essere soluzioni. – outis

Problemi correlati