符号计算

时间:2011-04-21 13:34:11

标签: algorithm ocaml symbolic-math

我的问题:符号表达操作。

符号表达式是在整数常量和变量的基础上,在+, - ,*,/,min,max等运算符的帮助下构建的。更确切地说,我将用以下方式表示一个表达式(Caml代码):

type sym_expr_t = 
  | PlusInf
  | MinusInf
  | Const of int
  | Var of var_t
  | Add of sym_expr_t * sym_expr_t
  | Sub of sym_expr_t * sym_expr_t
  | Mul of sym_expr_t * sym_expr_t
  | Div of sym_expr_t * sym_expr_t
  | Min of sym_expr_t * sym_expr_t
  | Max of sym_expr_t * sym_expr_t

我想,为了执行有用和有效的计算(例如a + b - a = 0或a + 1> a),我需要有某种正常形式并对其进行操作。上述表示可能不会太好。

有人能指出我应该如何处理这个问题吗?我不需要代码。如果我知道如何,这可以很容易地写出来。与提供正常形式和/或算法进行构造/简化/比较的论文的链接也会有所帮助。

此外,如果您知道Ocaml库,请告诉我。

2 个答案:

答案 0 :(得分:4)

如果您退出MinMax,普通表单很容易:它们是变量分数字段的元素,我的意思是P[Vars]/Q[Vars]其中PQ是多项式。对于Min和Max,我不知道;我想最简单的方法是将它们视为if / then / else测试,并使它们浮动到表达式的顶部(复制过程中的内容),例如P(Max(Q,R))将被重写为P(if Q>R then Q else R) },然后在if Q>R then P(Q) else P(R)

我知道有两种不同的方法可以找到表达式expr的正常形式:

  • 定义与您的直觉相对应的重写规则expr -> expr,并表明它们正在规范化。这可以通过指导你知道的方程式来完成:从Add(a,Add(b,c)) = Add(Add(a,b),c)你可以得到Add(a,Add(b,c)) -> Add(Add(a,b),c)或者相反。但是你有一个方程式系统,你需要显示Church-Rosser和规范化;确实很脏。

  • 采用更加语义的方法来给出值的“语义”:expr中的元素实际上是生成类型sem的数学对象的符号。找到sem的对象的合适(唯一)表示,然后是评估函数expr -> sem,然后最后(如果您愿意,但您不需要进行相等性检查)一个具体化{ {1}}。两个转换的组合自然会给你一个归一化程序,而不必担心例如Add重写的方向(一些任意选择将自然地从你的具体化函数中产生)。例如,对于多项式分数,语义空间将类似于:

sem -> expr

当然,这并不总是那么容易。我看不清楚用Min和Max函数为语义空间提供什么样的表示。

编辑:关于外部库,我不知道,我不确定是否有。您应该寻找与其他符号代数软件的绑定,但我还没有听说过它(几年前有一个简街夏季项目,但我不确定是否有任何可交付的产品)。 /> 如果您需要生产应用程序,也许您应该直接考虑自己编写绑定,例如。到Sage或Maxima。我不知道会是什么样的。

答案 1 :(得分:3)

解决此类问题的常用方法是:

  1. 以字符串开头,例如"a + 1 > a"
  2. 浏览词法分析器,并将输入分成不同的标记:[Variable('a'); Plus; Number(1); GreaterThan; Variable('a')]
  3. 将令牌解析为语法树(您现在拥有的)。您可以在此处使用运算符优先级规则:Max( Add( Var('a'), Const(1)), Var('a'))
  4. 创建一个可以解释语法树以获取最终结果的函数

    let eval_expr expr = match expr with
        | Number n -> n
        | Add a b -> (eval_expr a) + (eval_expr b)
        ...
    

  5. 原谅语法,我暂时没有使用过Ocaml。

    关于图书馆,我不记得任何超出我的想法,但肯定有很好的可用 - 这是FP社区喜欢做的任务。