如何将Mathematica二进制转储文件转换为定义列表?

7
根据文档所述,"DumpSave 以一种针对 Mathematica 输入进行优化的二进制格式编写定义。" 是否有一种方法可以将 Mathematica 二进制转储文件转换回定义列表而不评估它们?Import["file.mx","HeldExpression"] 不起作用...

@Simon "file.mx" 可以创建自己的上下文并在任何现有上下文中添加其他定义。更糟糕的是,它可以添加或部分更改现有符号的定义。因此,仅通过比较系统两个状态来恢复其定义可能非常困难。 - Alexey Popkov
1
@Simon 我寄希望于的一件事是,Mathematica 使用的转储文件格式并不是唯一的,它只是使用了一些标准的方法来创建转储文件。因此,如果有人知道这个标准(如果它存在的话),很可能可以解码这样的文件。我强烈怀疑这种标准的存在。 - Alexey Popkov
你需要“.mx”文件做什么?“.wdx”文件是否可以作为DumpSave的替代方案? - Simon
1
一番搜索后,我找到了这个Perl脚本:Mathematica Disassembler。但是对我来说并没有用(可能是因为我在运行64位Linux而该脚本是针对x86 .mx文件的)。或许你会有更好的运气。 - Simon
@Simon 可能你已经尝试过使用在64位系统下创建的转储文件运行这个脚本。但是你可以在 Mathematica 安装目录中轻松找到很多32位的转储文件。例如,在 FileNameJoin[{$InstallationDirectory,"SystemFiles","Kernel","SystemResources"}] 目录的适当子目录中查找。我没有安装Python,也没有相关经验,所以现在无法自行检查。但也许这个脚本是一个合适的解决方案。 - Alexey Popkov
显示剩余5条评论
2个回答

6

DumpSave函数用于存储与符号相关的值,例如OwnValuesDownValuesUpValuesSubValuesDefaultValuesNValuesFormatValues

这些值是在Mathematica会话中评估后保存的。

这些值存储在内部格式中。通过读取这个内部格式,MX文件只创建符号并将这些值填充到它们中,而绕过了求值器。

也许你可以分享一下引起你提出这个问题的问题。


[编辑] Alexey提出的问题有所澄清。MX文件保存符号定义的内部表示。看起来Mathematica在内部跟踪:

f[x_Real] := x^2 + 1
DumpSave[FileNameJoin[{$HomeDirectory, "Desktop", "set_delayed.mx"}], 
  f];
Remove[f]
f[x_Real] = x^2 + 1;
DumpSave[FileNameJoin[{$HomeDirectory, "Desktop", "set.mx"}], f];
setBytes = 
  Import[FileNameJoin[{$HomeDirectory, "Desktop", "set.mx"}], "Byte"];
setDelayedBytes = 
  Import[FileNameJoin[{$HomeDirectory, "Desktop", "set_delayed.mx"}], 
   "Byte"];

可以使用SequenceAlignment[setBytes, setDelayedBytes]来查看差异。我不知道为什么要这样做,但我的观点依然成立。在使用DumpSave保存值之前,所有使用Set构建的值的计算都已在Mathematica会话中完成。当读取MX文件时,内部表示将重新读入Mathematica会话,并且实际上不执行加载定义的任何计算。


