Diverse svårigheter man kan råka ut för

Optimeringsproblem kan vara svåra att formulera korrekt, men även korrekt formulerade problem kan ge fmincon bekymmer. Här följer exempel på några av de svårigheter man kan råka ut för.

Det är viktigt att formulera problemet korrekt. Det är t.ex. viktigt att använda rätt på tecken i bivillkoren, så att man inte får motsägelser. Antag att vi vill minimera x (en skalär variabel) när x <= 1 och x >= 2. Detta är givetvis omöjligt och det är uppenbart att vi har gjort ett fel. Detta är nu inte alltid så lätt att upptäcka i riktiga problem, där man kan ha tusentals bivillkor (som dessutom inte är enkla gränser). Samma problem kan inträffa med likhetsbivillkor, x = 2 och x = 3 t.ex.

fmincon ger ett felmeddelande i dessa fall:
Optimization terminated: no feasible solution found.

"A feasible solution" (en tillåten lösning, tillåten punkt) är en punkt som uppfyller bivillkoren, och rutinen hittar ingen sådan punkt. Man kan få detta felmeddelande även om det finns tillåtna punkter, men där startpunkten ligger så långt ifrån en tillåten punkt, att rutinen inte hittar fram. Det är viktigt med bra startvärden, men det kan vara svårt att hitta en startgissning som uppfyller bivillkoren. Det brukar dock räcka att man hittar en startgissning som inte bryter alltför mycket mot bivillkoren.

Ibland glömmer man bivillkor. Vi minimerar kanske en massa (vikt) och för oss är det självklart att massan skall vara ickenegativ. En optimeringsrutin har ju inte några sådana fördomar, utan den kan mycket väl ge oss ett negativt resultat.

Vi kan också råka ut för att iterationerna skenar iväg. Säg att vi minimerar f(x) = x^3 - 10 x. Funktionen har ett lokalt minimum för x = sqrt(10/3) (och ett lokalt maximum för -sqrt(10/3)), men den saknar globalt minimum. Om vi startar till vänster om -sqrt(10/3) kommer rutinen att producera alltmer negativa iterander. För att undvika oändliga loopar finns en begränsning på antalet funktionsberäkningar (av objektfunktionen) rutinen får utföra (standardvärdet är 100 * antalet variabler), och rutinen bryter med felmeddelandet:

Maximum number of function evaluations exceeded; increase OPTIONS.MaxFunEvals.

När vi arbetar med objektfunktioner som inte är nedåt begränsade, kan det vara lämpligt att införa enkla gränser på variablerna. Om vi avgränsar en kompakt mängd existerar ett minsta värde (vår objektfunktion är ju kontinuerlig). Detta minsta värde är nog ointressant, men vi riskerar inte att rutinen utför onödigt många funktionsberäkningar. Man måste sedan inspektera det resultat som fmincon producerat för att se om det är av något intresse.

Vi kan få ovanstående felmeddelande utan att någonting är fel. Det kan vara så att problemet är så pass svårt att rutinen får ta många steg för att hitta fram. Det är då möjligt att tillåta rutinen att utföra fler beräkningar. Här ett exempel:

   min x1 över (x1, x2)

   då -x1 + 16 (x2 - x1^2)^2 = 0
   och -5 <= x1, x2 <= 5


Vi har en väldigt enkel linjär objektfunktion, men ett lite besvärligt ickelinjärt likhetsbivillkor. Även om vi startar med en tillåten punkt, så har fmincon problem att hitta minimum (x1, x2) = (0, 0). Här en bild av objektfunktion och olikhetsbivillkor. Startgissningen (x1, x2) är ungefär (0.1, 0.089) (avvikelsen i bivillkoret är -4e-17, vilket väsentligen är noll).

banan

Den streckade ytan utgör en del av objektfunktionen och den blå kurvan är en del av olikhetsbivillkoret. Den svarta ringen markerar minimum och den röda startpunkten. Rutinen tar ett alldeles för långt förstasteg och hamnar i det röda krysset och sedan går rutinen ännu mera vilse. Det är först när den slår emot de enkla gränserna som det tar stopp. Om jag ger rutinen flera funktionsberäkningar hittar den tillbaks efter 252 funktionsberäkningar.

Så här ökar man antalet funktionsberäkningar (jag påstår inte att 500 räcker i labben):

options = optimset;         % skapa postvariabeln options
options.MaxFunEvals = 500;  % sätt datamedlemmen MaxFunEvals till 500 (till exempel)
% skicka med options sist i anropet av fmincon
[x_opt, obj_val] = fmincon(@obj_fun, x_guess, A, B, A_eq, B_eq, LB, UB, @constr_fun, options)

En kortform för de två första raderna är:
options = optimset('MaxFunEvals', 500);

Du skulle också kunna få felmeddelandet "Maximum number of iterations exceeded; increase OPTIONS.MaxIter". Öka då datamedlemmen MaxIter (om du tror att din kod är korrekt). Observera då att optimset skall anropas en gång, så t.ex.
options = optimset('MaxFunEvals', 500, 'MaxIter', 1000);

fmincon är inte bara en metod utan rutinen kan växla mellan olika alternativ. Ibland är inte ett av dessa alternativ tillgängligt (för det aktuella problemet), varför rutinen ger en varning.

Warning: Large-scale (trust region) method does not currently solve this type of problem, using medium-scale (line search) instead.

Detta är alltså en upplysning och inte resultatet av något fel vi gjort. Genom att välja bort den icke tillgängliga metoden slipper vi meddelandet:

options.LargeScale = 'off';


Back