2009-07-24 22 views
6

Je me demandais si quelqu'un avait des suggestions pour minimiser une fonction, f (x, y), où x et y sont des entiers. J'ai étudié beaucoup de techniques de minimisation et d'optimisation, comme BFGS et d'autres sur GSL, et des choses à partir de recettes numériques. Jusqu'à présent, j'ai essayé d'implémenter quelques schémas différents. Le premier travaille en choisissant la direction de la plus grande descente f (x + 1, y), f (x-1, y), f (x, y + 1), f (x, y-1), et suivez cette direction avec minimisation de ligne. J'ai également essayé d'utiliser une méthode de downhill simplex (Nelder-Mead). Les deux méthodes restent bloquées loin d'un minimum. Ils semblent tous deux travailler sur des fonctions plus simples, comme trouver le minimum d'un paraboloïde, mais je pense que les deux, et surtout le premier, sont conçus pour des fonctions où x et y sont des valeurs réelles (doubles). Un autre problème est que j'ai besoin d'appeler f (x, y) aussi peu de fois que possible. Il parle au matériel externe, et prend quelques secondes pour chaque appel. Toutes les idées pour cela seraient grandement appréciées.Minimisation de f (x, y) où x et y sont des entiers

Voici un exemple de la fonction d'erreur. Désolé, je n'ai pas posté cela avant. Cette fonction prend quelques secondes pour évaluer. En outre, les informations que nous interrogeons de l'appareil ne contribue pas à l'erreur si elle est inférieure à notre valeur souhaitée, que si elle est au-dessus

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

Toutes les idées concernant la classe et le comportement de votre fonction seront également appréciées. – EFraim

+1

Question intéressante. C'est marrant de voir comment les maths commencent à devenir difficiles quand vous avez commencé à apprendre sur les fractions et les nombres réels, et le plus difficile une fois que vous les avez retirés et que vous êtes revenu aux nombres naturels. =) –

+1

Connaissez-vous l'équation pour f (x, y)? – Noldorin

Répondre

2

Comment définissez-vous f (x, y)? La minimisation est un problème difficile, selon la complexité de votre fonction.

Les algorithmes génétiques pourraient être un bon candidat.

Ressources:

Genetic Algorithms in Search, Optimization, and Machine Learning

Implementing a Genetic Algorithms in C#

Simple C# GA

+0

Avez-vous des suggestions sur les bonnes ressources pour commencer avec les algorithmes génétiques? – Tim

+1

Il y a beaucoup de livres sur ce sujet. Ce qui m'a fait démarrer était le livre de Goldberg. http://www.amazon.com/Genetic-Algorithms-Optimization-Machine-Learning/dp/0201157675 – Indy9000

3

Avez-vous regardé des algorithmes génétiques? Ils sont très, très bons pour trouver des minimums et des maximums, tout en évitant les minimum/maximum locaux.

+0

Eh bien, ils s'améliorent progressivement, une génération à la fois! –

+0

Ils sont non-linéaires cependant :) – Indy9000

2

S'il s'agit d'une fonction arbitraire, il n'y a pas de manière simple de le faire.

Supposons que nous avons une fonction définie comme:

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

Comment un algorithme peut trouver de façon réaliste (100, 100) au minimum? Ce pourrait être n'importe quelle combinaison possible de valeurs.

Connaissez-vous quoi que ce soit sur la fonction que vous testez?

+0

f (x, y) est une fonction d'erreur d'étalonnage. Il y a deux paramètres qui m'intéressent. Les deux sont affectés par les changements de x et y. La fonction est assez continue, mais sa dérivée peut ne pas être parce que dès que l'un des paramètres est dans spec, je le mets juste à 0 – Tim

+2

@Jon Skeet: Cela suppose bien sûr que la fonction puisse être * n'importe quel *, en effet vous force à essayer toutes les combinaisons de (x, y). Si vous savez que la fonction est pseudo-continue, les choses sont énormément simplifiées. – Noldorin

+0

@Noldorin: C'est pourquoi j'ai demandé ce que l'OP connaissait de la fonction. Au moment où j'ai posté, la fonction que j'ai donnée aurait satisfait tout ce que nous savions. –

4

Il y a beaucoup, beaucoup de solutions ici. En fait, il existe des livres entiers et des disciplines académiques basées sur le sujet. Je suis en train de lire un excellent article en ce moment: How to Solve It: Modern Heuristics.

Il n'existe pas de solution unique - différentes solutions ont des avantages différents basés sur une connaissance spécifique de votre fonction. Il a même été prouvé qu'il n'y a pas d'heuristique qui fonctionne le mieux dans toutes les tâches d'optimisation.

Si vous savez que votre fonction est quadratique, vous pouvez utiliser Newton-Gauss pour trouver le minimum en une seule étape. Un algorithme génétique peut être un excellent outil polyvalent, ou vous pouvez essayer un recuit simulé, ce qui est moins compliqué.

+0

Pourquoi mes liens sont-ils brisés? Cela ne ressemble pas à ça sur l'aperçu. –

1

Ce que vous cherchez généralement s'appelle un optimisation technique en mathématiques.En général, ils s'appliquent à des fonctions à valeur réelle, mais beaucoup peuvent être adaptés pour des fonctions intégralement évaluées. En particulier, je recommande d'examiner non-linear programming et gradient descent. Les deux sembleraient tout à fait appropriés pour votre application.

Si vous pouviez fournir plus de détails, je pourrais vous suggérer quelque chose de plus spécifique.

+0

Comme je l'ai dit avant qu'il ne soit utilisé dans un programme d'étalonnage, il y aura donc beaucoup de dispositifs qui ont des formes similaires mais pas identiques pour leur fonction d'erreur. Je ne sais pas exactement à quoi ressemble la forme, car il y a beaucoup de données à obtenir. les deux x et y sont compris entre 0 et 65535, et il faut quelques secondes pour collecter une donnée. – Tim

