针对高度依赖数学的用户编码,推荐一种脚本或插件语言?

48

我已为这个问题发起了悬赏

......因为我真的希望社区可以提供意见。我可以(也确实)查看几种语言/框架,并认为“嗯,这可能可以正常工作”——但我真的很感激基于我面临的问题的建议,特别是来自任何具有集成/使用您推荐内容经验的人。


我从事科学分析软件的开发。它提供了许多用于数据数学转换的工具。其中一个工具允许用户输入自己的方程式,该方程式在数据集(一个大的二维或三维值矩阵)上运行并进行评估。
这个工具有一个图形化的方程式编辑器,内部构建了一个面向对象的表达式树,每个操作都有不同的对象(例如,Logarithm类的实例是树中计算值基数对数的节点;它有两个子节点作为输入)。以下是其中一部分的屏幕截图:

enter image description here

您可以在左侧看到它正在构建的树,右侧菜单中有许多(50个?)潜在操作。
这有一些缺点:
- 对于复杂方程,图形编辑器变得笨拙。 - 有一些难以用图形表示的操作,例如创建大矩阵(例如n x n卷积的内核)。 - 它只允许方程式:没有分支或其他逻辑。
当它更简单时,它很整洁,但对于我们的用户想要使用它进行的操作来说不再如此。如果我现在写它,我会用完全不同的方式 - 这是我的机会 :)
我想为用户提供更强大的东西,并让他们编写可以执行更高级操作的代码 - 脚本或编译代码。 我正在寻求SO关于应该使用哪种技术或采取何种方法的建议。
这个问题的其余部分相当长 - 很抱歉。我尝试详细描述问题。先感谢您阅读 :)
重要约束条件:
我们的数学运算是在大矩阵上进行的。在上述方程中,V1代表输入(可能有多个),是2D或3D的,每个维度都可以很大:在数千或数十万的数量级上。(我们很少一次计算所有内容,只是切片/段。但如果答案涉及需要编排数据的内容,请注意大小和速度是要考虑的因素。)
我们提供的操作允许您编写,例如,2 x V,它将V中的每个元素乘以2。结果是另一个相同大小的矩阵。换句话说,包括标准数学原语的脚本或编程语言是不够的:我们需要能够控制可用的原语如何实现它们。
这些操作可能很复杂:输入可以简单地是一个数字(2、5.3、pi),也可以是包含数值布尔值复数(成对的值)数据的1、2或3维矩阵。我目前的想法是使用强大到可以将我们的数据类型公开为类并实现标准运算符的语言。一个简单的评估器是不够的。
与其只编写在一个或多个输入上迭代计算以提供输出的操作(目前可以通过表达式评估器轻松实现),不如让用户能够:为输入提供不同大小的输出;调用其他函数等。对于主机程序,能够询问用户代码将需要哪个部分或切片的输入来评估输出的一部分或切片将非常有用。我认为公开我们的某些类并使用面向对象的语言可能是实现这些点的最佳方式。
我们的受众主要是研究科学家,他们要么不习惯编码,要么可能习惯于像Matlab或R这样的语言。
我们使用Embarcadero C++ Builder 2010进行开发,还有少量Delphi。这可能会限制我们可以利用的内容 - 只因为某些东西是C++,并不意味着它只是针对VC++或GCC进行了编码就能起作用。它还必须适用于商业软件的使用。
我们的软件目前具有COM接口,并且应用程序的一部分可以通过我们的应用程序作为外部进程COM服务器自动化。如果需要,我们可以向某些内部对象添加COM接口,或者专门为此制作第二个COM框架。
“工具”,包括这个工具,正在迁移到多线程框架。最终解决方案需要能够在任何线程中执行,并且在许多线程中同时有多个实例。这可能会影响托管的语言运行时 - 例如,Python 2.x具有全局锁。
使用具有数学或科学用途库的语言将是很好的选择。
与旧表达式工具的向后兼容性并不重要。这是第2版:从头开始!

