转换表达式,使所有 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_stepcharfuncharfun2替换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

好的,就是这样。此时您可以验证结果,例如,同时绘制 ee2 并验证它们是否相同,或者评估 e2 - e 的 x 值并验证结果为零或几乎如此(因为浮点运算可以产生非常小的非零结果)。

我做了一些努力来验证实现;参见 rtest_simplify_conditionals.mac。但测试并不详尽。另外,我没有尝试处理其他操作,例如指数或任意函数。尽管如此,我希望这个包在某些方面对你有用。