+0

@Tim: assez bien. Pourriez-vous nous donner la forme de cette fonction d'erreur? Je ne suis pas très optimiste sur le succès ici, si une demande prend quelques secondes! – Noldorin

+0

C'est essentiellement ce qui se passe. Je m'excuse si c'est un peu ambigu. double Erreur (x, y) { SetDeviceParams (x, y); double a = QueryParamA(); double b = QueryParamB(); double c = QueryParamC(); double _fReturnable = 0 if (a> = A_desired) { _fRetourable + = (A_desired-a) * (A_desired-a); } si (b> = B_desired) { _fRetourable + = (B_desired-b) * (B_desired-b); } si (c> = C_desired) { _fReturnable + = (C_desired-c) * (C_desired-c); } retour Math.sqrt (_fReturnable) } – Tim

1

La réponse de Jon Skeet est correcte. Vous avez vraiment besoin d'informations sur f et c'est dérivés même si f est partout continu. La manière la plus simple d'apprécier les difficultés de ce que vous demandez (minimisation de f en valeurs entières uniquement) est simplement de penser à un f: R-> R (f est une fonction de valeur réelle des réels) d'une variable cela fait de grandes excursions entre les entiers individuels. Vous pouvez facilement construire une telle fonction de sorte qu'il n'y ait AUCUNE corré- lation entre les minimums locaux sur la ligne réelle et les minimums sur les entiers, sans relation avec la dérivée première.

Pour une fonction arbitraire, je ne vois pas d'autre moyen que la force brute.

+0

D'après les tests que j'ai effectués, le gradient est petit partout, donc la fonction ne change pas beaucoup entre les valeurs entières, mais je ne peux pas prédire dans quelle direction il va changer. La force brute ne fonctionnera pas, car il faut si longtemps pour obtenir une seule donnée – Tim

+0

alors dites-vous maintenant qu'outre le problème de ne regarder que les valeurs intégrales, vous ne connaissez pas l'événement et vous allez seulement goûter sous-ensemble du {(x, y)} et essayer de tirer des conclusions à partir d'un sous-ensemble limité? –

+0

@pgast Malheureusement, c'est à peu près ce que je dis. J'ai assez de données que j'ai une bonne idée d'un point de départ, mais c'est à peu près tout. Les bonnes nouvelles sont que je ne me soucie pas nécessairement de la "meilleure" solution, tant que la solution que je reçois répond aux spécifications – Tim

0

Désolé, la mise en forme était si mauvaise auparavant. Voici un exemple de la fonction d'erreur

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, éditez votre QUESTION pour l'afficher. –

+0

Ah, eh bien, je l'ai fait pour vous. Le formatage s'est avéré différent, comme j'ai copié bêtement du texte affiché au lieu du texte d'édition. –

+0

Terminé. Désolé pour cela – Tim

1

Examinons donc votre problème en langage mathématique. Tout cela suppose que je comprends pleinement votre problème. N'hésitez pas à me corriger si je me trompe.

nous voulons réduire au minimum les éléments suivants:

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

ou dans d'autres notations || Pos (x - x_desired) || _2

où x = (a, b, c) et Pos (y) = max (y, 0) signifie que nous voulons que la "partie positive" (ce qui explique pour vos déclarations si). Enfin, nous souhaitons nous limiter aux solutions où x est une valeur entière.

Contrairement aux affiches ci-dessus, je ne pense pas que les algorithmes génétiques sont ce que vous voulez du tout.
En fait, je pense que la solution est beaucoup plus facile (en supposant que je comprends votre problème).

1) Exécuter une routine d'optimisation sur la fonction ci-dessus. Cela vous donnera la solution x^* = (a^*, b^*, c^*). Comme cette fonction augmente en ce qui concerne les variables, la meilleure solution entière que vous pouvez espérer est (ceil (a^*), ceil (b^*), ceil (c^*)).

Maintenant, vous dites que votre fonction est peut-être difficile à évaluer. Il existe des outils pour cela qui ne sont pas basés sur des heuristiques. Le go sous le nom Derivative-Free Optimisation. Les gens utilisent ces outils pour optimiser l'objectif à partir de simulations (je même entendu parler d'un cas où la fonction objective est basée sur les rendements Crowing des cultures!)

Chacune de ces méthodes ont des propriétés différentes, mais en général ils tentent de minimiser non seulement l'objectif, mais le nombre d'évaluations de la fonction objective.

+0

+1 pour l'optimisation sans dérivée, mais la restaturation math-y pourrait utiliser une mention explicite du fait que "x" est une fonction, et peut-être renommer "x" afin qu'elle ne soit pas en conflit avec les variables de la source publiée. – outis

+0

x n'est pas une fonction, juste la collection des variables a, b, c dans un seul vecteur. – SplittingField

+1

Tim ne veut pas minimiser 'Err_A (x) = || Pos (x - A) || ₂', mais plutôt' Err_A (Dev (u)) ', où' Dev (u): Z² -> R³ '. Si le soln. est dans 'x', il n'a pas besoin d'être en entiers. De plus, 'ceil · x'' pourrait ne pas être une requête valide. dans 'x', car il ne peut y avoir un' u 'tel que 'ceil · x' = Dev (u ')'. Pour les extensions de 'Dev' à quelques' Dev '(u): R² -> R³' je peux imaginer (terrasses, mailles), solns. dans 'u' serait à des valeurs entières. Si un 'Dev '(u)' exotique avait un minimum à 'u'Z²', les éléments de' {ceil, floor} ² · u'' ne sont peut-être pas des solutions. – outis