我的问题:符号表达操作。
符号表达式是在整数常量和变量的基础上,在+, - ,*,/,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库,请告诉我。
答案 0 :(得分:4)
如果您退出Min
和Max
,普通表单很容易:它们是变量分数字段的元素,我的意思是P[Vars]/Q[Vars]
其中P
,Q
是多项式。对于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)
解决此类问题的常用方法是:
"a + 1 > a"
[Variable('a'); Plus; Number(1); GreaterThan; Variable('a')]
Max( Add( Var('a'), Const(1)), Var('a'))
创建一个可以解释语法树以获取最终结果的函数
let eval_expr expr = match expr with
| Number n -> n
| Add a b -> (eval_expr a) + (eval_expr b)
...
原谅语法,我暂时没有使用过Ocaml。
关于图书馆,我不记得任何超出我的想法,但肯定有很好的可用 - 这是FP社区喜欢做的任务。