Cara menggunakan Mathematica dari Python

Sep 22 2020

Saya telah menggunakan baris kode berikut untuk menghasilkan geometri 3D ( ref ). Input edges, vd, vldan ewberasal dari Python dalam format berikut

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]}; 

Saya mengonversi secara manual di atas ke format input yang digunakan di Mathematica. Saya ingin tahu bagaimana menghindari konversi manual ini dan langsung mengintegrasikan dan menjalankan kode Mathematica dari Python.

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]

Saran tentang cara melanjutkan dan antarmuka Mathematica dari Python akan sangat membantu.

EDIT: Jawaban yang diposting di bawah ini membantu dalam menyampaikan argumen input dari Python menggunakan PythonExpression. Selanjutnya, saya ingin mengevaluasi ekspresi Mathematica ini dari skrip python. Berdasarkan komentar di bawah, saya menginstal wolframclient dan melakukan hal berikut

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: Bisakah saya melakukannya

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];'))

Saya mencoba,

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"];'
    ))

Tapi saya mendapatkan kesalahan berikut,

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.

Bisakah Anda memberi tahu bagaimana ini bisa diperbaiki? Seperti yang ditunjukkan di bawah, tidak ada masalah dalam menjalankan ekspresi yang sama di notebook MMA.

Jawaban

3 M.R. Sep 23 2020 at 02:06

Berikut salah satu cara untuk melakukan apa yang Anda inginkan di Mathematica.

Pertama, menggunakan "PythonExpression" bisa berguna untuk mengimpor / mengekspor barang:

{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]}"};

Sayangnya Grafik belum berfungsi dengan Asosiasi, jadi Anda memerlukan daftar, dan tepi harus menggunakan simbol seperti UndirectedEdgeatau 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]

Perhitungan Anda hampir berhasil, tetapi Anda perlu membuat tepinya menjadi aturan:

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]

Kemudian berfungsi dengan baik:

edgeLengths3d = # -> Norm[vars3d[[First@#]] - vars3d[[Last@#]]] /. 
     solution3d & /@ EdgeList[g3d];
ResourceFunction["PrettyGrid"][{#, # /. ew, # /. edgeLengths3d} & /@ 
  EdgeList[g3d],  "ColumnHeadings" -> {"edge", "EdgeWeight", "Edge Length"}]

2 DanielHuber Sep 25 2020 at 17:47

Maaf, saya salah dan tidak ingat bahwa Anda ingin menggunakan MMA dari Python dan bukan sebaliknya. ExternalEvaluate ["Python", str] adalah perintah MMA, bukan Python.

Cara memberikan masukan MMA dari Python dijelaskan di sini: "https://reference.wolfram.com/language/workflow/EvaluateAWolframLanguageExpressionFromPython.html".

Setelah memulai Python, Anda menjalankan dengan Python:

from wolframclient.evaluation import WolframLanguageSession

session = WolframLanguageSession()

from wolframclient.language import wlexpr

session.evaluate(wlexpr('myCommandString'))

di mana myCommandString adalah string dengan pernyataan Mathematica Anda. Misal dengan Python:

myCommandString="a=1;b=2;a+b" 

Atau jika Anda menginginkan ini di beberapa baris:

myCommandString="a=1;"

myCommandString=myCommandString+"b=2;"

myCommandString=myCommandString+"a+b"

semoga ini membantu.

1 DorianB. Sep 25 2020 at 16:51

Jika Anda memiliki blok kode yang mencakup beberapa baris, mungkin berguna untuk memasukkannya ke dalam file .m, dan Getfile dari python. Berikut ini contohnya:

Pertama buat file dan tulis kode Bahasa Wolfram yang ingin Anda evaluasi di dalamnya. Mari kita panggil file tersebut /tmp/test.m.

Sekarang dengan 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'))

Jangan lupa untuk menutup WolframLanguageSessionjika tidak Anda akan mendapatkan orphan kernel (info lebih lanjut di sini ).

Seperti yang Anda lihat, langkah evaluasi sekarang cocok dalam satu baris. Anda bebas memperbarui kode Anda di editor favorit Anda. Itulah yang saya lakukan dengan kode awal Anda, saya baru saja menambahkan dua titik koma yang hilang, dan mengekspor hasilnya seperti yang dilakukan nanti.

Ini /tmp/test.mfile saya :

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"];
```