=================================================================== RCS file: /home/cvs/OpenXM/src/asir-contrib/testing/tr.rr,v retrieving revision 1.6 retrieving revision 1.7 diff -u -p -r1.6 -r1.7 --- OpenXM/src/asir-contrib/testing/tr.rr 2005/04/21 10:54:50 1.6 +++ OpenXM/src/asir-contrib/testing/tr.rr 2005/05/04 05:47:03 1.7 @@ -1,111 +1,520 @@ -/* $OpenXM: OpenXM/src/asir-contrib/testing/tr.rr,v 1.5 2005/04/15 12:47:14 takayama Exp $ */ -/* $Id: tr.rr,v 1.6 2005/04/21 10:54:50 takayama Exp $ */ +/* $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 版の関数を用いるため. */ -/* $Id: tr.rr,v 1.6 2005/04/21 10:54:50 takayama Exp $ +/* このファイルは 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)+")"); +} -def qt_node(F) { - if (type(F) == 17) F=quotetolist(F); +/* 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 tr_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); +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); + return tr.apply_function0(Q,BindTable); } - if (type(F) != 4) return F; - Node = qt_node(F); - N = qt_nchild(F); + 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 qt_id(X) { - if (type(X) == 17) return quotetolist(X); - else return X; +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 --------------------------- */ -extern Rule_test2$ -/* " " と付けてもつけなくてもよい. 内部で rtostr してる. */ -/* Rule_test2=[quote(sin(pn("x")*@pi)),["qt_sin_int2","x"]]$ */ -Rule_test2=[quote(sin(pn(x)*@pi)),[qt_sin_int2,x]]$ + def test2() { /* 幅優先探索の場合, R0 は simplify できず. */ - Rule1=[quote(sin(pn("x")*@pi)),["qt_sin_int","x"]]; + 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]); + 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]); + R=tr.apply_rule1(R0,Rule_test2[0],Rule_test2[1]); print(print_input_form(R)); } -/* 右規則関数. sin(整数*@pi) を 0 に */ -def qt_sin_int(X) { - /* いま X は quote 型 */ - Y = quotetolist(X); - /* Todo: このようなものを作る機能は組み込みで欲しい. */ - R = "quote(sin("+listtoquote_str(Y)+"*@pi))"; - print(R); - R = eval_str(R); - /* Todo: X が 数字かどうか調べる機能も組み込みで欲しい. - */ - if (Y[0] == "internal") { - Z = eval_str(rtostr(Y[1])); - }else{ - return quotetolist(R); - } - if (type(Z) == 0) return quotetolist(quote(0)); - if ((type(Z) == 1) && (ntype(Z) == 0)) return quotetolist(quote(0)); - return quotetolist(R); -} -/* 右規則関数. sin(整数*@pi) を 0 に. 深さ優先用 */ -def qt_sin_int2(X) { - /* tr_apply_rule1 を再帰的によぶ. この方法で構文解析もかける. */ - X = tr_apply_rule1(X,Rule_test2[0],Rule_test2[1]); - Y = quotetolist(X); - R = "quote(sin("+listtoquote_str(Y)+"*@pi))"; - print(R); - R = eval_str(R); - if (qt_is_integer(Y)) return quotetolist(quote(0)); - else return quotetolist(R); -} - -/* --------------- end test -----------------------*/ -def qt_replace(F,Rule) { - return base_replace(F,Rule); -} - -/* F の中に不定元 X が含まれているか? - qt_is_dependent(quotetolist(quote(1+1/x)),x) -*/ -def qt_is_dependent(F,X) { - if (type(F) == 17) F = quotetolist(F); - Node = qt_node(F); - if ((F[0] == "internal") && (rtostr(F[1]) == rtostr(X))) { - return 1; - }else{ - N = qt_nchild(F); - for (I=0; I nn(f(nn(x),nn(y))) - qt_map_arg(nn,quote(1/4+f(x))) --> - テストは test4(). -*/ -def qt_map_arg(F,Q) { - F = rtostr(F); - if (type(Q) == 17) 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