一个小例子来说明“规则本身会通过求值器运行”的语句:比较 Clear[f];f[x_Real]=x^2+1;DumpSave["f.mx",f];Clear[f];f=a;<<f.mx;Definition[f]Clear[f]; f = a; f[x_Real] = x^2 + 1; Definition[f] - Alexey Popkov
在这里完全非平凡的是,即时定义(如“f[x_Real] = x ^ 2 + 1;”)被恢复为即时定义,而不是延迟定义。因此,在引文中强调的语句(已添加强调)“DumpSave存储与符号相关联的值,即OwnValuesDownValuesUpValuesSubValuesDefaultValuesNValuesFormatValues这些值被存储为延迟规则”显然是错误的。 - Alexey Popkov
使用 DumpSaveDumpGet 似乎是保存并恢复符号的原始定义的唯一方法,并且拥有保证。即使使用 Save 也不能提供这样的功能,因为它将定义存储在 SetSetDelayed 定义的标准形式中,在读入导出文件时再次评估。这样,这些定义可能会被涉及符号的现有定义更改。例如,设置 x=1 将破坏对 f=x 的进一步恢复定义等。 - Alexey Popkov
2
请注意,Save会保存文本文件,并且Mathematica必须解析和评估这些规则以将它们转换为内部格式,而DumpSave则保存内部结构,可以通过绕过求值器来读取。因此,将x设置为任何值都不会影响读取回来的内容。在评估了x = 1.0; Get[ FileNameJoin[{$HomeDirectory, "Desktop", "set.mx"}]]; f[3.0]之后,我得到了正确的值为10.0。因此,我仍然没有看到任何问题。您能发布展示所述问题的代码吗? - Sasha
问题在于我们无法读取.mx文件,也没有任何可读的替代格式,但我们显然可以有它!如果“保存”将其定义以对..Values的赋值形式保存,那么这几乎就是所需的。但是更好的方法是以某种方式能够读取.mx文件。 - Alexey Popkov
显示剩余6条评论

2

您可以将Rule分配给DownValues,而不是RuleDelayed,这相当于立即定义。赋值语句的右侧保持未求值状态并且被逐字复制,因此与之对应的命令也是如此。

Clear[f]; 
f[x_Real] = x^2 + 1;
DumpSave["f.mx", f];
Clear[f];
f = a;
<< f.mx;
Definition[f]

would be

Clear[f];
f = a;
DownValues[f] := {f[x_Real] -> x^2 + 1}
Definition[f]

f = a

f[x_Real] = x^2+1

(与您的示例Clear[f]; f = a; f[x_Real] = x^2 + 1; Definition[f]相比,该示例可以正常工作,而不是给a[x_Real]赋值规则)。这也适用于先前对x的任何赋值。


编辑:它不能很好地处理右侧的副作用,如下面评论中的示例所示。要分配一个downvalue避免任何评估,可以使用未记录的System`Private`ValueList,如下所示:

Clear[f];
f := Print["f is evaluated!"];
DownValues[f] := System`Private`ValueList[f[x_Real] -> Print["definition is evaluated!"]];

请注意,这个任务似乎被转换成了延迟规则:
DownValues[f]

{HoldPattern[f[x_Real]] :> x^2 + 1}

但是Definition(和Save)显示与:=的区别在内部已经被保留。我不知道为什么DownValues不显示真相。

回答原始问题,您可能最好使用导入转储文件并使用Save导出相关符号,然后,如果希望将其加载到先前定义过的内核中,可以像上面那样以编程方式将分配转换为DownValues的分配。在导出之前,将变量范围限定在私有上下文中可能更容易,这就是系统文件所做的事情,以防止冲突。


我刚刚检查了 Mathematica 5.2、8.0.4 和 10.3.1,并发现在向 DownValues 进行 SetDelayed 赋值时,右侧仍然会被计算,请尝试以下代码:Clear[f];f:=Print["f is evaluated!"];DownValues[f] := {f[x_Real] -> Print["definition is evaluated!"]};(它会输出 "f is evaluated!" 和 "definition is evaluated!")。 - Alexey Popkov
1
感谢您找到这个!实际上,这形成了在我的最近自我回答中无法在其他地方找到的分配“List”和“SystemPrivateValueList”给“DownValues”的示例,http://mathematica.stackexchange.com/a/108974/6041。 因此,考虑到这一点,我认为这是一个解决方案:Clear[f]; f:= Print ["f is evaluated!"]; DownValues [f]:= System`Private`ValueList [ f [x_Real] -> Print["definition is evaluated!"]]; - The Vee
好发现!请纠正你的答案,以免误导未来的读者。另一种方法是使用未记录的 Language`ExtendedDefinitionLanguage`DefinitionList 以相同的方式。 - Alexey Popkov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接