转换表达式,使所有 if/then/else 都在顶层
Transform expression so that all if/then/else are on top level
我有一系列简单的方程式,其中有一个输入变量 x 和一些辅助变量,结果应该是一个关于 x 的表达式。这些等式中有 if/then/else。我怎样才能强制最终结果只有 if/then/else 在顶层,而不是在子表达式中?理想情况下,我希望收到一个类似于 if x < step1 then m1 * x + k1 else if x < step2 then m2 * x + k2 else ...
形式的锯齿状线性绘图方程的结果,其中 step、m 和 k 将是数字常量。举个例子,我有
eq1: var1 = if x > 1678 then 400 - 0.18*(x - 642) else 460 - 0.26*(x-730);
eq2: var2 = subst([eq1], if x <= 7520.5 then (x - var1)*0.2 else 7520.5*0.2+(x - 7520.5)*-0.32);
eq3: x - var2;
res: subst([eq1, eq2], eq3);
expand(res);
当前计算为
x-(if x<=7520.5 then 0.2*x-0.2*(if x>1678 then 515.56-0.18*x else 649.8-0.26*x) else 3910.66-0.32*x)
问得好,不幸的是,我没有找到一种简单的方法来做到这一点。这是一些想法的草图;我会尽量在接下来的一两天内回来填写详细信息。
首先,我想到用unit_step
、charfun
或charfun2
替换if/then/else。但是,看起来这些表达式的算术简化(例如 unit_step
的乘积)并未实现,因此使用其中任何一个都不会更简单。但是,如果其他人可以看到如何做,请务必告诉我们。
我认为这样做的大致方法是 (1) 定义 if/then/else 上的算术规则,以及 (2) 定义展平嵌套 if/then/else 的规则。我会使用 defrule
来定义规则,尽管 tellsimpafter
也是一种可能。
编辑:我整理了一些代码来处理上面的 (1) 和 (2)。请参阅 robert-dodier/simplify_conditionals 处:https://github.com/maxima-project-on-github/maxima-packages
这是我针对您提到的问题得到的结果。
(%i2) load ("simplify_conditionals.mac");
(%o2) simplify_conditionals.mac
首先给e
你显示的表达式赋值。
(%i3) e: x-(if x<=7520.5 then 0.2*x-0.2*(if x>1678 then 515.56-0.18*x else 649.8-0.26*x) else 3910.66-0.32*x);
(%o3) x - (if x <= 7520.5 then 0.2 x
- 0.2 (if x > 1678 then 515.56 - 0.18 x else 649.8 - 0.26 x)
else 3910.66 - 0.32 x)
进行+
和*
运算。 (-
和 /
也包括在内,因为它们是根据 Maxima 中的 +
和 *
定义的。)
(%i4) arithmetic_with_conditionals (e);
(%o4) if x <= 7520.5 then (if x > 1678
then 0.8 x + 0.2 (515.56 - 0.18 x)
else 0.8 x + 0.2 (649.8 - 0.26 x)) else 1.32 x - 3910.66
调用 expand
将 *
分配给 +
(这不包括条件内容)。
(%i5) e1: expand (%);
(%o5) if x <= 7520.5 then (if x > 1678 then 0.764 x + 103.112
else 0.748 x + 129.96) else 1.32 x - 3910.66
展平嵌套条件。
(%i6) e2: flatten_conditionals (e1);
(%o6) if (x <= 7520.5) and (x > 1678) then 0.764 x + 103.112
elseif x <= 7520.5 then 0.748 x + 129.96 else 1.32 x - 3910.66
好的,就是这样。此时您可以验证结果,例如,同时绘制 e
和 e2
并验证它们是否相同,或者评估 e2 - e
的 x 值并验证结果为零或几乎如此(因为浮点运算可以产生非常小的非零结果)。
我做了一些努力来验证实现;参见 rtest_simplify_conditionals.mac
。但测试并不详尽。另外,我没有尝试处理其他操作,例如指数或任意函数。尽管如此,我希望这个包在某些方面对你有用。
我有一系列简单的方程式,其中有一个输入变量 x 和一些辅助变量,结果应该是一个关于 x 的表达式。这些等式中有 if/then/else。我怎样才能强制最终结果只有 if/then/else 在顶层,而不是在子表达式中?理想情况下,我希望收到一个类似于 if x < step1 then m1 * x + k1 else if x < step2 then m2 * x + k2 else ...
形式的锯齿状线性绘图方程的结果,其中 step、m 和 k 将是数字常量。举个例子,我有
eq1: var1 = if x > 1678 then 400 - 0.18*(x - 642) else 460 - 0.26*(x-730);
eq2: var2 = subst([eq1], if x <= 7520.5 then (x - var1)*0.2 else 7520.5*0.2+(x - 7520.5)*-0.32);
eq3: x - var2;
res: subst([eq1, eq2], eq3);
expand(res);
当前计算为
x-(if x<=7520.5 then 0.2*x-0.2*(if x>1678 then 515.56-0.18*x else 649.8-0.26*x) else 3910.66-0.32*x)
问得好,不幸的是,我没有找到一种简单的方法来做到这一点。这是一些想法的草图;我会尽量在接下来的一两天内回来填写详细信息。
首先,我想到用unit_step
、charfun
或charfun2
替换if/then/else。但是,看起来这些表达式的算术简化(例如 unit_step
的乘积)并未实现,因此使用其中任何一个都不会更简单。但是,如果其他人可以看到如何做,请务必告诉我们。
我认为这样做的大致方法是 (1) 定义 if/then/else 上的算术规则,以及 (2) 定义展平嵌套 if/then/else 的规则。我会使用 defrule
来定义规则,尽管 tellsimpafter
也是一种可能。
编辑:我整理了一些代码来处理上面的 (1) 和 (2)。请参阅 robert-dodier/simplify_conditionals 处:https://github.com/maxima-project-on-github/maxima-packages
这是我针对您提到的问题得到的结果。
(%i2) load ("simplify_conditionals.mac");
(%o2) simplify_conditionals.mac
首先给e
你显示的表达式赋值。
(%i3) e: x-(if x<=7520.5 then 0.2*x-0.2*(if x>1678 then 515.56-0.18*x else 649.8-0.26*x) else 3910.66-0.32*x);
(%o3) x - (if x <= 7520.5 then 0.2 x
- 0.2 (if x > 1678 then 515.56 - 0.18 x else 649.8 - 0.26 x)
else 3910.66 - 0.32 x)
进行+
和*
运算。 (-
和 /
也包括在内,因为它们是根据 Maxima 中的 +
和 *
定义的。)
(%i4) arithmetic_with_conditionals (e);
(%o4) if x <= 7520.5 then (if x > 1678
then 0.8 x + 0.2 (515.56 - 0.18 x)
else 0.8 x + 0.2 (649.8 - 0.26 x)) else 1.32 x - 3910.66
调用 expand
将 *
分配给 +
(这不包括条件内容)。
(%i5) e1: expand (%);
(%o5) if x <= 7520.5 then (if x > 1678 then 0.764 x + 103.112
else 0.748 x + 129.96) else 1.32 x - 3910.66
展平嵌套条件。
(%i6) e2: flatten_conditionals (e1);
(%o6) if (x <= 7520.5) and (x > 1678) then 0.764 x + 103.112
elseif x <= 7520.5 then 0.748 x + 129.96 else 1.32 x - 3910.66
好的,就是这样。此时您可以验证结果,例如,同时绘制 e
和 e2
并验证它们是否相同,或者评估 e2 - e
的 x 值并验证结果为零或几乎如此(因为浮点运算可以产生非常小的非零结果)。
我做了一些努力来验证实现;参见 rtest_simplify_conditionals.mac
。但测试并不详尽。另外,我没有尝试处理其他操作,例如指数或任意函数。尽管如此,我希望这个包在某些方面对你有用。