目前的想法:

  • RemObjects Pascal ScriptDWScript是易于绑定到TObject派生类的语言。我不知道是否可能提供操作符重载。
  • 托管.Net运行时,并加载基于C#(例如)的DLL作为插件。我很喜欢这个想法:我见过这样的做法,其中宿主程序提供了语法高亮、调试等功能。虽然我听说需要大量的编码工作,但这将使IronPython和F#也能够使用。
    • RemObjects Hydra看起来是实现这一点的有趣方法。不幸的是,它是为Delphi而非C ++ Builder设计的;我正在研究兼容性。
  • 托管像Python这样的东西,从RAD Studio中可行
  • 提供BPL接口,并让用户直接针对我们的程序进行编码,如果他们购买了RAD Studio的副本(即提供插件接口,并通过接口公开类;可能需要使用与我们IDE版本兼容的二进制兼容插件)
  • ...
感谢您的回复!即使它们不完美,我也很感激所有的答案-我可以进行研究,只是需要指引和意见(请在答案中包含原因:p)关于如何处理它或什么可能适合。每个答案,无论多么简短,都将受到赞赏。但如果您详细推荐某些内容而不仅仅是“使用语言X”,我会非常有兴趣阅读它:)
干杯,
大卫
更新:
到目前为止,已经推荐了以下内容:
  • Python: 2.6有全局锁,这听起来像是一个游戏杀手。3(显然)还没有得到有用库的广泛支持。对我来说(我知道我是Python社区的外部人员),它似乎有点分裂 - 使用它真的安全吗?

  • Lua:似乎不直接面向对象,但提供了“元机制来实现功能,而不是在语言中直接提供大量功能”。从程序员的角度来看,这听起来非常酷,但它并不针对想要玩耍的程序员。考虑到目标受众,我不确定它会运作得有多好 - 我认为提供更多内置基础的语言会更好。

  • MS脚本/ActiveScript。我们已经提供了一个外部COM接口,我们的用户通常使用VBScript自动化我们的软件。但是,我希望有一个比VBS更强大(而且,坦率地说,设计更好)的语言,我也不认为JScript适合。我也不确定在COM上可能存在哪些数据传输问题 - 我们有很多数据,通常是非常具体的类型,因此速度和保持这些类型非常重要。

  • Lisp:我甚至没有考虑过这种语言,但我知道它有很多粉丝。

  • 托管.Net插件:没有任何人提到。这不是一个好主意吗?您可以获得C#,F#,Python...是否具有与COM相同的数据传输问题?(通过COM工作的CLR托管是否有效?)

澄清一下:我所说的“矩阵”是指Matlab变量意义上的矩阵,即一个包含大量数值的巨型表格,而不是像你在3D软件中使用的4x4转换矩阵。这是随着时间收集的数据,通常每秒钟多次记录成千上万个值。我们也不需要计算机代数系统,而是需要用户能够编写完整插件并编写自己的数学公式 - 尽管如果该系统具有处理复杂数学问题的能力,如计算机代数系统,则会很有用。如果两者不能混合使用,我会选择“全语言”而不是“代数”,以允许用户代码中出现复杂分支/路径以及面向对象接口。

1
说实话,这听起来很像Matlab:http://www.mathworks.com/products/matlab/ - Stijn Sanders
@Stijn Sanders:是的...我试图一般性地描述它,而不涉及特定领域,但我猜这个特定组件可能会类似。整个产品做得更多,这只是其中的一小部分 :) 一些用户使用Matlab,如果我们提供足够的功能,他们就不必使用了。 - David
如果你需要一个迷你版的Matlab,或许wxMaxima是一个不错的选择...就像我在我的回答中所说的那样。 - Warren P
只是好奇,你倾向于哪种脚本语言? - ezpresso
@ezpresso:目前,可以选择Python或托管的.Net运行时。自从我提出这个问题以来,我还没有时间进一步调查(可能很长一段时间都不会有时间)。我倾向于使用.Net,因为用户可以使用多种语言(包括Python),并且插件最终将被编译而不仅仅是解释。它还有一个非常有用的库。这些语言也都相当普遍(特别是与Lua之类的东西相比),这将希望使新手用户更容易学习它们。 - David
显示剩余2条评论
12个回答

18

根据您的需求,这里有一些指南:

  • 区分语言和库-您可以拥有数学语言(如MATLAB)或从高级语言(如Python)调用的数学库;
  • 语言(或库)应由数学家为数学家设计;
  • 使用的语言应该是现有的(不要重复发明轮子);
  • 您应该能够与现有软件共享脚本内容;
  • 您不应该从头开始启动这样一个庞大而复杂的项目(数学脚本)。

