fourier_elim を懐柔する(その2)
前回の qfq では,例えば
(%i1) f:abs(x-a)=abs(x-b)+c; (%o1) abs(x - a) = abs(x - b) + c (%i2) qfq(f); (%o2) ((0 < c) %and (a = b - c) %and (x = b)) %or ((0 < c) %and (b = a - c) %and (x = a - c)) %or ((a = b) %and (c = 0) %and (x = b)) %or ((a = b - c) %and (max(b, b - c) < x)) %or ((a = b - c) %and (c < 0) %and (x = b - c)) %or ((a = c + b) %and (c < 0) %and (x = c + b)) %or ((a = c + b) %and (x < min(b, c + b))) %or ((a = 2 x - c - b) %and (x < min(b, c + b))) %or ((a = 2 x + c - b) %and (max(b, b - c) < x))
のように出力に max,min が入る場合があります.
原因は
(%i3) listofvars(f); (%o3) [a, x, c, b]
として変数を抽出している点,つまり,上の例の場合,fourier_elim が先ず a について解き,次に x について解き,…と進んでしまう点にあります.
そこで,変数の順序を指定できるように
qfq(f):=block([g], if op(f)="%and" then (g:args(f),f2q(fourier_elim(g, (if listp(fev) and length(fev)>0 then fev else listofvars(g)) ))) else f2q(fourier_elim(f, (if listp(fev) and length(fev)>0 then fev else listofvars(f)) )))$
と改め,例えば
(%i4) fev:[c,b,a]; (%o4) [c, b, a]
とすれば
(%i5) qfq(f); (%o5) ((a = x) %and (b = x) %and (c = 0)) %or ((a = x) %and (b = x - c) %and (c < 0)) %or ((a = x) %and (b = x + c) %and (c < 0)) %or ((a < x) %and (b = x) %and (c = x - a)) %or ((a < x) %and (b < x) %and (c = b - a)) %or ((a < x) %and (c = 2 x - b - a) %and (x < b)) %or ((b = x) %and (c = a - x) %and (x < a)) %or ((b < x) %and (c = (- 2 x) + b + a) %and (x < a)) %or ((c = a - b) %and (x < a) %and (x < b))
となり,これなら
(%i6) g:fqe([[E,x]],f);fqe([],(g) %eq (abs(c)<=abs(a-b))); (%o6) ((c - b + a >= 0) %and (c + b - a <= 0)) %or ((c - b + a <= 0) %and (c + b - a >= 0)) (%o7) true
と処理できます.