=================================================================== RCS file: /home/cvs/OpenXM/src/asir-contrib/testing/tr.rr,v retrieving revision 1.1 retrieving revision 1.7 diff -u -p -r1.1 -r1.7 --- OpenXM/src/asir-contrib/testing/tr.rr 2005/04/01 08:08:36 1.1 +++ OpenXM/src/asir-contrib/testing/tr.rr 2005/05/04 05:47:03 1.7 @@ -0,0 +1,844 @@ +/* $OpenXM: OpenXM/src/asir-contrib/testing/tr.rr,v 1.6 2005/04/21 10:54:50 takayama Exp $ */ +/* $Id: tr.rr,v 1.7 2005/05/04 05:47:03 takayama Exp $ */ + +/* + OpenXM版の Risa/Asir で実行のこと. OpenXM 版の関数を用いるため. +*/ +/* + このファイルは quotetolist でリストに変換したデータに対して + パターンマッチおよびそれを応用した変形を行う. + tr.oxt の仕様とことなり quotetolist で変換したものを扱う. + テストプログラムのため効率は無視. (append の多用, 無駄な2重呼び出し, など)) +*/ + + +extern Debug$ +Debug=0$ +extern Debug2$ /* For tr.apply_or_rules. とても便利. */ +Debug2=0$ +def dprint(X) { + if (Debug) print(X); +} +def dprint0(X) { + if (Debug) print(X,0); +} +extern Debug2$ +Debug2=0$ + +/* quotetolist の逆関数. ただし文字列で */ +def listtoquote_str(L) { + return quote_input_form_quote_list(L); +} +/* quotetolist の逆関数. quote を戻す */ +def listtoquote(L) { + return eval_str("quote("+quote_input_form_quote_list(L)+")"); +} + +/* unix の uniq に同じ */ +def uniq(L) { + N = length(L); + if (N > 0) A = [L[0]]; else A=[]; + for (I=1; I nn(f(nn(x),nn(y))) + qt.map_arg(nn,quote(1/4+f(x))) --> + テストは test4(). +*/ +def map_arg(F,Q) { + F = rtostr(F); + if (type(Q) == O_QUOTE) Q=quotetolist(Q); + if (rtostr(Q[0]) == "internal") { + T = listtoquote_str(Q); + return eval_str( "quote("+F+"("+T+"))" ); + } + /* node の子供を F で評価する. */ + N = qt.nchild(Q); + L = []; + for (I=0; I 1/2 へ + この実装は効率は悪い. +*/ +def cancel_number(Q) { + if (type(Q) == O_LIST) Q=listtoquote(Q); + if (qt.is_rational(Q)) { + Ans = eval_quote(Q); + return objtoquote(Ans); + } + A = quote_to_funargs(Q); + N = length(A); R=[]; + for (I=N-1; I>= 0; I--) { + if (type(A[I]) == O_QUOTE) + R = cons(qt.cancel_number(A[I]),R); + else + R = cons(A[I],R); + } + return funargs_to_quote(R); +} + +/* 先頭に - があるか形式的にみる. + -a+b + -3 + -34/y 等. +*/ +def is_minus(Q) { + if (type(Q) == O_LIST) Q=listtoquote(Q); + A = quote_to_funargs(Q); + if (A[0] == I_MINUS) return 1; + if (A[0] == I_BOP) { + if (qt.is_minus(A[2])) return 1; + else return 0; + } + return 0; +} +/* 無条件に ( ) を加える. */ +def add_paren0(Q) { + A = [I_PAREN,Q]; + return funargs_to_quote(A); +} +/* +- 等に ( ) を加える. + 動作が不審なので bug があるかも. +*/ +def add_paren(Q) { + if (type(Q) == O_LIST) Q=listtoquote(Q); + A = quote_to_funargs(Q); + /* この処理は毎度使うのでまとめた方がいいのでは? */ + N = length(A); R=[]; + for (I=N-1; I>= 0; I--) { + if (type(A[I]) == O_QUOTE) + R = cons(qt.add_paren(A[I]),R); + else + R = cons(A[I],R); + } + A = R; + if (A[0] == I_BOP) { + if (get_function_name(A[1]) == "+") { + if (qt.is_minus(A[3])) { /* x+-y ==> x+(-y) */ + A2 = [I_BOP,A[1], + qt.add_paren(A[2]), + qt.add_paren0(A[3])]; + return funargs_to_quote(A2); + } + }else if (get_function_name(A[1]) == "*" || + get_function_name(A[1]) == "/") + { + if (qt.is_minus(A[2])) { /* -x*y ==> (-x)*y */ + A2 = [I_BOP,A[1], + qt.add_paren0(A[2]), + qt.add_paren(A[3])]; + return funargs_to_quote(A2); + } + } + } + return funargs_to_quote(A); +} + +/* vars の真似. + この関数も 変数の出現回数分のリストを作るので効率わるい. + */ +def vars(Q) { + R = [ ]; + if (type(Q) == O_LIST) Q=listtoquote(Q); + A = quote_to_funargs(Q); + if (A[0] == I_FORMULA) { + if (type(A[1]) == O_P) { + R = cons(A[1],R); + } + } + /* この処理は毎度使うのでまとめた方がいいのでは? */ + N = length(A); + for (I=1; I action 関数の中で再帰的に呼べば深さ優先となる. + Todo: 書き換えがおこったかのフラグ. +*/ +def rp(F,P,Q) { + dprint0("tr.rp, F="); dprint(F); + dprint0("tr.rp, P="); dprint(P); + dprint0("tr.rp, Q="); dprint(Q); + if (tr.match0(F,P)) { + BindTable = tr.make_binding(F,P); + dprint0("BindTable="); dprint(BindTable); + return tr.apply_function0(Q,BindTable); + } + if (type(F) != O_LIST) return F; + Node = qt.node(F); + N = qt.nchild(F); + Ans = Node; + for (I=0; I "+RR+" by "); print(listtoquote_str(L));} + if (Debug2) print("-------- end of tr.apply_rule1_flag ------------ "); + return [Flag,eval_str(RR)]; +} + +def apply_or_rules(Q,R) { + Flag = 1; + N = length(R); + while (Flag) { + Flag = 0; + for (I=0; I 0 */ + Rule2=[quote(pn(y)*0), ["qt.zero"]]; /* any*0 --> 0 */ + Rule3=[quote(0/pn(y)), ["qt.zero"]]; /* 0/any --> 0 */ + Rule4=[quote(pn(y)+0), ["qt.id",y]]; /* any+0 --> any */ + Rule5=[quote(0+pn(y)), ["qt.id",y]]; /* 0+any --> any */ + Rule6=[quote(-0), ["qt.zero",y]]; /* -0 --> 0 */ + Rule7=[quote((0)), ["qt.zero",y]]; /* (0) --> 0 */ + Rule8=[quote(1*pn(y)), ["qt.id",y]]; /* 1*any --> any */ + Rule9=[quote(pn(y)*1), ["qt.id",y]]; /* any*1 --> any */ + R=tr.apply_or_rules(R0,[Rule1,Rule2,Rule3,Rule4,Rule5, Rule6,Rule7, + Rule8, Rule9]); + return R; +} + +def simp_unary(R0) { + Rule1=[quote(pn(x))+quote(-pn(y)), ["qt.minus",x,y]]; /* x+-y -> x-y */ + Rule2=[quote(-(-pn(x))), ["qt.id",x]]; /* -(-x) --> x */ + Rule3=[quote(pn(x)-(-pn(y))), ["qt.plus",x,y]]; /* x-(-y) --> x+y */ + R=tr.apply_or_rules(R0,[Rule1,Rule2,Rule3]); + return R; +} + +/* + test_1() はサンプルテスト. +*/ +def simp_sin(R0) { + Rule1=[quote(sin(pn(x)*@pi)),["qt.sin_int",x]]; /* sin(整数*@pi) --> 0 */ + Rule2=[quote(0*pn(y)), ["qt.zero"]]; /* 0*any --> 0 */ + Rule3=[quote(pn(y)*0), ["qt.zero"]]; /* any*0 --> 0 */ + Rule4=[quote(pn(y)+0), ["qt.id",y]]; /* any+0 --> any */ + Rule5=[quote(0+pn(y)), ["qt.id",y]]; /* 0+any --> any */ + Rule6=[quote(sin(0)), ["qt.zero"]]; /* sin(0) --> 0 */ + Rule7=[quote(cos(0)), ["qt.one"]]; /* cos(0) --> 1 */ + /* print(print_input_form(R0)); */ + R=tr.apply_rule1_flag(R0,Rule1[0],Rule1[1]); + /* print([R[0],print_input_form(R[1])]); */ + R=tr.apply_or_rules(R0,[Rule1,Rule2,Rule3,Rule4,Rule5,Rule6,Rule7]); + return R; +} + +endmodule$ +/* ------------ test --------------------------- */ + + + +def test2() { + /* 幅優先探索の場合, R0 は simplify できず. */ + Rule1=[quote(sin(pn("x")*@pi)),["qt.sin_int","x"]]; + R0 = quote(1+sin(sin(2*@pi)*@pi)*sin(@pi/2)); + print(print_input_form(R0)); + R=tr.apply_rule1(R0,Rule1[0],Rule1[1]); + print(print_input_form(R)); + print("-----------------------"); + /* 次のように書くと深さ優先で書ける */ + R0 = quote(1+sin(sin(2*@pi)*@pi)*sin(@pi/2)); + print(print_input_form(R0)); + R=tr.apply_rule1(R0,Rule_test2[0],Rule_test2[1]); + print(print_input_form(R)); +} + + +/* tr.check_pn の動作テスト */ +def test2b() { + Rule=[quote(sin(pn(x,qt.is_integer(x))*@pi)),["qt.zero"]]$ + R0 = quote(1+sin(2*@pi)*sin(a*@pi));; + print(print_input_form(R0)); + R=tr.apply_rule1(R0,Rule[0],Rule[1]); + return R; +} + +/* tr.simp_zero のテスト */ +def test_0() { + F = quote(x+(0*x+0)); + print(quote_input_form(F)); + return tr.simp_zero(F); +} + +/* tr.simp_sin のテスト */ +def test_1() { + F = quote(sin(sin(0))+sin(0)); + print(quote_input_form(F)); + return tr.simp_sin(F); +} + +/* ------------------------------------------------ */ + +/* Index 付き変数を実現する */ +def idxtov(V,I) { + if (type(I) == 5) I=vtol(I); + if (type(I) != O_LIST) I=[I]; + if (type(V) != 2) V=rtostr(V); + return util_v(V,I); +} + +def vtoidx(V) { + A = util_index(V); + if (length(A[1]) == 0) return [A[0]]; + if (length(A[1]) == 1) return [A[0],A[1][0]]; + return A; +} + +/* これら以外のテストプログラムは test1-tr.rr を +*/ + +module qt; +localf dtoq$ +localf qtod$ /* it has not yet been implemented. */ +localf etoq$ + +/* Distributed polynomial to quote + qt.dtoq(dp_ptod((x-y)^3,[x,y]),[]); +*/ +def dtoq(F,V) { + if (F == 0) return quote(0); + N = length(dp_etov(F)); + if (N > length(V)) { + for (I=length(V); I length(V)) { + for (I=length(V); I