所以我猜它可以缩小候选名单:

  • JavaScript没有为这种用途设计(未被使用);
  • Delphi脚本(DWS或PascalScript)主要用于自动化,而不是计算(并且并不广泛使用);
  • 我不知道你为什么在客户应用程序中谈论使用Delphi IDE,但你不应该为这样的专有开发使用Delphi IDE:基本的自定义IDE将比完整的RAD更具生产力;
  • Lua也许应该考虑:您可以使用此脚本引擎制作所需的任何内容-但是与Python不同,没有大量的数学家社区使用Lua...

在开源世界中,您可以找到许多非常有趣的解决方案。请参见http://blog.interlinked.org/science/open_source_math_programs.html

我认为应该考虑Octave。它简单、功能强大、成熟、广为人知、被许多软件使用并跨平台。

据我所知,您可以从C / C ++代码中调用 Octave库 。在翻译相关的.h文件后,这可以在Delphi IMHO中完成。

但要注意GPL许可证。如果您的软件是专有的,将Octave作为软件的一部分可能是不可能的。但是,如果您明确区分了您的软件和GPL软件,则可以从您的软件调用Octave库或任何其他GPL东西(如Python)

嵌入Python可能是一个不错的解决方案。可以从Delphi调用这种语言,并且您应该拥有良好的体系结构,无需直接调用一些C库,如Octave。 Python可以成为从Delphi应用程序访问所有其他计算库的主要门户。例如,Octave可以从某些Python库中调用。您还可以使用Python脚本自动化自己的应用程序。而且你在Delphi周围有一些Python IDE 。当然,每个组件的开源许可证是安全的。我越想越喜欢后者的解决方案...

仅我的两分钱


感谢@A. Bouchez!听起来Python很不错。您有使用它或将类绑定到它等方面的经验吗?是否存在任何开源许可问题?连接调试器有多容易,以便我们可以为用户提供原始开发环境?关于Delphi IDE,它的成本与我们软件的成本相比很小,因此如果他们想要开发,我们可以说“使用这个IDE”,提供一个插件模板,他们就可以得到一个功能齐全的东西。 - David
1
Lua - Roddy
@A. Bouchez:这是最高票答案,赏金期已结束...享受额外的+150!Python 也值得研究(下面的另一个答案也提到了它)。 - David
@A. Bouchez:同意:) 我发布了一个元问题来更改它。与此同时,我刚刚授予了您第二个赏金。谢谢! - David
@David 我不确定我是否非常熟悉SO政策和所有这些问题。无论如何,感谢第二个赏金! - Arnaud Bouchez
显示剩余10条评论

7

没有确定的答案,但还有一些其他建议:

  • 看看 LMD Innovative 的 ScriptPack,它支持本机 Pascal 脚本和基于 ActiveScripting 的语言。注意:我使用了很多 LMD 工具和组件,但我个人没有使用过 Scriptpack。

  • LMD 还有一个 IDE-Tools package,如果您需要走这条路,它可以真正简化制作简单自定义“RAD”工具的任务。

  • 另外支持 Lua。我在 C++Builder2010 应用程序中使用 Lua 作为脚本语言,它运行良好。您可以利用 C++Builder/Delphi RTTI 来帮助 Lua 脚本和您的 C++ 代码之间的集成。

关于Lua:我们的产品多年来一直有一个超级简单的“自制”脚本系统。没有循环、条件或程序,只有一系列参数化的命令。我们希望将其扩展为更强大的东西,选择第三方解决方案似乎比重新发明轮子要容易得多。选择Lua的主要原因是:

  • 快速
  • 有出版的书籍可用(Programming in Lua
  • 用C语言编写
  • 可以通过静态链接直接嵌入我们的项目中
  • MIT许可证
  • C++代码可以调用Lua代码并访问Lua变量
  • Lua代码可以调用C++函数
  • 部署占用空间小。在压缩之前,Lua及其标准库仅增加了不到200K的.EXE文件大小。

我相信其他语言可能同样好,但是Lua的“轻量级”特性使我倾向于它。


谢谢@Roddy。完全本地编译的脚本语言听起来不错!他们的IDE工具也很有用。我对Lua不是很了解:你为什么推荐它? - David
@David M:已更新答案 :-) - Roddy

5
我喜欢那里的许多答案,好吧,我是一个有偏见的Delphi迷 :) 但我建议您使用组合:RO Pascal Script + ESBPCS for VCL。
我不知道这是否适合您,但我会尝试一下。
从网站上,我提取了关于库的矩阵非可视部分的此链接。还有许多其他内容,您可能想尝试一下!

