【问题标题】:C# how to create functions that are interpreted at runtimeC#如何创建在运行时解释的函数
【发布时间】:2011-01-28 08:50:40
【问题描述】:

我正在制作一个遗传程序,但我遇到了 C# 的限制,我想向算法提供新功能,但如果不重新编译程序就无法做到。本质上,我希望程序的用户提供允许的功能,GP 会自动使用它们。如果要求用户尽可能少地了解编程,那就太好了。

我想插入新功能而不将它们编译到程序中。在 Python 中这很容易,因为它都是被解释的,但我不知道如何用 C# 来做。有人知道如何在 C# 中实现这一点吗?有没有库、技术等?

【问题讨论】:

  • 这并不能完全回答您的问题,但由于您使用的是 .net,您可以在应用程序的该部分使用 F#,因为它可以在运行时进行解释

标签: c# genetic-algorithm genetic-programming


【解决方案1】:

这取决于您希望程序的用户如何“提供允许的功能”。

  • 如果用户选择您已经实现的函数,您可以将它们作为委托或表达式树传递。
  • 如果用户打算用 C# 或其他 .NET 语言编写自己的方法,并将它们编译成程序集,则可以使用反射加载它们。
  • 如果您希望用户能够在您的程序中键入 C# 源代码,您可以使用 CodeDom 对其进行编译,然后使用 Reflection 调用生成的程序集。
  • 如果您想为用户提供自定义表达式语言,例如一种简单的数学语言,然后(假设您可以解析该语言)您可以使用 Reflection.Emit 生成一个动态程序集并使用 - 你猜对了 - 反射来调用它。或者,您可以从用户代码构建表达式树并使用 LINQ 进行编译——这取决于您需要多大的灵活性。 (如果您等得起,.NET 4.0 中的表达式树消除了 3.5 中的许多限制,因此您可以完全避免 Reflection.Emit。)
  • 如果您对用户使用 Python、Ruby 或其他 DLR 语言输入表达式感到满意,您可以托管动态语言运行时,它将为您解释用户的代码。

在这里托管 DLR(以及 IronPython 或 IronRuby)可能是一个不错的选择,因为您可以获得经过良好测试的环境以及 DLR 提供的所有优化。 Here's a how-to using IronPython.

添加以回答您的性能问题: DLR 在优化方面相当聪明。它不会每次都盲目地重新解释源代码:一旦将源代码(或者,特别是给定的函数或类)转换为 MSIL,它将继续重用该编译表示,直到源代码发生更改(例如函数被重新定义)。因此,如果用户继续使用相同的功能但在不同的数据集上,那么只要您可以保持相同的 ScriptScope,您应该会获得不错的性能;如果您只是担心在遗传算法期间将运行相同的函数无数次,则同上。托管 DLR 非常容易,因此进行概念验证和衡量以查看它是否符合您的需求应该不难。

【讨论】:

  • 我喜欢你提到的反射选项......它们可能是我最好的选择。 DLR 可能是一个不错的选择,调用 DLR 方法时是否存在显着的性能开销?这些方法将被非常频繁地调用,所以我想使用一个开销尽可能少的选项。
  • 我添加了一些关于 DLR 如何通过重复调用代码来提高性能的信息。虽然我没有量化数据,但您可能可以在 Google 上找到一些东西,或者如果没有,托管 DLR 并快速启动它很容易。
  • 是的,我不打算在执行期间修改源代码,它可能会使用相同的方法但具有不同的数据实例,因此 DLR 可能是一个不错的选择。我还将利用记忆,所以如果相同的参数总是产生相同的结果,那么该方法将不会被不必要地执行。谢谢:)。
【解决方案2】:

您可以尝试创建和操作Expression Trees。使用Linq 评估表达式树。

【讨论】:

  • 表达树比纯 eval 函数要好得多。
  • 我的 GP 有多个个体,每个个体都有一个函数和常量树。树中的节点可以是函数或常量...这是否意味着我应该用表达式树替换给定节点处的函数?用户如何插入他们的功能?
  • 请注意,树实际上并不包含函数,而是一个标识函数的枚举。当调用“执行器”时,只需查看枚举并调用相应的函数。
【解决方案3】:

您还可以使用 CodeDom 编译和运行函数。 当然,您可以通过 google 查看一些可能适合您需求的示例。 看来this article "How to dynamically compile C# code"this article "Dynamically executing code in .Net" 可以帮到你。

【讨论】:

    【解决方案4】:

    您可以从代码中访问编译器,然后可以创建已编译代码的实例并使用它们而无需重新启动应用程序。周围有它的例子

    Here

    Here

    第二个是 javascript 评估器,但很容易适应。

    【讨论】:

      【解决方案5】:

      您可以查看 System.Reflection.Emit 以在 IL 级别生成代码。

      或者生成 C#,编译成库并动态加载。几乎没有那么灵活。

      【讨论】:

        【解决方案6】:

        其实生成IL很容易。看这个教程:http://www.meta-alternative.net/calc.pdf

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-12-03
          • 1970-01-01
          • 2014-08-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-07-07
          • 1970-01-01
          相关资源
          最近更新 更多