Verwendung von Mathematica aus Python
Ich habe die folgenden Codezeilen verwendet, um 3D-Geometrie zu generieren ( ref ). Die Eingänge edges, vd, vlund ewkommen aus Python in den folgenden Formaten
edges = [(1,2), (1,3), (1,4), (2,5), (2,6), (5,6), (3,4), (3,7), (6,7), (7,8), (2,9)];
vl = [1,2,3,4,5,6,7,8,9]
ew = {(1, 2) : 49.6, (1,3): 74.4, (1, 4) : 49.6, (2,5): 37.2, (2, 6) : 74.4, (5, 6): 49.6,
(3, 4) : 37.2, (3, 7):24.8, (6, 7) : 62, (7, 8) : 37.2, (2, 9) : 24.8}
vd = {1:[75., 25., 0], 2:[115., 45., 0], 3:[10., 5., 0], 4:[45., 0, 0],
5:[90., 60., 0], 6:[45., 55., 0], 7:[0, 25., 0], 8:[10., 50., 0], 9:[115., 25.,0]};
Ich konvertiere das Obige manuell in die in Mathematica verwendeten Eingabeformate. Ich möchte wissen, wie Sie diese manuelle Konvertierung vermeiden und den Mathematica-Code direkt aus Python integrieren und ausführen können.
edges = {1 <-> 2, 1 <-> 3, 1 <-> 4, 2 <-> 5, 2 <-> 6, 5 <-> 6,
3 <-> 4, 3 <-> 7, 6 <-> 7, 7 <-> 8, 2 <-> 9};
vd = {{75., 25., 0}, {115., 45., 0}, {10., 5., 0}, {45., 0, 0},
{90., 60., 0}, {45., 55., 0}, {0, 25., 0}, {10., 50., 0}, {115., 25.,0}};
vl = Range[Length@vd];
vcoords = MapIndexed[#2[[1]] -> # &, vd];
ew = {1 \[UndirectedEdge] 2 -> 49.6, 1 \[UndirectedEdge] 3 -> 74.4,
1 \[UndirectedEdge] 4 -> 49.6, 2 \[UndirectedEdge] 5 -> 37.2,
2 \[UndirectedEdge] 6 -> 74.4, 5 \[UndirectedEdge] 6 -> 49.6,
3 \[UndirectedEdge] 4 -> 37.2, 3 \[UndirectedEdge] 7 -> 24.8,
6 \[UndirectedEdge] 7 -> 62, 7 \[UndirectedEdge] 8 -> 37.2,
2 \[UndirectedEdge] 9 -> 24.8}
g3d = Graph3D[vl, edges, VertexCoordinates -> vcoords,
EdgeWeight -> ew, VertexLabels -> Placed["Name", Center],
EdgeLabels -> {e_ :> Placed["EdgeWeight", Center]},
VertexSize -> .3, VertexStyle -> Red]
vars3d = Array[Through[{x, y, z}@#] &, Length @ vd];
λ = 1/100.;
obj3d = Total[(Norm[vars3d[[First@#]] - vars3d[[Last@#]]] - # /. ew)^2 & /@
EdgeList[g3d]] + λ Total[Norm /@ (vars3d - vd)];
lbnd = 0;
ubnd = 500;
solution3d = Last@Minimize[{obj3d, And @@ Thread[lbnd <= Join @@ vars3d <= ubnd]},
Join @@ vars3d];
edgeLengths3d = # -> Norm[vars3d[[First@#]] - vars3d[[Last@#]]] /.
solution3d & /@ EdgeList[g3d];
Grid[Prepend[{#, # /. ew, # /. edgeLengths3d} & /@
EdgeList[g3d], {"edge", "EdgeWeight", "Edge Length"}],
Dividers -> All]
Vorschläge, wie Sie fortfahren und Mathematica von Python aus verbinden können, sind sehr hilfreich.
BEARBEITEN: Die unten angegebene Antwort hilft bei der Übergabe von Eingabeargumenten aus Python mit PythonExpression. Als nächstes möchte ich diese Mathematica-Ausdrücke aus einem Python-Skript auswerten. Basierend auf den Kommentaren unten habe ich wolframclient installiert und Folgendes getan
from wolframclient.evaluation import WolframLanguageSession
session = WolframLanguageSession()
from wolframclient.language import wlexpr
session.evaluate(wlexpr('')) # I would like to know how to inclide Mathematica expressions here
EDIT2: Kann ich tun
session.evaluate(wlexpr(
'edges = {1 <-> 2, 1 <-> 3, 1 <-> 4, 2 <-> 5, 2 <-> 6, 5 <-> 6, 3 <-> 4, 3 <-> 7, 6 <-> 7, 7 <-> 8, 2 <-> 9};'
'vd = {{75., 25., 0}, {115., 45., 0}, {10., 5., 0}, {45., 0, 0},{90., 60., 0}, {45., 55., 0}, {0, 25., 0}, {10., 50., 0}, {115., 25.,0}};'
'vl = Range[Length@vd];'))
Ich habe es versucht,
from wolframclient.evaluation import WolframLanguageSession
session = WolframLanguageSession()
from wolframclient.language import wlexpr
session.evaluate(wlexpr(
'edges = {1 <-> 2, 1 <-> 3, 1 <-> 4, 2 <-> 5, 2 <-> 6, 5 <-> 6, 3 <-> 4, 3 <-> 7, 6 <-> 7, 7 <-> 8, 2 <-> 9};'
'vd = {{75., 25., 0}, {115., 45., 0}, {10., 5., 0}, {45., 0, 0},{90., 60., 0}, {45., 55., 0}, {0, 25., 0}, {10., 50., 0}, {115., 25.,0}};'
'vl = Range[Length@vd];'
'vcoords = MapIndexed[#2[[1]] -> # &, vd];'
'ew = {1 \[UndirectedEdge] 2 -> 49.6, 1 \[UndirectedEdge] 3 -> 74.4,'
'1 \[UndirectedEdge] 4 -> 49.6, 2 \[UndirectedEdge] 5 -> 37.2,'
'2 \[UndirectedEdge] 6 -> 74.4, 5 \[UndirectedEdge] 6 -> 49.6,'
'3 \[UndirectedEdge] 4 -> 37.2, 3 \[UndirectedEdge] 7 -> 24.8,'
'6 \[UndirectedEdge] 7 -> 62, 7 \[UndirectedEdge] 8 -> 37.2,'
'2 \[UndirectedEdge] 9 -> 24.8};'
'g3d = Graph3D[vl, edges, VertexCoordinates -> vcoords,EdgeWeight -> ew, VertexLabels -> Placed["Name", Center],'
'EdgeLabels -> {e_ :> Placed["EdgeWeight", Center]},'
'VertexSize -> .3, VertexStyle -> Red];'
'vars3d = Array[Through[{x, y, z}@#] &, Length @ vd];'
'λ = 1/100.;'
'obj3d = Total[(Norm[vars3d[[First@#]] - vars3d[[Last@#]]] - # /. ew)^2 & /@EdgeList[g3d]] + λ Total[Norm /@ (vars3d - vd)];'
'lbnd = 0;'
'ubnd = 500;'
'solution3d = Last@Minimize[{obj3d, And @@ Thread[lbnd <= Join @@ vars3d <= ubnd]},Join @@ vars3d];'
'edgeLengths3d = # -> Norm[vars3d[[First@#]] - vars3d[[Last@#]]] /.solution3d & /@ EdgeList[g3d];'
'Grid[Prepend[{#, # /. ew, # /. edgeLengths3d} & /@EdgeList[g3d], {"edge", "EdgeWeight", "Edge Length"}],Dividers -> All];'
'z1 = Values[solution3d] // Partition[#, 3] &;'
'theFile = File["op.txt"];'
'Export[theFile, z1, "Table"];'
))
Aber ich bekomme folgenden Fehler:
String expected at position 1 in StringForm[MessageName[General, msgl], $MessageList]. Undefined message MessageName[Message, msgl] with arguments {$MessageList} The problem may be unbounded. Specifying a value for MaxIterations greater than 5000 may improve the solution. String expected at position 1 in StringForm[MessageName[General, msgl], $MessageList].
Undefined message MessageName[Message, msgl] with arguments {$MessageList} String expected at position 1 in StringForm[MessageName[General, msgl], $MessageList].
Further output of MessageName[StringForm, string] will be suppressed during this calculation.
The problem may be unbounded. Specifying a value for MaxIterations greater than 5000 may improve the solution.
String expected at position 1 in StringForm[MessageName[General, msgl], $MessageList]. Undefined message MessageName[Message, msgl] with arguments {$MessageList} The problem may be unbounded. Specifying a value for MaxIterations greater than 5000 may improve the solution. String expected at position 1 in StringForm[MessageName[General, msgl], $MessageList].
Undefined message MessageName[Message, msgl] with arguments {$MessageList} String expected at position 1 in StringForm[MessageName[General, msgl], $MessageList].
Further output of MessageName[StringForm, string] will be suppressed during this calculation.
The problem may be unbounded. Specifying a value for MaxIterations greater than 5000 may improve the solution.
Könnten Sie bitte vorschlagen, wie dies behoben werden kann? Wie unten gezeigt, gab es kein Problem beim Ausführen derselben Ausdrücke im MMA-Notizbuch.
Antworten
Hier ist eine Möglichkeit, in Mathematica das zu tun, was Sie wollen.
Erstens kann die Verwendung von "PythonExpression" nützlich sein, um Dinge zu importieren / exportieren:
{edges,vl,ew,vd}=ImportString[#,"PythonExpression"]&/@ {"[(1,2),(1,3),(1,4),(2,5),(2,6),(5,6),(3,4),(3,7),(6,7),(7,8),(2,9)]",
"[1,2,3,4,5,6,7,8,9]","{(1,2):49.6,(1,3):74.4,(1,4):49.6,(2,5):37.2,(2,6):74.4,(5,6):49.6,(3,4):37.2,(3,7):24.8,(6,7):62,(7,8):37.2,(2,9):24.8}",
"{1:[75.,25.,0],2:[115.,45.,0],3:[10.,5.,0],4:[45.,0,0],5:[90.,60.,0],6:[45.,55.,0],7:[0,25.,0],8:[10.,50.,0],9:[115.,25.,0]}"};
Leider funktionieren Diagramme noch nicht mit Zuordnungen, sodass Sie Listen benötigen und Kanten Symbole wie UndirectedEdgeoder verwenden sollten DirectedEdge:
edges = UndirectedEdge @@@ edges; vcoords = List @@ vd;
ew = Normal @ KeyMap[UndirectedEdge @@ # &,ew];
g3d = Graph3D[vl, edges, VertexCoordinates -> vcoords,
EdgeWeight->ew, VertexLabels->Placed["Name",Center],
EdgeLabels->{e_:>Placed["EdgeWeight",Center]}, VertexSize->.5, BaseStyle->16]
Ihre Berechnung hat fast funktioniert, aber Sie mussten die Kanten in Regeln umwandeln:
vars3d = Array[Through[{x, y, z}@#] &, Length@vd];
\[Lambda] = 1/100.; lbnd = 0; ubnd = 500;
obj3d = Total[(Norm[vars3d[[First@#]] - vars3d[[Last@#]]] - # /. (Rule @@@ ew))^2 & /@ EdgeList[g3d]] + \[Lambda] * Total[Norm /@ (vars3d - Values@vd)];
solution3d = Last @ Minimize[{obj3d, And @@ Thread[lbnd <= Join @@ vars3d <= ubnd]}, Join @@ vars3d]
Dann funktioniert es gut:
edgeLengths3d = # -> Norm[vars3d[[First@#]] - vars3d[[Last@#]]] /.
solution3d & /@ EdgeList[g3d];
ResourceFunction["PrettyGrid"][{#, # /. ew, # /. edgeLengths3d} & /@
EdgeList[g3d], "ColumnHeadings" -> {"edge", "EdgeWeight", "Edge Length"}]
Entschuldigung, ich habe mich geirrt und mich nicht daran erinnert, dass Sie MMA von Python verwenden möchten und nicht umgekehrt. ExternalEvaluate ["Python", str] ist ein MMA-Befehl, nicht Python.
Hier erfahren Sie, wie Sie MMA-Eingaben von Python geben: "https://reference.wolfram.com/language/workflow/EvaluateAWolframLanguageExpressionFromPython.html".
Nach dem Start von Python führen Sie in Python Folgendes aus:
from wolframclient.evaluation import WolframLanguageSession
session = WolframLanguageSession()
from wolframclient.language import wlexpr
session.evaluate(wlexpr('myCommandString'))
Dabei ist myCommandString die Zeichenfolge mit Ihren Mathematica-Anweisungen. ZB in Python:
myCommandString="a=1;b=2;a+b"
Oder wenn Sie dies in mehreren Zeilen möchten:
myCommandString="a=1;"
myCommandString=myCommandString+"b=2;"
myCommandString=myCommandString+"a+b"
hoffe das hilft.
Wenn Sie einen Codeblock haben, der sich über mehrere Zeilen erstreckt, kann es hilfreich sein, ihn in eine .m-Datei und Getdie Datei aus Python einzufügen . Hier ist ein Beispiel:
Erstellen Sie zunächst eine Datei und schreiben Sie den Wolfram Language-Code, den Sie auswerten möchten. Rufen wir die Datei auf /tmp/test.m.
Jetzt in Python:
from wolframclient.evaluation import WolframLanguageSession
from wolframclient.language import wl
# important note: the session is automatically closed.
with WolframLanguageSession() as s:
s.evaluate(wl.Get('/tmp/test.m'))
Vergessen Sie nicht zu schließen, WolframLanguageSessionsonst erhalten Sie verwaiste Kernel (weitere Informationen hier ).
Wie Sie sehen, passt der Bewertungsschritt jetzt in eine Zeile. Sie können Ihren Code in Ihrem bevorzugten Editor aktualisieren. Genau das habe ich mit Ihrem ursprünglichen Code gemacht. Ich habe gerade zwei fehlende Semikolons hinzugefügt und das Ergebnis wie später ausgeführt exportiert.
Hier ist die meine /tmp/test.mDatei:
edges = {1 <-> 2, 1 <-> 3, 1 <-> 4, 2 <-> 5, 2 <-> 6, 5 <-> 6,
3 <-> 4, 3 <-> 7, 6 <-> 7, 7 <-> 8, 2 <-> 9};
vd = {{75., 25., 0}, {115., 45., 0}, {10., 5., 0}, {45., 0, 0}, {90.,
60., 0}, {45., 55., 0}, {0, 25., 0}, {10., 50., 0}, {115., 25.,
0}};
vl = Range[Length@vd];
vcoords = MapIndexed[#2[[1]] -> # &, vd];
ew = {1 \[UndirectedEdge] 2 -> 49.6, 1 \[UndirectedEdge] 3 -> 74.4,
1 \[UndirectedEdge] 4 -> 49.6, 2 \[UndirectedEdge] 5 -> 37.2,
2 \[UndirectedEdge] 6 -> 74.4, 5 \[UndirectedEdge] 6 -> 49.6,
3 \[UndirectedEdge] 4 -> 37.2, 3 \[UndirectedEdge] 7 -> 24.8,
6 \[UndirectedEdge] 7 -> 62, 7 \[UndirectedEdge] 8 -> 37.2,
2 \[UndirectedEdge] 9 -> 24.8};
g3d = Graph3D[vl, edges, VertexCoordinates -> vcoords,
EdgeWeight -> ew, VertexLabels -> Placed["Name", Center],
EdgeLabels -> {e_ :> Placed["EdgeWeight", Center]},
VertexSize -> .3, VertexStyle -> Red];
vars3d = Array[Through[{x, y, z}@#] &, Length@vd];
\[Lambda] = 1/100.;
obj3d = Total[(Norm[vars3d[[First@#]] - vars3d[[Last@#]]] - # /.
ew)^2 & /@ EdgeList[g3d]] + \[Lambda] Total[
Norm /@ (vars3d - vd)];
lbnd = 0;
ubnd = 500;
solution3d =
Last@Minimize[{obj3d,
And @@ Thread[lbnd <= Join @@ vars3d <= ubnd]}, Join @@ vars3d];
edgeLengths3d = # -> Norm[vars3d[[First@#]] - vars3d[[Last@#]]] /.
solution3d & /@ EdgeList[g3d];
z1 = Values[solution3d] // Partition[#, 3] &;
Export["/tmp/result.txt", z1, "Table"];
```