gpt4 book ai didi

wolfram-mathematica - 如何动态生成mathematica代码?

转载 作者:行者123 更新时间:2023-12-04 03:16:56 25 4
gpt4 key购买 nike

我想用 mma 制作一种迷你编程语言。从文本文件到包中的模块。理想情况下,我应该能够通过另一个包中的函数从 Mathematica 中生成包和模块。

问题:
这可能吗?我正在寻找一个引用或一个例子来开始这个。

编辑:
例如:

想象一个具有 n 个整数类型寄存器的内存库。

指令是:

1 Z(n)

2 C(m,n)

3 J(m,n,q)

4 S(n)

每行都有一个地址。第一行 1,第二行 2 等等。
Z(n) 在寄存器 n 中存储 0。
C(m,n) 将寄存器 m 的值存储在寄存器 n 中。
J(m,n,q) 如果寄存器 m 的值等于寄存器 n 的值,则跳转到地址 q 所在的行。
S(n) 将寄存器 n 中的值加 1。

然后给定两个工作程序 P 和 Q,我想生成连接程序 P+Q。

然后给定两个工作程序 P 和 Q,我想在 P 之后生成替换 Q。

最后我想开始尝试递归......这个“迷你项目”的目的。

最佳答案

你的问题有几个部分。首先,如果您想为您的语言使用一些非 mma 语法,您需要制作一个从您的语言到 mma 表达式(代码的 AST)的解析器。我将忽略这个(因为这是一个单独的主题)并假设您愿意使用 mma 语法或有办法将您的程序转换为某个 mma 表达式。

关于 mma 代码生成,Mathematica 非常适合它,因为它包含代码即数据范式。这里最难的部分是评估控制——我们要确保我们生成的代码段在代码生成过程中不会被评估。评估控制的标准技术可以成功地用于此,但这通常会使事情变得相当复杂。我将说明一种 mma 代码生成技术,它不是最好/最强大的技术,但最简单。

考虑由这些定义创建的玩具语言:

SetAttributes[testSet, HoldFirst];
SetAttributes[testIf, HoldRest];
SetAttributes[testVar, HoldAll];
SetAttributes[module, HoldAll];
SetAttributes[{package, inContext}, HoldRest];
testPlus[x_, y_] := Plus[x, y];
testTimes[x_, y_] := Times[x, y];
testDivide[x_, y_] := If[y == 0, Inf, Times[x, Power[y, -1]]];
testPower[x_, y_] := If[x == 0 && y < 0, Inf, Power[x, y]];
testSet[HoldPattern[testVar[x_]], expr_] := Set[x, expr];
testVar[x_] := If[ValueQ[x], x, Throw[$Failed, {"varundef", x}]];
testIf[cond_, expr_] := If[cond, expr];
testIf[cond_, expr_, else_] := If[cond, expr, else];
module[{vars__}, body_] := Module[{vars}, body];
package[name_, code_] := (BeginPackage[name]; code; EndPackage[]);
inContext[name_, code_] := (Begin[name]; code; End[]);

这是这种新语言的一小段代码(包含在 Hold 中):
cd = 
Hold[module[{a}, testSet[testVar[a],
testPlus[testTimes[testTimes[testPlus[1, 2],
testPower[testPlus[3, 4], -1]], testPlus[5, 6]], -7]]; testVar[a]]]

它对应于这个 mma 代码:
Module[{a},a = (1 + 2)/(3 + 4)*(5 + 6) - 7; a]

我们的代码生成器基于一个非常简单的想法——我们将反复应用本地规则到我们持有的代码。本地规则将从我们的函数定义中提取,如下所示:
ClearAll[expansionRules];
expansionRules[heads : {__Symbol}] := Flatten[DownValues /@ heads]

我们需要为我们的语言提供一个头部列表。我将手动执行此操作,但通过创建自定义赋值运算符很容易实现自动化。
allHeadsToExpand[] := {testIf, testVar, testPlus, testTimes, testDivide, 
testPower, testSet, testIf,module,package, inContext}

现在,我们生成我们的代码:
In[195]:= expanded = cd//.expansionRules[allHeadsToExpand[]]

Out[195]=
Hold[Module[{a},
a = ((1 + 2) If[3 + 4 == 0 && -1 < 0, Inf, 1/(3 + 4)]) (5 + 6) - 7;
If[ValueQ[a], a, Throw[$Failed, {"varundef", a}]]]]

要执行它,您可以简单地使用 ReleaseHold :
In[197]:= ReleaseHold[expanded]

Out[197]= -(16/7)

我们构造的好处是我们也可以直接执行我们的AST:
In[198]:= ReleaseHold[cd]

Out[198]= -(16/7)

要将其保存到包中,您可以简单地使用 Put命令。以您想要的任何方式扩展语言也很容易。当然,这种语言的代码看起来并不漂亮,因为它本质上是用 mma 表达式表示的 AST。为了让它更漂亮,你需要引入你自己的语法并编写一个解析器到 mma AST,但那是另一回事了。

编辑

关于代码生成的自动化并将生成的代码保存到一个包中:这里有几个实用程序可以做到这一点。
Clear[generateCode];
generateCode[code_Hold] :=
code //. expansionRules[allHeadsToExpand[]] //.
HoldPattern[
CompoundExpression[left___, CompoundExpression[middle___], right___]] :>
(left; middle; right);

Clear[formatCode];
formatCode[code_Hold] :=
StringReplace[Function[Null, ToString[Unevaluated[#], InputForm], HoldAll] @@
code, ";" :> ";\n"];

Clear[saveCode];
saveCode[file_, generatedCode_] :=
With[{result = BinaryWrite[file, formatCode@generatedCode]},
Close[file];
result];

这是相同的示例,但放在一个包中:
cdp = Hold[
package["myPackage`",
inContext["`Private`",
module[{a},
testSet[testVar[a],
testPlus[testTimes[testTimes[testPlus[1, 2],
testPower[testPlus[3, 4], -1]], testPlus[5, 6]], -7]];
testVar[a]]]]]

我们生成并保存代码如下:
In[101]:= file = FileNameJoin[{"C:","Temp","myPackage.m"}]
Out[101]= C:\Temp\myPackage.m

In[106]:= saved =saveCode[file,generateCode[cdp]]
Out[106]= C:\Temp\myPackage.m

我们可以 Import它来测试:
In[107]:= Import[file,"Text"]

Out[107]=
BeginPackage["myPackage`"];
Begin["`Private`"];
Module[{a}, a = ((1 + 2)*If[3 + 4 == 0 && -1 < 0, Inf, (3 + 4)^(-1)])*(5 + 6) - 7;
If[ValueQ[a], a, Throw[$Failed, {"varundef", a}]]];
End[];
EndPackage[]

编辑 2

关于您的语言代码的外观,您可以通过使用 Notation 包更改您输入代码的方式和 Format 来使代码更漂亮,而无需一路创建自己的解析器。/ FormatValues控制前端如何呈现它。

关于wolfram-mathematica - 如何动态生成mathematica代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6214946/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com