我在同一台机器上安装了Mathematica 7.01和Mathematica5.2。我希望能够从Mathematica7.01会话中评估5.2版本内核中的代码。我的意思是,运行Mathatica7.0.1标准会话时,我希望有一个像kernel5Evaluate这样的命令来计算5.2内核中的一些代码,并将结果返回到7.01内核中,并以在7.01内核中执行这些代码的方式链接7.01 FrontEnd记事本。
例如(在标准Mathematica v.7.01会话中):
In[1]:= solutionFrom5 = kernel5Evaluate[NDSolve[{(y^\[Prime])[x]==y[x],y[1]==2},y,{x,0,3}]]
Out[1]= {{y -> InterpolatingFunction[{{0., 3.}}, <>]}}
In[2]:= kernel5Evaluate[Plot3D[Sin[x y],{x,-Pi,Pi},{y,-Pi,Pi}]]
During evaluation of In[2]:= GraphicsData["PostScript", "\<\............
Out[2]= -SurfaceGraphics-在这两种情况下,结果应该是将v.5.2内核设置为v.7.01 FrontEnd中的“Notebook‘set”。当然,solutionFrom5变量应该设置为v.5.2内核返回的实际解决方案。
发布于 2011-02-16 13:33:59
这是我想要的东西的工作实现。按照Todd here的建议,我增加了对死MathLink连接的检查。现在,即使从内核以不寻常的方式终止,kernel5Evaluate也是可靠的。我还改进了Message的解析,并为kernel5Evaluate添加了一些诊断消息。以下是代码:
$kern5Path = "C:\\Program Files\\Wolfram Research\\Mathematica\\5.2\\MathKernel.exe";
Clear[printMessage, printPrint, printPostScript]
printMessage[str_String] :=
CellPrint@
Cell[BoxData[
RowBox[StringSplit[str,
x : ("MyDelimeterStart" | "MyDelimeterEnd") :> x] //. {x___,
"MyDelimeterStart", y_, "MyDelimeterEnd", z___} :> {x,
ToExpression[y], z}]], "Message",
CellLabel -> "(Kernel 5.2)", ShowCellLabel -> True];
printPostScript =
CellPrint@
Cell[GraphicsData["PostScript", #], "Graphics",
CellLabel -> "(Kernel 5.2 PostScript)", ShowCellLabel -> True] &;
printPrint[str_String] :=
CellPrint@
Cell[If[StringTake[str, -1] === "\n", StringDrop[str, -1], str],
"Print", CellLabel -> "(Kernel 5.2 print, text mode)",
ShowCellLabel -> True];
Clear[linkEvaluate]
SetAttributes[linkEvaluate, HoldAllComplete]
linkEvaluate[link_LinkObject, expr_] := Catch[
Module[{out = {}, postScript = {}, packet, result = Null},
If[LinkReadyQ[link],
While[LinkReadyQ[link],
Print["Rest of the buffer:\t",
packet = LinkRead[link, Hold]]];
If[Not@MatchQ[packet, Hold[InputNamePacket[_]]],
Message[kernel5Evaluate::linkIsBusy]; Throw[$Failed]]];
LinkWrite[link, Unevaluated[EnterExpressionPacket[expr]]];
While[
Check[Not@
MatchQ[packet = LinkRead[link, Hold],
Hold[InputNamePacket[_]]],
Message[kernel5Evaluate::linkIsClosed]; Throw[$Failed]],
Switch[packet,
Hold@DisplayPacket[_String],
AppendTo[postScript, First@First@packet],
Hold@DisplayEndPacket[_String],
AppendTo[postScript, First@First@packet];
printPostScript@StringJoin[postScript]; postScript = {},
Hold@MessagePacket[__], ,
Hold@TextPacket[_String],
If[StringMatchQ[First@First@packet,
WordCharacter .. ~~ "::" ~~ WordCharacter .. ~~ ": " ~~ __],
printMessage[First@First@packet],
printPrint[First@First@packet]],
Hold@OutputNamePacket[_], ,
Hold@ReturnExpressionPacket[_], result = First[First[packet]],
_, AppendTo[out, packet]
]
];
If[Length[out] > 0, Print["Unparsed packets: ", out]];
result
]];
Clear[kernel5Evaluate]
SetAttributes[kernel5Evaluate, HoldAllComplete]
kernel5Evaluate::usage = "kernel5Evaluate[\!\(\*
StyleBox[\"expr\",\nFontFamily->\"Times New Roman\",\n\
FontSlant->\"Italic\"]\)] writes \!\(\*
StyleBox[\"expr\",\nFontFamily->\"Times New Roman\",\n\
FontSlant->\"Italic\"]\) to MathKernel 5.2, returns output and prints \
messages generated during computation.";
kernel5Evaluate::linkIsBusy =
"Kernel 5.2 is still running previous calculation.";
kernel5Evaluate::linkIsClosed = "Connection to Kernel 5.2 is lost.";
kernel5Evaluate::kernel5NotFound =
"Path `1` not found. Please set variable $kern5Path to correct path \
to MathKernel 5.2.";
kernel5Evaluate[expr_] :=
If[TrueQ[MemberQ[Links[], $kern5]],
If[LinkReadyQ[$kern5]; First[LinkError[$kern5]] == 0,
With[{$kern5 = $kern5}, linkEvaluate[$kern5, expr]],
LinkClose[$kern5]; kernel5Evaluate[expr]],
Clear[$kern5];
If[FileExistsQ[$kern5Path],
$kern5 = LinkLaunch[$kern5Path <> " -mathlink -noinit"];
LinkRead[$kern5]; LinkWrite[$kern5,
Unevaluated[
EnterExpressionPacket[$MessagePrePrint = ("MyDelimeterStart" <>
ToString[ToBoxes[#]] <> "MyDelimeterEnd") &;
SetOptions[$Output, {PageWidth -> Infinity}];]]];
LinkRead[$kern5]; kernel5Evaluate[expr],
Message[kernel5Evaluate::kernel5NotFound, $kern5Path]; $Failed]
]下面是一些测试表达式:
kernel5Evaluate[Unevaluated[2 + 2]]
kernel5Evaluate[$Version]
kernel5Evaluate[Quit[]]
kernel5Evaluate[Print["some string"];]
kernel5Evaluate[Sin[1,]]
kernel5Evaluate[1/0]
kernel5Evaluate[{Plot[Sin[x], {x, 0, Pi}],
Plot[Sin[x], {x, -Pi, Pi}]}] //
DeleteCases[#, HoldPattern[DefaultFont :> $DefaultFont], Infinity] &
kernel5Evaluate[Plot3D[Sin[x y], {x, 0, Pi}, {y, 0, Pi}]];
ListPlot3D[First@%, Mesh -> Full, DataRange -> MeshRange /. Last[%]]
s = kernel5Evaluate[
NDSolve[{y'[x] == y[x] Cos[x + y[x]], y[0] == 1}, y, {x, 0, 30}]]
% // InputForm // Short
kernel5Evaluate[ContourPlot[Sin[x y], {x, -5, 5}, {y, -5, 5}]];
ListContourPlot[First@%, DataRange -> MeshRange /. Last[%],
Contours -> 10,
Method -> {"Refinement" -> {"CellDecomposition" -> "Quad"}}]发布于 2011-02-14 12:43:38
下面是一个基于Simon代码的实现。它仍然需要改进。我不清楚的是如何处理从内核(v.5.2)中生成的消息。
这是我的代码:
Clear[linkEvaluate]
SetAttributes[linkEvaluate, HoldRest]
linkEvaluate[link_LinkObject, expr_] := Catch[
Module[{out = {}, postScript = {}, packet, outputs = {}},
While[LinkReadyQ[link],
Print["From the buffer:\t", LinkRead[link]]];
LinkWrite[link, Unevaluated[EnterExpressionPacket[expr]]];
While[Not@MatchQ[packet = LinkRead[link], InputNamePacket[_]],
Switch[packet,
DisplayPacket[_], AppendTo[postScript, First@packet],
DisplayEndPacket[_], AppendTo[postScript, First@packet];
CellPrint@
Cell[GraphicsData["PostScript", #], "Output",
CellLabel -> "Kernel 5.2 PostScript ="] &@
StringJoin[postScript]; postScript = {},
TextPacket[_],
If[StringMatchQ[First@packet,
WordCharacter .. ~~ "::" ~~ WordCharacter .. ~~ ": " ~~ __],
CellPrint@
Cell[BoxData@
RowBox[{StyleBox["Kernel 5.2 Message = ",
FontColor -> Blue], First@packet}], "Message"],
CellPrint@
Cell[First@packet, "Output", CellLabel -> "Kernel 5.2 Print"]],
OutputNamePacket[_], AppendTo[outputs, First@packet];,
ReturnExpressionPacket[_], AppendTo[outputs, First@packet];,
_, AppendTo[out, packet]
]
];
If[Length[out] > 0, Print[out]];
Which[
(l = Length[outputs]) == 0, Null,
l == 2, Last@outputs,
True, multipleOutput[outputs]
]
]];
Clear[kernel5Evaluate]
SetAttributes[kernel5Evaluate, HoldAll]
kernel5Evaluate[expr_] :=
If[TrueQ[MemberQ[Links[], $kern5]], linkEvaluate[$kern5, expr],
Clear[$kern5]; $kern5 = LinkLaunch[
"C:\\Program Files\\Wolfram Research\\Mathematica\\5.2\\MathKernel.exe -mathlink"];
LinkRead[$kern5];
LinkWrite[$kern5,
Unevaluated[EnterExpressionPacket[$MessagePrePrint = InputForm;]]];
LinkRead[$kern5]; kernel5Evaluate[expr]]下面是测试表达式:
plot = kernel5Evaluate[Plot3D[Sin[x y], {x, 0, Pi}, {y, 0, Pi}]]
plot = kernel5Evaluate[Plot[Sin[x], {x, 0, Pi}]; Plot[Sin[x], {x, -Pi, Pi}]] //
DeleteCases[#, HoldPattern[DefaultFont :> $DefaultFont], Infinity] &
s = kernel5Evaluate[
NDSolve[{y'[x] == y[x] Cos[x + y[x]], y[0] == 1}, y, {x, 0, 30}]]
s // InputForm // Short
kernel5Evaluate[1/0; Print["s"];]它似乎如预期的那样起作用。不过可能会更好..。
发布于 2011-02-13 11:18:18
这是我想要的结果,
首先,我定义了linkEvaluate,它接受一个活动的Link,并将其传递给一个表达式。如果LinkRead还需要阅读一些东西,那么它就会读取它们,直到没有更多的内容为止。然后编写表达式并等待结果返回。然后,它读取输出,直到没有什么可读。通常,它返回第一个ReturnExpressionPacket,除非您将最终的可选参数all设置为True -在这种情况下,它返回它读取的所有内容。
Clear[linkEvaluate]
SetAttributes[linkEvaluate, HoldRest]
linkEvaluate[link_LinkObject, expr_, all : (True | False) : False] :=
Catch[Module[{out = {}},
While[LinkReadyQ[link], PrintTemporary[LinkRead[link]]];
If[LinkReadyQ[link], Throw["huh"]];
LinkWrite[link, Unevaluated[EnterExpressionPacket[expr]]];
While[! LinkReadyQ[link], Pause[.1]];
While[LinkReadyQ[link], AppendTo[out, LinkRead[link]]];
If[all, out, Cases[out, _ReturnExpressionPacket][[1, 1]]]
]];然后kernel5Evaluate首先检查全局$kern5是否定义为LinkObject,如果没有,则检查是否定义了全局LinkObject。然后,它简单地将工作转交给linkEvaluate。您必须将"math5“替换为MMA5.2内核的文件名和路径。
Clear[kernel5Evaluate]
SetAttributes[kernel5Evaluate, HoldAll]
kernel5Evaluate[expr_, all:(True|False):False] := If[TrueQ[MemberQ[Links[], $kern5]],
linkEvaluate[$kern5, expr, all],
Clear[$kern5]; $kern5 = LinkLaunch["math5 -mathlink"]; kernel5Evaluate[expr,all]
]https://stackoverflow.com/questions/4983301
复制相似问题