2016-11-02 1 views
1

ein einfaches Problem vor:Math Domain Fehler aufgrund disrespected Einschränkung in scipy SLSQP minimieren

Um das Problem mit scipy.optimize.minimize zu lösen:

import numpy as np 
from scipy.optimize import minimize 
from math import log 

def func(x): 
    return log(x[0]) 

def func_deriv(x): 
    return np.array([1/x[0]]) 

cons = ({'type': 'ineq', 
     'fun' : lambda x: x[0] - 1e-4, 
     'jac' : lambda x: np.array([1])}) 
minimize(func, [1.0], jac=func_deriv, constraints=cons, method='SLSQP') 

Das Skript trifft ValueError weil log(x) mit negativ bewertet x. Es scheint, dass der Funktionswert ausgewertet wird, selbst wenn die Bedingung nicht erfüllt ist.

Ich verstehe, dass bounds in minimize() könnte das Problem vermeiden, aber das ist nur eine Vereinfachung meines ursprünglichen Problems. In meinem ursprünglichen Problem kann die Einschränkung x >= 1e-4 nicht einfach als Grenzen von x dargestellt werden, sondern eher von der Form g(x) >= C, so bounds würde nicht helfen.

+0

Ich benutze immer Grenzen für diesen Zweck sogar auf Kosten von zusätzlichen Variablen oder Einschränkungen (aber ich verwende typischerweise fortgeschrittenere Algorithmen als scipy.optimize). Z.B. In deinem Fall würde ich 'y = g (x)' hinzufügen und dann die Grenzen auf 'y' setzen. Stattdessen können Sie die Rückgabe von Einschränkungsfunktionswerten durchmachen, die (sehr) negativ (d. H. Nicht machbar) sind. –

+0

@ErwinKalvelagen Das ist eine Lösung, aber ich muss dann eine modifizierte Version von "log (x)" entwickeln, die sehr negativ ist und ableitbar ist, selbst wenn "x" etwas kleiner als Null ist. Darf ich fragen, welche fortschrittlichen Algorithmen Sie normalerweise verwenden? – peter

+0

@peter Ich denke, er bezieht sich auf die kommerziellen Tools wie Knigro, Baron, Conopt und Co. (oder im Allgemeinen NLP-Löser von AMPL unterstützt). Eine Open-Source-Alternative, die Sie untersuchen können, wäre ipopt (oder andere, wenn Ihr vollständiges Problem konvex ist). – sascha

Antwort

0

Wenn nur der Funktionswert mit x > ε interessiert ist, kann eine sichere Funktion definiert werden, die die Domäne erweitert. Geben Sie die log Funktion als ein Beispiel ein. Es ist möglich, log mit einer anderen kubische Funktion zu erweitern, während glatt die Brücke Punkt ε machen:

safe_log(x) = log(x) if x > ε else a * (x - b)**3 

a und b zu berechnen, müssen wir erfüllen:

log(ε) = a * (ε - b)**3 
1/ε = 3 * a * (ε - b)**2 

Daraus ergibt sich die safe_log Funktion:

eps = 1e-3 

def safe_log(x): 
    if x > eps: 
     return log(x) 
    logeps = log(eps) 
    a = 1/(3 * eps * (3 * logeps * eps)**2) 
    b = eps * (1 - 3 * logeps) 
    return a * (x - b)**3 

Und es sieht wie folgt aus:

Plot of safe_log(x)

Verwandte Themen