嗨@Andrea - 感谢您的回答。我认为ESBPCS可能针对比我们小得多的矩阵...也许术语“矩阵”的使用略有不同。我们基本上指的是大型网格(如果在Excel中),或数字表格,而不是用于变换或“标准”矩阵数学的矩阵。 - David
嗨,大卫,我不知道你的确切要求是什么...可能找出最好的方法是问他们 :) - Andrea Raimondi

5
使用Python,您可以免费获得NumPySciPy。是的,有GIL,但仅在Python解释器运行多个线程时才会激活。我相信您可以在单独的线程中运行多个Python主机而不会出现问题(尚未尝试过)。
此外,还有类似multiprocessing的东西。
Python 3仍在普及中,NumPy从版本1.5.0开始支持Python 3,而SciPy从版本0.9.0开始提供支持。此外,GIL仍然存在于Python 3中,尽管已进行重新设计,因此应该更好。此外,NumPy在操作期间释放锁定

NumPy和SciPy看起来非常有用。这正是我希望找到的那种库——你应该得到比我能给你的一个赞更多 :) 我认为在单独的线程中使用多个Python主机可能是避免GIL的方法。 - David
还可以查看 SciPy 推荐的绘图库 matplotlib:http://matplotlib.sourceforge.net/ - Harriv

4
我们一直很成功地使用Microsoft脚本自动化(活动脚本)。基本上,您需要实现一个主机来运行这些脚本。脚本可以用任何已安装在当前机器上的语言编写。我们正在使用JavaScript编写脚本,但并不限于此。有许多脚本实现 (甚至是Python)。

从您的角度来看,您将需要提供一个框架来运行脚本。虽然不简单,但只要您了解基本的COM,它也并不难。有为Delphi设计的实现。这里有一些资源:http://www.torry.net/pages.php?id=280,但您可以在整个网络上找到资源。

祝你好运!


谢谢你的回答。我想我一直希望有比 MS 脚本更复杂或更紧密集成的东西 - 我们实际上已经支持了外部自动化我们软件的脚本。我不确定它是否真的适合使用我们的内部类、传递大量数据等(它们是后期绑定的,对吧?)。不过还是谢谢你,我会研究一下的! - David

4
我建议使用Lua。它是最常用的脚本语言之一,有许多工具,如调试器、带语法高亮的编辑器等。许多人都使用过它,它是你可以轻松插入C/C++引擎的最快速的脚本语言之一。将C函数扩展到其中非常容易(特别是如果您使用LuaJIT加上FFI)。在Lua中没有真正好的多线程方法,但您可以轻松地在单独的线程中运行多个Lua实例以运行多个脚本。

