2013-07-12 8 views
5

Załóżmy, że chcę wygenerować funkcję, która zostanie później włączona w zestaw równań do rozwiązania za pomocą funkcji scipy nsolve. Chcę utworzyć funkcję tak:Dynamicznie buduj funkcję lambda w pythonie

xi + xi + 1 + xi + 3 = 1

w którym liczba zmiennych będzie zależna od liczby komponentów. Na przykład, jeśli mają 2 składniki:

f = lambda x: x[0] + x[1] - 1 

do 3:

f = lambda x: x[0] + x[1] + x[2] - 1 

określić elementy w postaci tablicy w ciągu argumentów funkcji nazywać:

def my_func(components): 
     for component in components: 
     ..... 
     ..... 
     return f 

Nie mogę po prostu znaleźć sposobu na zrobienie tego. Mam być w stanie zrobić to w ten sposób, jak tę funkcję i inne funkcje muszą być rozwiązywane wspólnie z nsolve:

x0 = scipy.optimize.fsolve(f, [0, 0, 0, 0 ....]) 

Każda pomoc będzie mile widziane

Dzięki!


Ponieważ nie jestem pewien, co jest najlepszym sposobem osiągnięcia tego celu będę w pełni wyjaśnić, co usiłuję zrobić:

-Jestem próbuje wygenerować to dwie funkcje, aby być później nsolved:

enter image description here

enter image description here

Więc chcę stworzyć Teste funkcyjny ([lista komponentów]), które mogą mi wrócić te dwa równania (Psat (T) jest funkcją, którą mogę wywołać w zależności od komponentu, a P jest stałą (wartość = 760)).

przykład:

teste(['Benzene','Toluene']) 

powróci:

xBenzene + xToluene = 1

xBenzene PSAT ('benzen') + xToluene PSAT ('toluen') = 760

w przypadku połączenia:

teste(['Benzene','Toluene','Cumene']) 

że powróci:

xBenzene + xToluene + xCumene = 1

xBenzene PSAT ('benzenu') + xToluene PSAT ('toluen') + xCumene * PSAT ('kumenu') = 760

Wszystkie te wartości x nie są czymś, co mogę obliczyć i zamienić na listę, którą mogę zsumować. Są to zmienne, które są tworzone w zależności od liczby komponentów, które mam w systemie ...

Nadzieja to pomaga znaleźć najlepszy sposób na osiągnięcie tego

+1

Nie używaj lambda? – Ryan

+4

To pachnie jak [problem XY] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Co dokładnie próbujesz zrobić, to sprawia, że ​​myślisz, że dynamiczne budowanie funkcji lambda jest częścią odpowiedzi, lub że włączenie liczby komponentów zamiast ich powtarzania jest częścią odpowiedzi? Prawdopodobnie jest lepszy sposób na zrobienie tego. – abarnert

+1

Ponadto wiele osób, które zadają tego rodzaju pytania, wydaje się myśleć, że jest coś specjalnego w funkcjach lambda. Tam nie ma. Nie ma nawet czegoś takiego jak "funkcja lambda". Funkcja jest funkcją, zdefiniowaną przez 'lambda' lub' def'. – abarnert

Odpowiedz

1

Chciałbym skorzystać z numpy i zrobić coś takiego:

def teste(molecules): 
    P = np.array([Psat(molecule) for molecule in molecules]) 
    f1 = lambda x: np.sum(x) - 1 
    f2 = lambda x: np.dot(x, P) - 760 
    return f1, f2 

Właściwie to, co staramy się rozwiązać to ewentualnie underdetermined układ równań liniowych z formularza A.x = b. Można skonstruować A i B, co następuje:

A = np.vstack((np.ones((len(molecules),)), 
       [Psat(molecule) for molecule in molecules])) 
b = np.array([1, 760]) 

I można następnie utworzyć pojedynczą funkcję lambda przekazujących 2 element wektora jako:

return lambda x: np.dot(A, x) - b 

Ale ja naprawdę nie sądzę, że jest to najlepszy podejście do rozwiązywania twoich równań: albo masz jedno rozwiązanie, które możesz uzyskać z np.linalg.solve(A, b), albo masz system liniowy z nieskończenie wieloma rozwiązaniami, w takim przypadku to, co chcesz znaleźć, jest podstawą przestrzeni rozwiązania, a nie pojedynczym punktem tę przestrzeń, którą otrzymasz od solwera liczbowego, który przyjmuje funkcję jako dane wejściowe.

+0

Wielkie dzięki Jaime, właśnie tego szukałem! A tak przy okazji, skoro wydajesz się być ekspertem od scipy/numpy, czy wiesz, że istnieje jakiś sposób na rozwiązanie układu równań nieliniowych z ograniczeniami? Rozwiązanie mojego problemu dało mi x1 = 21 i x2 = -22, gdy powinny być między 0 a 1. – user2574761

2

tłumaczenia bezpośredniego byłoby:

f = lambda *x: sum(x) - 1 

ale nie jestem pewien, czy to naprawdę to, co chcesz.

+0

Myślę, że właśnie tego chce. +1 –

+0

Proszę spojrzeć na zaktualizowane pytanie – user2574761

+0

To jest ładne i eleganckie, myślałem również o podobnych problemach i nigdy nie myślałem o używaniu * x w lambdach, (lub właściwie nigdy nie używano * argumentów nigdzie wcześniej, chociaż dostaję powód) – usethedeathstar

0

Jeśli naprawdę chcesz zdefiniować funkcję, budując ją iteracyjnie, możesz. Nie mogę myśleć o jakiejkolwiek sytuacji, w której byłoby to najlepsze rozwiązanie, a nawet rozsądne jeden, ale to, co prosiłeś, więc:

def my_func(components): 
    f = lambda x: -1 
    for component in components: 
     def wrap(f): 
      return lambda x: component * x[0] + f(x[1:]) 
     f = wrap(f) 
    return f 

Teraz:

>>> f = my_func([1, 2, 3]) 
>>> f([4,5,6]) 
44 

to oczywiście nie będzie dobrej zabawy przy debugowaniu. Na przykład spójrz na traceback, dzwoniąc pod numer f([4,5]).

4

Można dynamicznie zbudować lambda sznurkiem następnie zanalizować go z funkcji eval tak:

a = [1, 2, 3] 

s = "lambda x: " 
s += " + ".join(["x[" + str(i) + "]" for i in xrange(0, 3)]) # Specify any range 
s += " - 1" 

print s 

f = eval(s) 
print f(a) 
+0

wyjaśnienie, dlaczego jest to odrzucone, byłoby docenione .. – cheeyos

+0

'eval' może być niebezpieczne: http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html. Plus w tym przypadku użycie 'lambda' niekoniecznie jest najlepszą metodą. –

+1

eval jest niebezpieczny tylko wtedy, gdy bierzesz ciąg znaków od użytkownika. W tym wniosku wyraźnie nie ma to miejsca. Odpowiedź Jona zakłada, że ​​wszystkie elementy na x muszą zostać zsumowane, co nie musi dotyczyć przypadku. Pokazuję tylko przykład dynamicznego tworzenia lambda, który jest wystarczająco elastyczny, aby służyć OP. – cheeyos

-1
def make_constraint_function(components): 
    def constraint(vector): 
     return sum(vector[component] for component in components) - 1 
    return constraint 

Można to zrobić za pomocą lambda, ale o nazwie funkcja może być bardziej czytelne. def Funkcje karmione mogą zrobić wszystko, co tylko można i lambdas. Upewnij się, że funkcja jest dobrze napisana i użyj nazw zmiennych i funkcji odpowiednich dla twojego programu.

Powiązane problemy