È possibile richiamare Mathematica quando si utilizza Python tramite ExternalEvaluate?
ExternalEvaluaterende possibile chiamare codice Python da Mathematica. Il client Wolfram per Python rende possibile chiamare Mathematica da Python.
Quando si utilizza ExternalEvaluate, è possibile chiamare di nuovo per lo stesso kernel di Mathematica?
Ad esempio, supponiamo che io abbia una funzione Python nintche esegue l'integrazione numerica. Prende un'altra funzione come argomento: la funzione da integrare. C'è un modo per utilizzare la funzione Python nintattraverso ExternalEvaluate/ ExternalFunctionper integrare una funzione fdefinita in Mathematica?
Per essere chiari, questo è solo un esempio per aiutare a spiegare il problema. In realtà non sto cercando di fare l'integrazione numerica, e in questo momento le prestazioni (che sarebbe un grosso problema per l'integrazione numerica pratica) non mi preoccupano.
Risposte
Sono Riccardo Di Virgilio, uno degli sviluppatori di ExternalEvaluate e wolframclientforpython.
C'è un modo per fare quello che vuoi, anche se la funzione non è documentata o esposta, quindi il codice che ti sto dando potrebbe non funzionare nelle versioni future.
prova a eseguirlo in ExternalEvaluate:
from wolframclient.language.side_effects import wl_side_effect
from wolframclient.language import wl
wl_side_effect(wl.Print(2))
wl_side_effect(wl.Print(3))
wl_side_effect(wl.Print(4))
"actual result"
Quindi fondamentalmente abbiamo un logger Python standard che può inviare messaggi al kernel originale. Il kernel riceve il messaggio e continua ad aspettare il risultato del calcolo.
Se stai scrivendo qualcosa di complesso ti consiglio di dare un'occhiata al codice di valutazione esterna, che è pubblico.
Sì. È menzionato nel documento di ExternalEvaluate
Il comando
"cmd"può contenere un'espressione di modello inline<*expr*>. Questo valuta expr prima di"cmd"essere inviato al valutatore esterno.
che potremmo usare TemplateExpressionnella stringa passata a ExternalEvaluate. Un esempio di base:
ExternalEvaluate["Python", "<* Range@5 *>"]
Tuttavia, questo metodo non riesce quando si tenta di definire una funzione in sessione python, perché la <* expr *>si valuta prima che la "cmd"viene inviato al valutatore esterno.
Una soluzione a questo problema è definire la funzione in Mathematica con SetDelayed, quindi chiamare la funzione in Python con <* *>. Un esempio è dimostrato in questa mia risposta .
Forse con questo? https://reference.wolfram.com/language/WolframClientForPython/
Utilizzo:
Per le funzioni definite in Mathematica:
Due strade:
1.
from wolframclient.evaluation import WolframLanguageSession
from wolframclient.language import wl, wlexpr
session = WolframLanguageSession()
Eval = session.evaluate
def sin(x):
return Eval(Eval(wl.Sin)(x))
>>> sin(wl.Plus(wl.Pi,2))
Times[-1, Sin[2]]
Avviso FullForm è necessario.
2.
def sinPlusCos(x):
return Eval(Eval(wlexpr("Sin@#+Cos@#&"))(x))
Usa wlexpr e pure function.
In Mathematica, ecco un piccolo esempio:
ExternalEvaluate["Python", {"from wolframclient.evaluation import \
WolframLanguageSession",
"from wolframclient.language import wl, wlexpr",
"session = WolframLanguageSession()",
"Eval = session.evaluate",
"def sin(x): return Eval(Eval(wl.Sin)(x))", "sin(wl.Pi)"}]
{Null, Null, Null, Null, Null, 0}
"sin (wl.Pi)" può essere sostituito da altre cose, ad esempio: "sin(2.5)"
{Null, Null, Null, Null, Null, 0.598472}