嗨@Simon!感谢您的回答 - 特别是针对多线程的解答 :) 另一个答案也推荐了Lua。我不太了解它:如果您不习惯编程,它是否易于阅读/编写?您可以创建/使用类吗?您说您可以将C函数扩展到其中,但是将C++类公开以提供OO接口有多容易? - David
2
无论您选择哪种脚本语言,您都可以使用SWIG将C++类暴露给它。(SWIG支持Python、TCL、Lua等语言。) - Nemo
@David M:Lua非常容易使用。我不会说这种编程语言在语法上很难,所以学习它可能相当简单。你可以使用类,有一些包装器可以帮助你完成这个(在lua.org上检查,他们比我更擅长描述这些东西)......尽管个人而言,我更喜欢通过类似于C的接口将事物暴露给Lua。(或通过FFI - http://luajit.org/ext_ffi.html)。 - Simon
@Nemo,感谢您提出SWIG建议 - 对我来说也很有趣! - Roddy

4

因为你需要一个数学定向的脚本语言,我建议你看一下Common Lisp。它是LISP的方言,最初被开发为计算机程序的传统数学符号。像MaximaAxiom这样的计算机代数系统都是用Common Lisp编写的。最显著的Common List实现是ECL,它在LGPL许可下发布。当然,还有许多其他的开源实现。

此外,还有Scheme编程语言(一种Lisp方言)的GNU Guile解释器。他们的网站上说:

Guile是一个高效的虚拟机,它执行由其优化编译器生成的可移植指令集,并且非常容易与C和C ++应用程序代码集成。除Scheme外,Guile还包括ECMAScript和Emacs Lisp的编译器前端(支持Lua正在进行中)...

然而,我自己从未使用过这个库,所以我不能保证将其嵌入到您的应用程序中有多容易。


我甚至没有想到Lisp!有趣的是,另一个回复也提到了Maxima...我们不是很需要计算机代数,而是需要一种完整的语言,但Lisp是一个有趣的选择。我们确实需要一些可以与商业(非操作系统)软件捆绑的东西。不过,还是谢谢你的回复,我会研究一下的! - David
@David,根据LGPL的条款,您可以在商业产品中使用该库!这就是为什么ECL是一个很好的选择。 - ezpresso

4
没有人提到PaxCompiler,它可以将Pascal、Javascript和Basic编译成本地代码,并且可以轻松设置以访问您 Delphi 项目中的对象。它有许多优点:
  1. 编译后的代码比解释执行要快。
  2. 提供了三种不同的编程语言,以便几乎任何开发人员都能够熟悉。
  3. 作为 Delphi 开发人员,您可以访问源代码,并且它与您的项目紧密集成。
  4. 价格非常有吸引力。

对于一个受欢迎的项目来说,它的缺点和挑战包括:

  1. 确保三种语言得到平等的对待:根据我的测试,JavaScript 在捆绑样例方面似乎落后了。
  2. 如果您选择打包这三种编程语言,您可能需要在所有语言中提供几乎所有示例,并且您必须熟悉支持所有三种编程语言。

谢谢,@John!我不确定JavaScript或VBScript是否适合数学/科学编程,所以我很乐意放弃它们,只支持Pascal。你有使用它的经验吗?FAQ让我担心,看起来它缺少一些功能(例如,手动绑定重载虚函数需要很多麻烦操作)。 - David
1
我不确定什么样的语言适合数学/科学编程,以及Pascal在这方面与JS或VB有何不同,但这是你的决定。关于PaxCompiler,我的建议是尝试一下,因为它真的很好用。我曾经和你一样,担心网站/支持问题,但当我通过电子邮件联系他们时,我收到了快速而良好的答复。我目前正在开发一个基于它的应用程序,到目前为止还没有出现任何问题:借助RTTI,使用最新版本的Delphi,您可以让整个对象在脚本中可访问,只需几行代码即可实现。 - jonjbar

3
我建议您了解基于wx(C++)的GUI包装器wxMaxima。它是一个经典的开源数学程序Maxima,在Windows上被称为wxMaxima。它采用GPL许可证,因此派生作品也必须开放源代码。您应该能够使用这个应用程序及其代数引擎,并可能编写自己的Delphi包装器以围绕MACSYMA/MAXIMA(LISP)引擎的C++用户界面。他们的系统源代码中包括一些您可能希望包装并提供为服务的东西:
1. 将数学方程从用户输入的格式编码成显示格式,并对其进行定义和文档化的方法。 2. 您可以使用简单的“语言”规范来组合您的所见即所得方程式工具。
Maxima可以处理绘图、矩阵、线性代数和基本计算,引擎非常稳定。由于您已经在C++中做了很多事情,我建议您考虑使用wxWidgets完成整个应用程序,wxMaxima作为基础。我不确定您是否可以在C++Builder中创建wx + VCL混合应用程序,但您应该尝试一下。如果不能,请使用VC++制作主要应用程序,并为其制作Delphi插件(DLL)。

有趣的回答,谢谢!我以前没有遇到过这种情况。它绘制图形的能力也可能很有用。 (顺便说一下,在wxWidgets中编写整个应用程序可能有利于未来的跨平台兼容性,但是......该应用程序有一个十五年的代码库,数十万行代码,并且非常深入VCL中。也许在我们的下一个版本中考虑吧:p) - David
你确定它有一个“基于C++的引擎”吗?维基百科认为它是用公共Lisp编写的 - David
感谢您的纠正 - 我已更新我的答案,以使其更清晰地表明 wxMAXIMA 意味着 C++ 中的 GUI/UI 层,但底层的 MAXIMA/MACSYMA 引擎是 LISP。我没有注意到 LISP 部分! - Warren P

3

有趣。我认为你关于Mathematica的速度是正确的,但能够生成F#代码真是太酷了! - David
如果你用F#构建一个LISP编译器,然后通过它运行MACSYMA/MAXIMA LISP引擎,最终可以得到一个F#代数/数学引擎。 - Warren P

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