Re: regex with boolean operations over character classes built_in on DCG
Kuniaki Mukai <[email protected]> Sat, 2 Aug 2014 01:50:56 +0900
| Newsgroups | gmane.comp.ai.prolog.swi |
|---|---|
| Message-ID | <[email protected]> |
On Aug 1, 2014, at 10:51 PM, Michael Hendricks <[email protected]> wrote: > On Fri, Aug 1, 2014 at 3:34 AM, Kuniaki Mukai <[email protected]> wrote: > >> I have completely rewritten my old codes for regex in SWI-Prolog DCG, so >> that >> now it is working stable on SWI-Prolog develop version. >> >> Features are: >> 1. Character classes >> 2. Boolean operations >> 3. States are minimized as taught in automata theory. >> 4. Built_in on DCG. >> 5. Hybrid syntax of unix-like regex and prolog terms. >> 6. regex expressions are term-expanded on being read. >> 7. No runtime library needed except generated predicates as state labels. >> > > This is intriguing. Is the source code available somewhere for us to see? Thank you for your interest. I have no idea on how to make the source code available, though I wish to do so if there is any handy way. What I can do for your request for now is to copy and paste a main source codes file "expand-word.pl" for term-expansion to expand the regex. The codes is dirty, lengthy and not clean, but I hope you can find something what the codes is doing to cover the features announced. :- module(word,[]). :- include(pac('pac-only')). :- include(pac(op)). % ?- phrase(w(char(alnum) + *(char(alpha))), [a, '1', b,c], S). %@ S = ['1', b, c] ; % ?- phrase(w(ab+cd), [a, b, c, d, e], S). % ?- phrase(w("abcd"), [a, b, c, d, e], S). %@ S = [e]. % ?- word:let_word(X, regex("a*" % ?- word:let_word(X, "a*"). % ?- word:let_word(X, "a*"), phrase(w(X), [a,a,b,c], R). % ?- word:let_word(X, abc), phrase(w(X), [a,b,c,d,e], R). % NOT meta_predicate ! % ?- word:let_word(X, ".*"), phrase(w(X), [a,b,c], R). let_word(F, X):- once(let_word(coa_dcg, F, X, Y)), maplist(assert, Y). % ?- word:let_word_d(X, ".*"), phrase(w(X, A), [a,b,c], R). let_word_d(F, X):- once(let_word(coa_dcg_d, F, X, Y)), maplist(assert, Y). % NOT meta_predicate ! let_word(T, F, X, Y):- nb_getval(module_name_for_aux, M), regex_coalgebra(X, Coa), translate_coa(T, Coa, M, F, Y, []). % ?- trace, word:regex_coalgebra(*(a|b)+ [a]+(*([]))+ (*(*([]|[]))), N). % ?- word:regex_coalgebra(".*", X). %@ X = coa([1-[[], dot([inf-sup])-1]], 1, [1]). % ?- word:regex_coalgebra(*(.), X). %@ X = coa([1-[[], dot([inf-sup])-1]], 1, [1]). % ?- word:regex_coalgebra(ab+cd, X). % ?- word:regex_coalgebra_code(ab+cd, X). % ?- word:regex_coalgebra_char(ab+cd, X). % regex_coalgebra_code(X, coa(E0, I, Fs)):- once(regex_am(X, coa(E, I))), am_finals(coa(E, _), Fs), am_convert_interval_code(E, E0). % regex_coalgebra_char(X, coa(E0, I, Fs)):- once(regex_am(X, coa(E, I))), am_finals(coa(E, _), Fs), am_convert_interval_char(E, E0). % regex_coalgebra(X, C):- regex_coalgebra_char(X, C). % ?- phrase(w(char(alnum) + *(char(alpha))), [a, '1', b,c], S). %@ S = ['1', b, c] ; %@ S = ['1', b, c] ; % ?- phrase(w(ab+cd), [a, b, c, d, e], S). % ?- phrase(w("abcd"), [a, b, c, d, e], S). %@ S = [e]. % ?- word:let_word(X, "a*"). % ?- word:let_word(X, "a*"), phrase(w(X), [a,a,b,c], R). % ?- word:let_word(X, abc), phrase(w(X), [a,b,c,d,e], R). % ?- trace, word:expand_w("[a]", user, G, P, []). % ?- trace, word:expand_w("[^a]", user, G, P, []). % am_convert_interval_char(X, Y):- am_convert_interval(X, Y, interval_char_code). % am_convert_interval_code(X, Y):- am_convert_interval(X, Y, =). :- meta_predicate am_convert_interval(?,?,2). am_convert_interval([], [], _). am_convert_interval([I-A|R], [I-B|S], F):- am_convert_interval_aux(A, B, F), am_convert_interval(R, S, F). am_convert_interval_aux([], [], _). am_convert_interval_aux([[]|Q], [[]|R], F) :- am_convert_interval_aux(Q, R, F). am_convert_interval_aux([U-S|Q], [dot(V)-S|R], F) :- maplist(F, U, V), am_convert_interval_aux(Q, R, F). % am_convert_interval(X, Y):- % maplist([I-A, I-B]:- % maplist(pred( [[], []] % & ([U-S, dot(V)-S] :- % maplist(interval_char_code, % U, V))), % A, B), % X, Y). % wrap_char_dot(X, Y):- % maplist([I-A, I-B]:- % maplist(pred( [[], []] % & ([U-S, dot(V)-S] )) % A, B), % X, Y). interval_char_code(inf-sup, inf-sup). interval_char_code(inf-X, inf-Y):- char_code(Y, X). interval_char_code(X-sup, Y-sup):- char_code(Y, X). interval_char_code(X-X0, Y-Y0):- char_code(Y, X), char_code(Y0, X0). % ?- coa:regex_min_coa("a" & "b", R). %@ R = coa([1-[[]]], 1) . % regex_min_coa(R, C):- once(word_am(R, coa(E0, I))), % distribute_am_goto(E0, E1), % am_minimum(coa(E1, I), C). % distribute_am_goto(X, Y):- refine_am_goto(X, X0), split_goto(X0, Y). % ?- iboole:m_partition([[1-5], [3-6], [1-5]],R). % ?- iboole:m_partition([[3-6], [1-5]], R). %@ R = [[3-5, 6-6], [1-2, 3-5]] . % ?- coa:refine_am_goto([a-[[1-5]-b, [3-6]-c], d-[[inf-sup]-3]], X). %@ X = [a-[[1-2, 3-5]-b, [3-5, 6-6]-c], d-[[inf-0, 1-2, 3-5, 6-6, 7-sup]-3]] . refine_am_goto(E, E0):- am_char_table(E, E0, [], P), refine_char_table(P). % refine_char_table(Tzip):- zip_hyphen(Left, Right, Tzip), iboole:m_partition(Left, Right). % ?- coa:am_char_table([2-[[inf-sup]-3]], C, [], P). %@ C = [2-[_G2137-3]], %@ P = [[inf-sup]-_G2137]. am_char_table([], [], P, P). am_char_table([[]|Z], [[]|Z0], P, Q):- am_char_table(Z, Z0, P, Q). am_char_table([X-Y|Z], [X-Y0|Z0], P, Q):- goto_table(Y, Y0, P, R), am_char_table(Z, Z0, R, Q). % goto_table([], [], P, P). goto_table([[]|X],[[]|Y], P, Q):- goto_table(X, Y, P, Q). goto_table([I-S|X],[V-S|Y], P, Q):- add_char_table(I, P, P0, V), goto_table(X, Y, P0, Q). % % add_char_table([X],P, Q, V):- !, add_char_table(char([X-X]), P, Q, V). add_char_table(I, P, P, V):- memberchk(I-V, P), !. add_char_table(I, P, [I-V|P], V). % expand_char_class(U, V):- maplist(([X-Y, X-Y0]:- maplist(pred( [[], []] & ([V-S, Gotos] :- maplist(S^([A, A-S]), V, Gotos))), Y, Y0)), U, V). % ?- coa:split_goto([1-[[], [1,2,3]-s, [2,3]-t], 1-[[1,2,3]-s, [2,3]-t]], X). %@ X = [1-[[], 1-s, 2-s, 3-s, 2-t, 3-t], 1-[1-s, 2-s, 3-s, 2-t, 3-t]] . split_goto(X, Y):- maplist([I-S, I-S0]:- distribute_state(S, S0), X, Y). % distribute_state([], []). distribute_state([[]|X], [[]|X0]):- distribute_state(X, X0). distribute_state([X-S|Y], Z):- distribute_state(Y, Y0), maplist(pred(S, [C, C-S]), X, XS), append(XS, Y0, Z). % ?- coa:word_am("a", X). % ?- coa:word_am(".*", X). %@ X = coa([1-[[], [46-46]-1]], 1) . %@ X = coa([1-[[], [46-46]-1]], 1) . :-bekind(word_am, []). % (.) = char([inf-sup]). char(X) = :am_char@ ((iboole:i_boole) @ (coa:char_boole_form(X))). '$INTLIST'(X) = :am_char_simple(X). [] = char([]). [X|Y] = :am_codes([X|Y]). X+Y = :am_concat@X@Y. (X|Y) = :am_cup@X@Y. (X\Y) = :am_minus@X@Y. &(X, Y) = :am_cap@X@Y. +(X) = ( X + (*(X))). *(X) = :am_star@X. \+(X) = ( *(.) \ X ). ?(X) = ( [] | X ). E^N = :am_repeat(N)@E. (E<N) = :am_repeat_upto(N)@E. E = @(:parse_regex(E)) :- string(E). E = @(:atom_codes(E)) :- atom(E). E = @(:number_codes(E)) :- number(E). :- ekind. % merge([X,X|Y], U):-!, merge([X|Y], U). merge([X|R], [X|U]):- merge(R, U). merge([], []). % regex_am(X, Y):- regex_word(X, X0, Basic_interval_table), word_am(X0, Y0), am_connected_region(Y0, Y0_reachable), am_remove_empty_states(Y0_reachable, Y0_slim), am_remove_useless_states(Y0_slim, Y0_useful), am_char_back(Y0_useful, Basic_interval_table, Y1), am_normal(Y1, Y). regex_word(X, Y, Basic_interval_table):- parse_interval(X, Y, P, []), sort(P, SortedP), merge(SortedP, P0), zip_hyphen(Is, Js, P0), zip_hyphen(Is, Ks, Q0), refine_char_table(Q0), basic_interval_index(Ks, Js, Basic_interval_table). am_char_back(coa(X, I), M, coa(Y, I)):- maplist(pred(M, [I-A, I-B]:- maplist(pred(M, ([[], []] & ([C-J, D-J] :- memberchk(D-C, M)))), A, B)), X, Y). basic_interval_index(Ks, Js, Basic_interval_table):- maplist([B, C, D]:- zip_hyphen(B, C, D), Ks, Js, U), flatten(U, V), sort(V, Basic_interval_table0), merge(Basic_interval_table0, Basic_interval_table), length(Basic_interval_table, N), ( N==0 -> true ; numlist(1, N, NZip), zip_hyphen(_, NZip, Basic_interval_table) ). % ?- coa:regex_am((.), R). %@ R = coa([1-[inf-sup-2], 2-[[]]], 1) . parse_interval((.), '$INTLIST'(U), [[inf-sup]-U|P], P). parse_interval(char(X), '$INTLIST'(U) , [I-U|P], P) :- char_boole_form(X, X0), iboole:i_boole(X0, I). parse_interval(out(X), U, P, Q):- parse_interval(char(out(X)), U, P, Q). parse_interval(dot(X), U, P, Q):- parse_interval(char(X), U, P, Q). parse_interval(X+Y, U+V, P, Q):- parse_interval(X, U, P, P0), parse_interval(Y, V, P0, Q). parse_interval(X|Y, U|V, P, Q):- parse_interval(X, U, P, P0), parse_interval(Y, V, P0, Q). parse_interval(X\Y, U\V, P, Q):- parse_interval(X, U, P, P0), parse_interval(Y, V, P0, Q). parse_interval(X&Y, U&V, P, Q):- parse_interval(X, U, P, P0), parse_interval(Y, V, P0, Q). parse_interval(+(X), +(U), P, Q):- parse_interval(X, U, P, Q). parse_interval(*(X), *(U), P, Q):- parse_interval(X, U, P, Q). parse_interval(\+(X), U, P, Q) :- parse_interval( *(.) \ X, U, P, Q). parse_interval(flip(X), U, P, Q):- parse_interval(\+X, U, P, Q). parse_interval(?(X), ?(U), P, Q):- parse_interval(X, U, P, Q). parse_interval(E^N, E0^N, P, Q):- parse_interval(E, E0, P, Q). parse_interval(E<N, E0<N, P, Q):- parse_interval(E, E0, P, Q). parse_interval(X, U, P, Q):- string(X), !, parse_regex(X, X0), parse_interval(X0, U, P, Q). parse_interval(X, U, P, Q):- atom(X), !, atom_codes(X, X0), parse_interval(X0, U, P, Q). parse_interval(X, U, P, Q):- number(X), !, number_codes(X, X0), parse_interval(X0, U, P, Q). parse_interval(X, U, P, Q):- is_list(X), parse_interval_codes(X, U, P, Q). % parse_interval_codes([], [], P, P). parse_interval_codes([X], '$INTLIST'(U), [[X-X]- U|P], P). parse_interval_codes([X, Y|Z], '$INTLIST'(U) + R, [[X-X]- U|P], Q):- parse_interval_codes([Y|Z], R, P, Q). % Note. % ?- val(:(=) @ (:(=) @ (:(=) @ 1)), V). %@ V = 1 . % ?- trace, coa:am_codes([a,b], X). %@ Call: (8) coa:am_codes([a, b], _G820) ? no debug %@ X = coa([1-[[a-a]-2], 2-[[b-b]-3], 3-[[]]], 1) . am_codes([X|Y], Coa):- am_char([X-X], Coa0), ( Y == [] -> Coa = Coa0 ; am_codes(Y, Coa1), am_concat(Coa0, Coa1, Coa) ). % %% Boolean operations on sets of intergers represented % as a list of characters % and intervals of characters, e.g, [a, c-k, u, x-z]. % ?- coa:char_boole_form(., X). % ?- coa:char_boole_form((a-c)&(b-d), X). % ?- coa:char_boole_form(abc, X). % ?- char_code(a, R). %@ R = 97. char_boole_form((.), [inf-sup]):- !. char_boole_form([], []):- !. char_boole_form(X-Y, [A0-A1]):- !, (atom(X), atom_length(X, 1); integer(X)), (atom(Y), atom_length(Y, 1); integer(Y)), ( atom(X)-> char_code(X, X0); X0=X ), ( atom(Y)-> char_code(Y, Y0); Y0=Y ), msort([X0,Y0], [A0,A1]). char_boole_form(X, Y):- atom(X), !, i_type_assoc(Assoc), memberchk(X-C, Assoc), % maplist(pred([A-B, A-B]& [A, A-A]), C, C0), maplist(pred(([A-B, A0-B0]:- char_code(A, A0), char_code(B, B0)) & ([A, A0] :- char_code(A, A0))), C, C0), char_boole_form(C0, Y). char_boole_form(X, [X-X]):- integer(X), !. char_boole_form([X|Y], X0;Y0):- char_boole_form(X, X0), char_boole_form(Y, Y0). char_boole_form(dot(X), Y):- char_boole_form(X, Y). char_boole_form(out(X), out(Y)):- char_boole_form(X, Y). char_boole_form(^(X), Y):- char_boole_form(out(X), Y). char_boole_form(\+(X), Y):- char_boole_form(out(X), Y). char_boole_form(X|Y, X0|Y0):- char_boole_form(X, X0), char_boole_form(Y, Y0). char_boole_form(X;Y, Z):- char_boole_form(X|Y, Z). char_boole_form(X&Y, X0&Y0):- char_boole_form(X, X0), char_boole_form(Y, Y0). %%% Tiny helpers zip_hyphen([], [], []). zip_hyphen([A|B], [C|D], [A-C|R]):- zip_hyphen(B, D, R). % zip_comma([], [], []). zip_comma([A|B], [C|D], [(A,C)|R]):- zip_comma(B, D, R). % translate_coa(F, coa(C, I, _), M, M:Name, P, Q):- all_states(C, Nts), maplist([J, J-N]:- gensym('nt#', N), Nts, Assoc), call(F, C, M, P0, [], Assoc), memberchk(I-Name, Assoc), maplist(dcg_translate_rule_expand_dot, P0, P1), append(P1, Q, P). % dcg_translate_rule_expand_dot(P, H:-G0):- dcg_translate_rule(P, H:-G), pac:expand_goal(G, [], G0, _, []). % am_dcg([], _, P, P, _). am_dcg([I-D|E], M, P, Q, Assoc):- am_dcg(I, M, D, P, R, Assoc), am_dcg(E, M, R, Q, Assoc). am_dcg(_, _, [], P, P, _). am_dcg(I, M, [[]|R], [M:PI-->[]|P], Q, Assoc):- memberchk(I-PI, Assoc), am_dcg(I, M, R, P, Q, Assoc). am_dcg(I, M, [A-J|R], [M:PI-->(A0, M:PJ)|P], Q, Assoc):- memberchk(I-PI, Assoc), memberchk(J-PJ, Assoc), ( A == (.), A0=[_]; A0 = A ), !, am_dcg(I, M, R, P, Q, Assoc). % d means d-list version of am_dcg am_dcg_d([], _, P, P, _). am_dcg_d([I-D|E], M, P, Q, Assoc):- am_dcg_d(I, M, D, P, R, Assoc), am_dcg_d(E, M, R, Q, Assoc). am_dcg_d(_, _, [], P, P, _). am_dcg_d(I, M, [[]|R], [M:PI-->[]|P], Q, Assoc):- memberchk(I-PI0, Assoc), PI=..[PI0, X, X], am_dcg_d(I, M, R, P, Q, Assoc). am_dcg_d(I, M, [A-J|R], [M:PI-->(A0, M:PJ)|P], Q, Assoc):- memberchk(I-PI0, Assoc), memberchk(J-PJ0, Assoc), PI=..[PI0, U, V], dcg_d(A, U, W, A0), PJ=..[PJ0, W, V], am_dcg_d(I, M, R, P, Q, Assoc). % dcg_d((.), [A|B], B, [A]). dcg_d([A], [A|B], B, [A]). dcg_d({G}, A, A, {G}). dcg_d(X, A, B, X0):- pac:complete_args(X, [A, B], X0). % ?- coa:am_determine([1-[a-1]], 1, D, R). %@ D = [[1]-[a-[1]]], %@ R = [1]. % ?- coa:am_determine([1-[a-1, a-2], 2-[[]]], 1, D, R). %@ D = [[1]-[a-[1, 2]], [1, 2]-[[], a-[1, 2]]], %@ R = [1] % ?- coa:am_determine(coa([1-[a-1, a-2], 2-[[]]], 1), D). %@ D = coa([1-[a-2], 2-[[], a-2]], 1) . am_determine(coa(E, I), D):- am_determine(E, I, E0, I0), am_fresh(coa(E0, I0), D0), am_clean(D0, D). am_determine(E, I, D, [I]):- am_determine([[I]], [], E, D, []). am_determine([], _, _, P, P). am_determine([S|R], H, E, P, Q):- memberchk(S, H), !, am_determine(R, H, E, P, Q). am_determine([S|R], H, E, [S-C|P], Q):- expand_power_state(S, E, C, R0, R), am_determine(R0, [S|H], E, P, Q). % am_slim(coa(E, I), coa(D, I)):- am_slim([I], [], E, D, []). am_slim([], _, _, P, P). am_slim([S|R], H, E, P, Q):- memberchk(S, H), !, am_slim(R, H, E, P, Q). am_slim([I|A], H, E, [I-U|P], Q):- once(select(I-U, E, E0)), am_slim(U, A, [I|H], E0, P, Q). % am_slim([], A, H, E, P, Q):- !, am_slim(A, H, E, P, Q). am_slim([[]|R], A, H, E, P, Q):- !, am_slim(R, A, H, E, P, Q). am_slim([_-G|R], A, H, E, P, Q):- !, am_slim(R, [G|A], H, E, P, Q). % % ?- coa:expand_power_state([x,y], [x-[a-2, b-3], y-[a-2, b-4, c-5]], R, A, []). %@ R = [a-[2], b-[3, 4], c-[5]], %@ A = [[2], [3, 4], [5]] . expand_power_state(S, E, Coa, P, Q):- foldl(pred(E, ([K, L, M] :- memberchk(K-B, E), foldl(pred([X, U, [X|U]]), B, L, M))), S, [], Pairs0), sort(Pairs0, Pairs), merge_pairs(Pairs, Coa, [], P, Q). % ?-coa:is_deterministic(coa([1-[a-1, b-1]], _)). %@ true. % ?-coa:is_deterministic(coa([1-[a-1, a-1]], _)). %@ false. is_deterministic(coa(E, _)):- is_deterministic(E). % is_deterministic([]). is_deterministic([_-A|_]):- consecutive_same_key(A), !, fail. is_deterministic([_|R]):- is_deterministic(R). % consecutive_same_key([A-_, A-_|_]):-!. consecutive_same_key([_, A|B]):- consecutive_same_key([A|B]). %%% automata state minimization % ?- word:regex_coalgebra(".*****", X). %@ X = coa([1-[[], dot([inf-sup])-1]], 1, [1]). % ?- word:am_minimum([2-[[], (inf-sup)-3], 3-[[], (inf-sup)-3]], 2, R). %@ R = coa([1-[[], dot([inf-sup])-1]], 1, [1]) . % ?- coa:am_minimum([1-[[inf-sup]-1]], Q). %@ Q = [[1]-1] . % ?- coa:am_minimum([1-[(a-b)-1, (b-c)-2], 2-[[]]], Q). % ?-trace, E= [1-[(inf-sup)-1]], word:ya_am_minimum(E, Q), word:ya_quotient_coa(E, Q, E0), word:am_normal(E0, E1). % ?-trace, E= [2-[(inf-sup)-3], 3-[[]]], word:ya_am_minimum(E, Q), word:ya_quotient_coa(E, Q, E0), word:am_normal(E0, E1). %@ Call: (8) _G1418=[2-[inf-sup-3], 3-[[]]] ? no debug %@ E = [2-[inf-sup-3], 3-[[]]], %@ Q = [[2]-1, [3]-2], %@ E0 = E1, E1 = [1-[inf-sup-2], 2-[[]]] ; % ?- coa:am_minimum(coa([1-[a-2, b-1], 2-[a-1, b-2], 3-[a-3, b-1]], 1), D). %@ D = coa([1-[[a, b]-1]], 1) . am_minimum(coa(E,I), C):- am_minimum(E, I, C). am_minimum(E, I, coa(E3, J)):- minimum_am_qmap(E, Qmap), ( Qmap == [] -> E3 = E, J = I ; member(X-I0, Qmap), memberchk(I, X), quotient_coa(E, Qmap, E1), am_clean(coa(E1, I0), coa(E2, J)), sort(E2, E3) ). %@@@ minimum_am_qmap(Coa, Qmap):- am_conflict_pairs(Coa, Conflicts), sort(Conflicts, CSorted), pairs_to_assoc(CSorted, Inicon, []), all_states(Coa, All), assoc_product(All, All, Prod, []), assoc_subtract(Prod, Inicon, Rel), maplist([I, [I]], All, Singletons), union_find(Rel, Singletons, Clusters), ( Clusters == [] -> Qmap = [] ; length(Clusters, N), numlist(1, N, S), zip_hyphen(Clusters, S, Qmap) ). % quotient_coa(Eqs, Qmap, Eqs0) :- maplist(Qmap^[S-L, S0-L0]:- ( member(Cluster-S0, Qmap), memberchk(S, Cluster), maplist(pred(Qmap, [[],[]] & ([A-G, A-G0]:- (member(GCluster-G0, Qmap), memberchk(G, GCluster))) ), L, L1 ), predsort(compare_right, L1, L0) ), Eqs, Eqs0). % am_normal(coa([], _), C):- !, am_empty(C). am_normal(coa(A,I), coa(B, I)):- sort(A, C), am_normal(C, B, []). % am_normal([], P, P). am_normal([I-A|R], [I-B|P], Q):- am_normal(I, R, R0, As, []), append([A|As], H), sort(H, G), am_normal_body(G, B), am_normal(R0, P, Q). am_normal_body([], []). am_normal_body([[]|G], [[]|B]) :- !, am_normal_body(G, B). am_normal_body(G, B) :- keysort_right(G, G0), join_char(G0, B0), maplist([I-X, J-X] :- iboole:i_normal(I, J), B0, B). % am_normal(I, [I-A|R], R0, [A|P], Q):- !, am_normal(I, R, R0, P, Q). am_normal(_, R, R, P, P). % compare_right(=, [], []). compare_right(<, [], _). compare_right(>, _, []). compare_right(C, X-Y, Z-Y):- !, compare(C, X, Z). compare_right(C, _-X, _-Y):- compare(C, X, Y). % ?- coa:merge_pairs([a-2, a-3, a-2, b-1, b-3, c-2], R, [], S, []). %@ R = [a-[2, 3], b-[1, 3], c-[2]], %@ S = [[2, 3], [1, 3], [2]]. merge_pairs([], D, D, A, A). merge_pairs([[]|Cs], [[]|D0], D, A0, A):- !, merge_pairs(Cs, D0, D, A0, A). merge_pairs([I-X|Cs], [I-Pow|D0], D, [Pow|A0], A):- power_state(I, Cs, Cs0, Pow0, []), sort([X|Pow0], Pow), merge_pairs(Cs0, D0, D, A0, A). % power_state(I, [I-G|R], R0, [G|P], Q):- !, power_state(I, R, R0, P, Q). power_state(_, A, A, B, B). % ?- coa:join_char_interval([], []). % ?- trace, coa:join_char_interval([(3-4)-t], R). %@ R = [[3-4]-t] . % ?- trace, coa:join_char_interval([(inf-4)-t, (5-sup)-t], R). %@ R = [[inf-sup]-t] . % ?-coa:join_char_interval([(10-sup)-t, (20-20)-s, (inf-4)-t], R). %@ R = [[20-20]-s, [10-sup, inf-4]-t]. keysort_right(X,Y):- predsort(pred( [=, [], []] & [<, [], _] & [>, _, []] & ([C, _-U, _-V] :-U @> V, C=(>); C=(<))), X, Y). join_char_interval(A, B):- keysort_right(A, A0), join_char(A0, B). % join_char([], []). join_char([[]|R], [[]|S]):- join_char(R, S). join_char([X-A|R], [[X|Xs]-A|S]):- join_char(A, R, Xs, R0), join_char(R0, S). % join_char(_, [], [], []):- !. join_char(A, [X-A|R], [X|Xs], S):- !, join_char(A, R, Xs, S). join_char(_, R, [], R). % ?- coa:merge_target([a-1], R, []). %@ R = [a-[1]]. % ?- coa:merge_target([a-1, a-2], R, []). %@ R = [a-[1, 2]] . % ?- coa:merge_target([a-1, a-2, b-3], R, []). %@ R = [a-[1, 2], b-[3]] . % ?- coa:merge_target([[], a-1, a-2, b-3], R, []). %@ R = [[], a-[1, 2], b-[3]] . % ?- coa:merge_target([[], a-1, b-3, a-2], R). %@ R = [[], a-[1, 2], b-[3]] . merge_target(X, Y):- sort(X, X0), merge_target(X0, Y, []). merge_target([], P, P). merge_target([[]|R], [[]|P], Q):- merge_target(R, P, Q). merge_target([I-X|R], [I-Xs|P], Q):- merge_target(I, R, R0, [X], Xs), merge_target(R0, P, Q). % merge_target(I, [I-X|R], R0, P, Q):- contract_insert(X, P, P0), merge_target(I, R, R0, P0, Q). merge_target(_, R, R, P, P). % ?- union_find([a-b,x-y, x-x, y-z, b-c], [], R). % ?- union_find([a-b,x-y, x-x, y-z, b-c], [], R). union_find([], X, X). union_find([X-Ys|R],C,D):-union_find(Ys, X, C,C1), union_find(R,C1,D). union_find([], _, P, P). union_find([Y|Ys], X, P, Q):- union_find_one(X, Y, P, P0), union_find(Ys, X, P0, Q). union_find_one(X,Y,Z,U):-find_cluster(X,Z,C,Z0), (memberchk(Y, C) -> U=[C|Z0] ; find_cluster(Y, Z0, C0, Z1), append(C,C0, C1), U=[C1|Z1] ). % ?- coa:find_cluster(a, [[a,b],[c,d]], C, X). find_cluster(X,[],[X],[]):-!. find_cluster(X,[Y|Z],Y,Z):- memberchk(X,Y),!. find_cluster(X,[Y|Z],U,[Y|V]):- find_cluster(X,Z,U,V). % Reversing coalgebra % ?- coa:am_reverse([a-[b-c], d-[b-c], e-[b-c], x-[y-z]], R). %@ R = [c-[b-[a, d, e]], z-[y-[x]]] . % ?- coa:am_reverse([a-[b-c], d-[b-c], e-[m-c], x-[y-z]], R). %@ R = [c-[b-[a, d], m-[e]], z-[y-[x]]] . % ?- coa:am_reverse([a-[[], b-c, d-e, e-c], x-[y-z]], R). %@ R = [c-[b-[a], e-[a]], e-[d-[a]], z-[y-[x]]] . % ?- coa:am_reverse([a-[d-e, e-c], x-[y-z]], R). %@ R = [c-[e-[a]], e-[d-[a]], z-[y-[x]]] . % ?- coa:am_reverse([1-[a-1]], R). %@ R = [1-[a-[1]]] . % ?- coa:am_reverse([], X). %@ X = []. am_reverse(X, Y):- maplist(pred([I-As, B]:- foldr(pred(I, ( [ C-J, [(J-(C-I))|W], W] & [ [] , W, W] ) ), As, B, []) ), X, X0 ), append(X0, X1), triples_to_coa(X1, Y). %?- coa:triples_to_coa([1-(a-4), 3-(c-3), 2-(b-1), 1-(a-2)], R). %@ R = [1-[a-[2, 4]], 2-[b-[1]], 3-[c-[3]]]. triples_to_coa(X, Y):-sort(X, X0), pairs_to_assoc(X0, Assoc, []), maplist(pred([I-U, I-V]:- pairs_to_assoc(U, V, [])), Assoc, Y). % am_to_reversed_dag(E, D):- am_to_reversed_dag(E, [], Ps), sort(Ps, Ps0), pairs_to_assoc(Ps0, D, []). am_to_reversed_dag([], X, X). am_to_reversed_dag([I-A|R], X, Y):- am_to_reversed_dag(A, I, X, X0), am_to_reversed_dag(R, X0, Y). am_to_reversed_dag([], _, X, X). am_to_reversed_dag([[]|R], I, X, Y):- am_to_reversed_dag(R, I, X, Y). am_to_reversed_dag([_-G|R], I, X, Y):- am_to_reversed_dag(R, I, [G-I|X], Y). % ?- trace, coa:fiber_product_basic([a-[b,c]], [a-[1,2]], [], P). %%@ P = [2-c, 1-c, 2-c, 1-c, 2-b, 1-b] . % ?- coa:am_conflict_pairs([a-[[],1-a], b-[1-b]], S). %@ S = [a-b] . % ?- coa:am_conflict_pairs([a-[[],1-a], b-[1-b], c-[[],1-a]], S). %@ S = [b-c, a-b] . % ?- trace, coa:am_conflict_pairs([a-[1-a], b-[1-b]], S). % ?- trace, coa:am_conflict_pairs([a-[[]], b-[[]]], S). % am_conflict_pairs(Coa, S):- % am_arity_dict(Coa, Dict), % arity_conflict_pairs(Dict, IniCon, []), % sort(IniCon, IniCon0), % pairs_to_assoc(IniCon0, IniCon1, []), % am_reverse(Coa, RCoa), % propagate_conflict(IniCon1, RCoa, [], S). am_conflict_pairs(Coa, S):- am_arity_dict(Coa, Dict), arity_conflict_pairs(Dict, IniCon, []), sort(IniCon, IniCon0), % pairs_to_assoc(IniCon0, IniCon1, []), am_reverse(Coa, RCoa), propagate_conflict(IniCon0, RCoa, [], S). % by agenda programming propagate_conflict([], _, P, P). propagate_conflict([U|R], Coa, P, Q):- memberchk(U, P), !, propagate_conflict(R, Coa, P, Q). propagate_conflict([I-J|R], Coa, P, Q):- memberchk(I-A, Coa), memberchk(J-B, Coa), !, fiber_product(A, B, F), append(F, R, R0), propagate_conflict(R0, Coa, [I-J|P], Q). propagate_conflict([U|R], Coa, P, Q):- propagate_conflict(R, Coa, [U|P], Q). % ?- coa:fiber_product([a-[7,8,9], b-[1,2,3]], [a-[6,7,8], b-[1,2,3]], P). %@ P = [1-2, 1-3, 2-3, 6-7, 6-8, 6-9, 7-8, 7-9, 8-9] . fiber_product(A, B, P):- fiber_product(A, B, [], P0), sort(P0, P). fiber_product([], _, P, P). fiber_product([X|Y], N, P, Q):- fiber_product_one(X, N, P, R), fiber_product(Y, N, R, Q). fiber_product_one([], _, P, P). fiber_product_one(_, [], P, P). fiber_product_one(X, [Y|Z], P, Q):- fiber_product_one_one(X, Y, P, R), fiber_product_one(X, Z, R, Q). fiber_product_one_one(_, [], P, P). fiber_product_one_one(A-G, A-H, P, Q):- !, s_product(G, H, P, Q). fiber_product_one_one(_, _, P, P). % ?- coa:pairs_to_assoc([1-2, 1-3, 2-3, 2-4], X, []). %@ X = [1-[2, 3], 2-[3, 4]]. pairs_to_assoc([], X, X). pairs_to_assoc([I-A|R], [I-As|V], V0):- pairs_to_assoc(I, R, R0, [A], As), pairs_to_assoc(R0, V, V0). % pairs_to_assoc(I, [I-A|R], R0, S, T):-!, contract_insert(A, S, S0), pairs_to_assoc(I, R, R0, S0, T). pairs_to_assoc(_, R, R, S, S). % ?- coa:assoc_to_pairs([1-[2,3], 2-[3,4]], R, []). %@ R = [1-2, 1-3, 2-3, 2-4]. assoc_to_pairs([], P, P). assoc_to_pairs([I-Vs|A], P, Q):- assoc_to_pairs(I, Vs, P, P0), assoc_to_pairs(A, P0, Q). assoc_to_pairs(_, [], P, P):- !. assoc_to_pairs(I, [X|Xs], [I-X|P], Q):- assoc_to_pairs(I, Xs, P, Q). % ?- coa:contract_merge([1,3,6], [2, 5, 7], R). %@ R = [1, 2, 3, 5, 6, 7]. % Remark. % ?- union([1,3,6], [2, 5, 7], R). %@ R = [1, 3, 6, 2, 5, 7]. % ?- union([1,3,6], [2, 3, 5, 7], R). %@ R = [1, 6, 2, 3, 5, 7]. contract_merge([], X, X):-!. contract_merge(X, [], X):-!. contract_merge([X|R], [X|S], [X|T]):- !, contract_merge(R, S, T). contract_merge([X|R], [Y|S], [X|T]):- X@<Y, !, contract_merge(R, [Y|S], T). contract_merge([X|R], [Y|S], [Y|T]):- contract_merge([X|R], S, T). % ?- coa:contract_insert(3, [2, 5, 7], R). %@ R = [2, 3, 5, 7]. contract_insert(X, [], [X]):-!. contract_insert(X, [X|S], [X|S]):- !. contract_insert(X, [Y|S], [X, Y|S]):- X@<Y, !. contract_insert(X, [Y|S], [Y|R]):- contract_insert(X, S, R). % ?- coa:final_states([1-[[],a-b], 2-[c-d]], R). %@ R = [1]. all_states(X, S):- maplist([A-_, A], X, S0), sort(S0, S). % arity(X, Y):- maplist(pred([[], []] & [A-_, A]), X, Y0), sort(Y0, Y). am_arity_dict(Coa, Dict):- maplist([I-X, I-M]:- arity(X, M), Coa, Dict). % ?- coa:arity_conflict_pairs([1-a, 2-b, 3-a, 4-b], A, []). %@ A = [1-2, 1-4, 2-3, 3-4] . arity_conflict_pairs([], A, A). arity_conflict_pairs([I-A|As], P, Q):- arity_conflict_pairs(I, A, As, P, P0), arity_conflict_pairs(As, P0, Q). % arity_conflict_pairs(_, _, [], P, P). arity_conflict_pairs(I, A, [J-B|Bs], [I-J|P], Q):- A\==B, !, arity_conflict_pairs(I, A, Bs, P, Q). arity_conflict_pairs(I, A, [_|Bs], P, Q):- arity_conflict_pairs(I, A, Bs, P, Q). % ?-coa:s_product([1,2,3],[1,2,3], P). %@ P = [1-2, 1-3, 2-3] . s_product(X, Y, P):- s_product(X, Y, [], Q), sort(Q, P). s_product([], _, P, P). s_product([X|Xs], Y, P, Q):- s_product(X, Xs, Y, P, R), s_product(Xs, Y, R, Q). s_product(X, Xs, Y, P, Q):- foldl(pred(X, ([A, L, L]:- A==X, !) & ([A, L, [W|L]]:- s_pair(X, A, W))), Y, P, R), s_product(Xs, Y, R, Q). % ?- trace, coa:assoc_product([1,2,3], [1,2,3], R, []). %@ R = [1-[2, 3], 2-[3]] . assoc_product([], _, P, P). assoc_product(_, [], P, P). assoc_product([X|Xs], [Y|Ys], [X-[Y|Ys]|P], Q):- Y@>X, !, assoc_product(Xs, [Y|Ys], P, Q). assoc_product(Xs, [_|Ys], P, Q):-assoc_product(Xs, Ys, P, Q). % subtraction on assoc lists. % ?- coa:assoc_subtract([1-[2,3,4], 2-[3,4], 3-[4,5,6]], [1-[3], 2-[4], 5-[6,7,8]], R). %@ R = [1-[2, 4], 2-[3], 3-[4, 5, 6]] . assoc_subtract([], _, []). assoc_subtract(A, [], A). assoc_subtract([I-A|Ps], [I-B|Qs], R):- !, ord_subtract(A, B, C), ( C == [] -> R = Rs ; R = [I-C|Rs] ), assoc_subtract(Ps, Qs, Rs). assoc_subtract([I-A|Ps], [J-B|Qs], [I-A|Rs]):- I@<J, !, assoc_subtract(Ps,[J-B|Qs], Rs). assoc_subtract([I-A|Ps], [_|Qs], [I-A|Rs]):- assoc_subtract(Ps, Qs, Rs). % ?-coa:assoc_complement([1,2,3], [1-[2], 2-[3]], R). %@ R = [1-[3]] . %@ R = [1-[3]] . assoc_complement(A, C, D):- assoc_product(A, A, AConf, []), assoc_subtract(AConf, C, D). % s_pair(A, B, A-B):- A @< B, !. s_pair(A, B, B-A). % expand_dot_list([A], X, P):-!, expand_dot(A, X, P). expand_dot_list([A, B], X, P):- expand_dot_adhoc(A, B, X, P), !. expand_dot_list([I|Is], X, P; Ps):- expand_dot(I, X, P), expand_dot_list(Is, X, Ps). % Ad hoc code optimization. Shoud be revised. !! % expand_dot_adhoc(inf-A, B-sup, X, X\==C):- integer(A), integer(B), !, % B is A + 2, % C is A + 1. expand_dot_adhoc(inf-A, B-sup, X, X\==C):- B is A + 2, !, C is A + 1. % expand_dot(A, X, X==A ):- atomic(A). expand_dot(A-A, X, P ):- expand_dot(A, X, P). expand_dot(inf-sup, _, true ). expand_dot(inf-A, X, X @=< A ). expand_dot(A-sup, X, A @=< X ). expand_dot(A-B, X, (A @=< X, X @=< B) ). % am_char([], coa([1-[[]]], 1)):-!. am_char(Is, coa([1-[[]|G], 2-[[]]], 1)):- maplist([I, I-2], Is, G). am_char_simple([], coa([1-[[]]], 1)):-!. am_char_simple(Is, coa([1 - G, 2-[[]]], 1)):- maplist([I, I-2], Is, G). % digraph traversal by Agenda Programming. % am_cap(coa(E0, I0), coa(E1, I1), Coa):- am_cap([I0*I1], [], E0, E1, [], E2), am_fresh(coa(E2, I0*I1), Coa0), am_minimum(Coa0, Coa). % am_cap([], _, _, _, P, P). am_cap([U|R], H, A, B, P0, P):- memberchk(U, H), !, am_cap(R, H, A, B, P0, P). am_cap([I*J|R], H, A, B, P0, P):- memberchk(I-GI, A), memberchk(J-GJ, B), product_cap(GI, GJ, R0, R, Q, []), am_cap(R0, [I*J|H], A, B, [I*J-Q|P0], P). % product_cap([], _, R, R, Q, Q). product_cap(_, [], R, R, Q, Q). product_cap([[]|G], [[]|H], R0, R, [[]|Q0], Q):-!, product_cap(G, H, R0, R, Q0, Q). product_cap([[]|G], H, R0, R, Q0, Q):-!, product_cap(G, H, R0, R, Q0, Q). product_cap(G, [[]|H], R0, R, Q0, Q):-!, product_cap(G, H, R0, R, Q0, Q). product_cap([U-I|G], [U-J|H], [I*J|R0], R, [U-I*J|Q0], Q):-!, product_cap(G, H, R0, R, Q0, Q). product_cap([U-_|G], [V-I|H], R0, R, Q0, Q):- U@<V, !, product_cap(G, [V-I|H], R0, R, Q0, Q). product_cap([U-I|G], [_|H], R0, R, Q0, Q):- product_cap([U-I|G], H, R0, R, Q0, Q). % am_minus(coa(E0,I0), coa(E1, I1), Coa):- am_minus([I0*I1], [], E0, E1, [], E2), append(E0, E2, E3), am_determine(coa(E3, I0*I1), NCoa), am_minimum(NCoa, Coa). % am_minus([], _, _, _, P, P). am_minus([U|R], H, A, B, P0, P):- memberchk(U, H), !, am_minus(R, H, A, B, P0, P). am_minus([I*J|R], H, A, B, P0, P):- memberchk(I-GI, A), memberchk(J-GJ, B), product_minus(GI, GJ, R0, R, Q, []), am_minus(R0, [I*J|H], A, B, [I*J-Q|P0], P). % product_minus([], _, R, R, Q, Q). product_minus([W|G], [], R0, R, [W|P], Q):- product_minus(G, [], R0, R, P, Q). product_minus([[]|G], [[]|H], R0, R, Q0, Q):-!, product_minus(G, H, R0, R, Q0, Q). product_minus([[]|G], H, R0, R, [[]|Q0], Q):-!, product_minus(G, H, R0, R, Q0, Q). product_minus(G, [[]|H], R0, R, Q0, Q):-!, product_minus(G, H, R0, R, Q0, Q). product_minus([U-I|G], [U-J|H], [I*J|R0], R, [U-I*J|Q0], Q):-!, product_minus(G, H, R0, R, Q0, Q). product_minus([U-I|G], [V-I|H], R0, R, [U-I|Q0], Q):- U@<V, !, product_minus(G, [V-I|H], R0, R, Q0, Q). product_minus([U-I|G], [_|H], R0, R, Q0, Q):- product_minus([U-I|G], H, R0, R, Q0, Q). % am_cup(coa(A,I), Coa0, Coa):- length(A, N), am_shift(N, Coa0, coa(C, K)), append(A, C, D), am_determine([[I,K]], [], D, E, []), am_fresh(coa(E, [I,K]), Coa1), am_minimum(Coa1, Coa). % ?- trace, coa:am_concat(coa([1-[[], a-2], 2-[[]]],1), coa([1-[a-2], 2-[[]]],1), R). %@ R = coa([1-[a-4, a-2], 2-[a-4], 3-[a-4], 4-[[]]], 1) . % ?- coa:am_concat(coa([1-[[], a-1]],1), coa([1-[[], b-1]],1), R). %@ R = coa([1-[[], b-2, a-1], 2-[[], b-2]], 1) . am_concat(coa(E0, I0), Coa1, Coa):- length(E0, N), am_shift(N, Coa1, coa(E3, I3)), memberchk(I3-G, E3), maplist(am_replace_null(G), E0, E1), append(E1, E3, E4), am_slim(coa(E4,I0), E5), am_determine(E5, E), am_minimum(E, Coa). % am_repeat(0, _, coa([1-[[]]], 1)):-!. am_repeat(N, E, Coa):- am_repeat(N, E, E, Coa). % am_repeat(1, _, C, C). am_repeat(N, E, C, C0):- N>1, am_concat(E, C, C1), N0 is N-1, am_repeat(N0, E, C1, C0). % am_unit(coa([1-[[]]], 1)). % am_empty(coa([], 0)). % am_repeat_upto(1, _, U):- am_unit(U). am_repeat_upto(N, E, Coa):- N>1, am_unit(U), N0 is N-1, am_repeat_upto(N0, E, U, Coa). % am_repeat_upto(0, _, C, C). am_repeat_upto(N, E, C, C0):- N>0, am_concat(C, E, C1), am_unit(U), am_cup(C1, U, C2), N0 is N-1, am_repeat_upto(N0, E, C2, C0). % ?- coa:am_shift(3, coa([1-[a-2, b-3]],1), R). %@ R = coa([4-[a-5, b-6]], 4). am_shift(N, coa(E,I), coa(E0, I0)):- I0 is I+N, maplist(state_id_shift(N), E, E0). % state_id_shift(N, I-A, J-B):- J is I + N, maplist(goto_id_shift(N), A, B). % goto_id_shift(_, [],[]). goto_id_shift(N, A-I, A-J):- J is I+N. % ?- coa:am_replace_null([a-2], 2-[[]], X). am_replace_null(A, I-[[]|B], I-C):- !, ord_union(A, B, C). am_replace_null(_, P, P). % ?- coa:am_minimum(coa([1-[a-2, a-3, b-3], 2-[b-3], 3-[a-1]], 1), R). % ?- coa:am_plus(coa([1-[a-2], 2-[[]]], 1), R). % ?- coa:am_star(coa([1-[a-2], 2-[[]]], 1), R). % ?- coa:am_star(coa([1-[a-2, b-3], 3-[[]], 2-[[]]], 1), R). % ?- coa:am_star(coa([1-[a-2, a-3, b-3], 3-[[]], 2-[[]]], 1), R). % ?- coa:am_star(coa([1-[a-2], 2-[[]]], 1), R). %@ R = coa([1-[[], a-1]], 1) . % ?- coa:am_star(coa([1-[a-2, b-2], 2-[[]]], 1), R). %@ R = coa([1-[[], a-1, b-1]], 1) . % ?- coa:am_plus(coa([1-[a-2, b-2], 2-[[]]], 1), R). %@ R = coa([1-[a-2, b-2], 2-[[], a-2, b-2]], 1) . % ?- coa:am_copy(coa([1-[a-2], 2-[[]]], 1), D). am_kleene(coa(E, I), Coa):- once(select(I-R, E, E0)), drop_null(R, NR), maplist(am_replace_null([[]|NR]), E0, E1), am_determine(coa([I-R|E1], I), Coa). % am_star(C, D):- am_kleene(C, coa(E0, I)), once(select(I-R0, E0, E)), ( R0=[[]|_] -> R = R0 ; R = [[]|R0] ), am_minimum(coa([I-R|E], I), D). % am_plus(X, Y):- am_kleene(X, Z), am_minimum(Z, Y). % am_fresh(coa([], _), C):- !, am_empty(C). am_fresh(coa(E, I), coa(E0, I0)):- length(E, L), numlist(1, L, Ns), zip_hyphen(M, _, E), zip_hyphen(M, Ns, S), subst_coa(E, S, E0), memberchk(I-I0, S). am_fresh(Coa0, coa(E0, _), Coa):- length(E0, N), am_shift(N, Coa0, Coa). am_fresh(Coa0, coa(E0, _), Coa):- length(E0, N), am_shift(N, Coa0, Coa). % am_size(coa(E, _), N):- length(E, N). am_initial_state(coa(_, I), I). am_equations(coa(E, _), E). % ?- coa:am_finals(coa([1-[[]], 2-[a-3], 3-[[]]], 1), R). %@ R = [1, 3] . am_finals(coa(E, _), A):- foldl(pred( [I-[[]|_], [I|U], U] & [_, U, U] ), E, A, []). % ?- coa:am_states(coa([1-[[]], 2-[a-3], 3-[[]]], 1), R). %@ R = [1, 2, 3]. am_states(coa(E, _), A):- maplist([I-_, I], E, A). am_copy(C, D):- C = coa(E0, _), length(E0, N), am_shift(N, C, D). % am_clean(coa(E, I), coa(D, I)):- maplist([I-A, I-B]:- sort(A, B), E, E0), sort(E0, D). % drop_null([[]|A], A):- !. drop_null(A, A). % add_one(X, Y, Z):- ( memberchk(X, Y) -> Z=Y ; Z = [X|Y]). % ?-coa:subst_coa([1-[b-2]], [1-9, 2-10], X). %@ X = [9-[b-10]]. % ?-coa:subst_coa([1-[[], b-2]], [1-9, 2-10], X). %@ X = [9-[[], b-10]]. % ?- coa:am_remove_useless_states(coa([1-[[], a-1, a-2], 2-[b-3], 3-[c-3]], 1), R). %@ R = coa([1-[[], a-1]], 1) . am_remove_useless_states(coa(E, I), coa(E0, I)):- am_live_dead(coa(E,I), _, Dead), am_remove_states(E, Dead, E0). am_live_dead(Coa, Live, Dead):- am_finals(Coa, Fs), am_equations(Coa, E), am_to_reversed_dag(E, Assoc), dg_path_find(Fs, Assoc, [], Live, Dead). % ?- coa:dg_path_find([], [1-[2], 2-[1]], [], X, Y). %@ X = [], %@ Y = [1, 2]. % ?- coa:dg_path_find([1], [1-[2], 2-[1], 3-[1,2]], [], X, Y). %@ X = [2, 1], %@ Y = [3]. dg_path_find([], E, Live, Live, Dead):- !, maplist([I-_, I], E, Dead). dg_path_find([X|R], E, Z, Live, Dead):- memberchk(X, Z), !, dg_path_find(R, E, Z, Live, Dead). dg_path_find([X|R], E, Z, Live, Dead):- select(X-G, E, E0), !, union(G, R, R0), dg_path_find(R0, E0, [X|Z], Live, Dead). dg_path_find([X|R], E, Z, Live, Dead):- dg_path_find(R, E, [X|Z], Live, Dead). % ?- trace, coa:am_connected_region(coa([1-[[]]], 1), C). %@ C = coa([1-[[]]], 1) . % ?- trace, coa:am_connected_region(coa([1-[[], a-2], 2-[[]], 3-[a-3]], 1), C). %@ C = coa([1-[[], a-2], 2-[[]]], 1) . % ?- trace, coa:am_connected_region(coa([1-[[], a-2], 2-[[]], 3-[a-3]], 1), C). am_connected_region(coa(E, I), coa(E0, I)):- am_path_find([I], [], E, E0, []). % am_path_find([],_H, _E, R, R). am_path_find(_, _H, [], R, R). am_path_find([X|R], H, STS, E0, E1):- memberchk(X, H), !, am_path_find(R, [X|H], STS, E0, E1). am_path_find([X|R], H, STS, [X-G|E0], E1) :- select(X-G, STS, STS0), !, am_path_find_next(G, R0, R), am_path_find(R0, [X|H], STS0, E0, E1). am_path_find([X|R], H, STS, [X|E0], E1) :- am_path_find(R, [X|H], STS, E0, E1). % am_path_find_next([], X, X). am_path_find_next([[]|R], X, Y):- am_path_find_next(R, X, Y). am_path_find_next([_-G|R], [G|X], Y):- am_path_find_next(R, X, Y). % naive method. % ?- coa:am_remove_empty_states(coa([], 1), C). %@ C = coa([], 1). %@ C = coa([], 1). % ?- trace, coa:am_remove_empty_states(coa([1-[[],a-2], 2-[]], 1), C). %@ C = coa([1-[[]]], 1) . % ?- trace, coa:am_remove_empty_states(coa([1-[[],a-2, a-3], 3-[b-2], 2-[]], 1), %@ C = coa([1-[[]]], 1) . am_remove_empty_states(coa(E, I), coa(E0,I)):- am_elim_empty_states(E, E0). % am_elim_empty_states(E, E0):- am_elim_empty_states(E, S, [], E1, []), ( S == [] -> E0 = E1 ; am_elim_link(S, E1, E2), am_elim_empty_states(E2, E0) ). % am_elim_empty_states([], X, X, Y, Y). am_elim_empty_states([I-[]|R], [I|X], X0, Y, Y0):- !, am_elim_empty_states(R, X, X0, Y, Y0). am_elim_empty_states([U|R], X, X0, [U|Y], Y0):- am_elim_empty_states(R, X, X0, Y, Y0). % am_elim_link([], E, E). am_elim_link(Is, E, E0):- am_elim_link(Is, E, E0, []). % am_elim_link(_, [], E, E). am_elim_link(Is, [I-A|R], [I-B|E], F):- elim_link_step(Is, A, B, []), !, am_elim_link(Is, R, E, F). % elim_link_step(_, [], X, X). elim_link_step(Is, [[]|R], [[]|X], Y):- !, elim_link_step(Is, R, X, Y). elim_link_step(Is, [_-S|R], X, Y):- memberchk(S, Is), !, elim_link_step(Is, R, X, Y). elim_link_step(Is, [I-S|R], [I-S|X], Y):- elim_link_step(Is, R, X, Y). % ?- coa:am_remove_states([1-[a-2,b-2]], [1,2], R). %@ R = []. % ?- coa:am_remove_states([1-[[],a-2,b-2], 2-[b-1]], [1], R). %@ R = [2-[]]. am_remove_states([], _, []). am_remove_states([I-_|R], Ds, E):- memberchk(I, Ds), !, am_remove_states(R, Ds, E). am_remove_states([I-A|R], Ds, [I-B|E]):- am_remove_goto(A, Ds, B), am_remove_states(R, Ds, E). % am_remove_goto([], _, []). am_remove_goto([[]|R], Ds, [[]|S]):- am_remove_goto(R, Ds, S). am_remove_goto([_-G|R], Ds, S):- memberchk(G, Ds), !, am_remove_goto(R, Ds, S). am_remove_goto([U|R], Ds, [U|S]):- am_remove_goto(R, Ds, S). % subst_coa([], _, []). subst_coa([I-G|R], S, [I0-G0|R0]):- memberchk(I-I0, S), subst_am_goto(G, S, G0), subst_coa(R, S, R0). subst_am_goto([], _, []). subst_am_goto([[]|R], S, [[]| R0]):- !, subst_am_goto(R, S, R0). subst_am_goto([A-I|R], S, [A-J|R0]):- memberchk(I-J, S), subst_am_goto(R, S, R0). % i_type_assoc([ alnum-['0'-'9', 'A'-'Z', a-z], alpha-['A'-'Z', a-z], csym-['0'-'9', 'A'-'Z', '_', a-z], csymf-['A'-'Z', '_', a-z], digit-['0'-'9'], lower-[a-z], quote-['"', '\'', '`'], white-['\t', ' '], paren(')')-['('], paren(']')-['['], paren('}')-['{'], cntrl-['\000\'-'\037\', '\177\'] %' ]). % expand_coa(C, I, M, M:G, P, Q):- all_states(C, Nts), maplist([J, J-N]:- gensym('nt#', N), Nts, Assoc), memberchk(I-G, Assoc), coa_dcg(C, M, P0, [], Assoc), maplist(dcg_translate_rule_expand_dot, P0, P1), append(P1, Q, P). % expand_coa(C, I, A, B, M, M:G, P, Q):- all_states(C, Nts), maplist([J, J-N]:- gensym('nt#', N), Nts, Assoc), memberchk(I-G0, Assoc), G =..[G0, A, B], coa_dcg_d(C, M, P0, [], Assoc), maplist(dcg_translate_rule_expand_dot, P0, P1), append(P1, Q, P). % coa_dcg([], _, P, P, _). coa_dcg([I-D|E], M, P, Q, Assoc):- coa_dcg(I, M, D, P, R, Assoc), coa_dcg(E, M, R, Q, Assoc). coa_dcg(_, _, [], P, P, _). coa_dcg(I, M, [[]|R], [M:PI-->[]|P], Q, Assoc):- memberchk(I-PI, Assoc), coa_dcg(I, M, R, P, Q, Assoc). coa_dcg(I, M, [A-J|R], [M:PI-->(A0, M:PJ)|P], Q, Assoc):- memberchk(I-PI, Assoc), memberchk(J-PJ, Assoc), ( A == (.), A0=[_]; A0 = A ), !, coa_dcg(I, M, R, P, Q, Assoc). % d means d-list version of coa_dcg coa_dcg_d([], _, P, P, _). coa_dcg_d([I-D|E], M, P, Q, Assoc):- coa_dcg_d(I, M, D, P, R, Assoc), coa_dcg_d(E, M, R, Q, Assoc). coa_dcg_d(_, _, [], P, P, _). coa_dcg_d(I, M, [[]|R], [M:PI-->[]|P], Q, Assoc):- memberchk(I-PI0, Assoc), PI=..[PI0, X, X], coa_dcg_d(I, M, R, P, Q, Assoc). coa_dcg_d(I, M, [A-J|R], [M:PI-->(A0, M:PJ)|P], Q, Assoc):- memberchk(I-PI0, Assoc), memberchk(J-PJ0, Assoc), PI=..[PI0, U, V], dcg_d(A, U, W, A0), PJ=..[PJ0, W, V], coa_dcg_d(I, M, R, P, Q, Assoc). % % % dcg_d((.), [A|B], B, [A]). % dcg_d([A], [A|B], B, [A]). % dcg_d({G}, A, A, {G}). % dcg_d(X, A, B, X0):- pac:complete_args(X, [A, B], X0). %%%% % ?- pac:parse_regex("a\\*",R). %@ R = [a]+[*]. % ?- pac:parse_regex("a\\\*",R). % <== intentional Syntex error % ?- pac:parse_regex("a\\\\*",R). % ?- pac:parse_regex("a\\\\\\*",R). % ?- pac:parse_regex("[abc\\]]*",R). % ?- pac:parse_regex("[abc\\\\]]*",R). % ?- pac:parse_regex("a", R). % ?- pac:parse_regex("(a)", R). % ?- pac:parse_regex("(abc)", R). % ?- pac:parse_regex("[abc]", R). % ?- pac:parse_regex("[abc]*",R). % ?- pac:parse_regex("[^abc]", R). % ?- pac:parse_regex("(.*)", R). % ?- pac:parse_regex("(a*)", R). % ?- pac:parse_regex("a*b", R). % ?- trace, pac:parse_regex(".", R). % ?- pac:parse_regex("[^a-zA-Z]",R). % ?- pac:parse_regex("a|b|c", R). % ?- pac:parse_regex("(a|b|c)**", R). % ?- pac:parse_regex("(\\(*[a]|1)",R). % ?- pac:parse_regex("abc",R). % ?- pac:parse_regex('abc',R). % ?- pac:parse_regex("[a]",R). % ?- pac:parse_regex("[ab]",R). % ?- pac:parse_regex("[a-b]",R). % parse_regex/2 never fails. char_code_option(X, Y):- char_code(X, Y). parse_regex(X, R):- regex(X, Y), paren_to_plus(Y, R). regex(X, Y) :- is_list(X), !, once(regex_list(Y, [], X, [])). regex(X, Y) :- must_be(string, X), string_chars(X, X0), once(regex_list(Y, [], X0, [])). % regex([\(C)]) --> [(\)], [C]. % escape charcter regex([(.)]) --> [(.)]. regex(G) --> ['('], regex_list(G, []), [')']. regex(out(D)) --> ['[', ^], regex_dot(D0, []), {dot_hyphen(D0, D)}. regex(dot(D)) --> ['['], regex_dot(D0, []), {dot_hyphen(D0, D)}. regex({J,K}) --> ['{'], digits(J0), [','], digits(K0), ['}'], { number_chars(J, J0), number_chars(K, K0) }. regex([C]) --> [C0], {char_code_option(C0, C)}. % digits([D|Ds]) --> [D0], {char_type(D0, digit), char_code_option(D0, D)}, digits(Ds). digits([]) --> []. % regex_list(L, L) --> look_ahead(')'). regex_list(L0, L) --> regex(X), regex_list(X, L0, L). regex_list(L, L) --> []. % regex_list(X, L0, L) --> [*], regex_list(*(X), L0, L). regex_list(X, L0, L) --> [#], regex_list(#(X), L0, L). regex_list(X, L0, L) --> [+], regex_list(+(X), L0, L). regex_list(X, L0, L) --> [?], regex_list(?(X), L0, L). regex_list(X, [(X|Y)|L0], L) --> ['|'], regex_list([Y|L0], L). % regex_list(X, [(X;Y)|L0], L) --> ['|'], regex_list([Y|L0], L). regex_list(X, L0, L) --> look_ahead('{'), regex( {J, K} ), {J =< K }, regex_list(?(X,J,K), L0, L). regex_list(X, [X|L0], L) --> regex_list(L0, L). % regex_dot([\(C)|Y], Z) --> [\], [C], regex_dot(Y,Z). regex_dot(X, X) --> [']']. regex_dot([C|Y], Z) --> [C], regex_dot(Y,Z). % dot_hyphen([],[]). dot_hyphen([X, -, Y|R], [C - D|S]):- !, drop_escape(X, X0), drop_escape(Y, Y0), char_code(X0, C), char_code(Y0, D), dot_hyphen(R, S). dot_hyphen([X|R], [C|S]):- drop_escape(X, X0), char_code(X0, C), dot_hyphen(R, S). % drop_escape(\(X), X):-!. drop_escape(X, X). % Eliminating parenthesis which is used for grouping. % ex. [dot, dot([a,b]), [c, d]] => dot + dot([a,b]) + [c,d] paren_to_plus(X, Y):- is_list(X), !, flatten(X, X0), delete(X0, [], X1), maplist(paren_to_plus, X1, X2), binary_term(+, X2, Y). paren_to_plus(*(X), *(Y)):- !, paren_to_plus(X, Y). paren_to_plus(+(X), +(Y)):- !, paren_to_plus(X, Y). paren_to_plus(?(X), []|Y):- !, paren_to_plus(X, Y). paren_to_plus(?(X, N), Y):- !, paren_to_plus(X, X0), paren_to_plus(N, X0, Y). paren_to_plus(?(X, J, K), Y):- !, paren_to_plus(X, X0), paren_to_plus(J, K, X0, Y). paren_to_plus((X; Y), (X0; Y0)):- !, paren_to_plus(X, X0), paren_to_plus(Y, Y0). paren_to_plus((X| Y), (X0| Y0)):- !, paren_to_plus(X, X0), paren_to_plus(Y, Y0). paren_to_plus(\(X), [X]):- !. paren_to_plus(X, X):- compound(X), !. paren_to_plus((.), (.)). paren_to_plus(A, [A]). % paren_to_plus(0, _, []). paren_to_plus(N, X, (X|[])+Y):- N>0, N0 is N-1, paren_to_plus(N0, X, Y). paren_to_plus(0, K, X, Y):- paren_to_plus(K, X, Y). paren_to_plus(J, K, X, X+Y):- J > 0, J0 is J-1, K0 is K - 1, paren_to_plus(J0, K0, X, Y). % look_ahead(C, [C|X], [C|X]). % % ?- phrase((w(*(.), X), w(*(.), Y)), [a,b,c], []). % ?- phrase((wl(*(.), X), wl(*(.), Y)), [a,b,c], []). expand_w(X, _, call(X), P, P):-var(X), !. % @ meta call expand_w(X, M, G, P, Q):- regex_coalgebra_code(X, coa(C, I, _)), expand_coa(C, I, M, G, P, Q). % expand_w(X, A, B, _, call(X, A, B), P, P):- var(X), !. % @ meta call expand_w(X, A, B, M, G, P, Q):- regex_coalgebra_code(X, coa(C, I, _)), expand_coa(C, I, A, B, M, G, P, Q). expand_wl(X, _, call(X), P, P):-var(X), !. % @ meta call expand_wl(X, M, G, P, Q):- regex_coalgebra_code(X, coa(C, I, _)), reverse_coa(C, C0), expand_coa(C0, I, M, G, P, Q). % expand_wl(X, A, B, _, call(X, A, B), P, P):- var(X), !. % @ meta call expand_wl(X, A, B, M, G, P, Q):- regex_coalgebra_code(X, coa(C, I, _)), reverse_coa(C, C0), expand_coa(C0, I, A, B, M, G, P, Q). reverse_coa(X, Y):- maplist(reverse_coa_, X, Y). reverse_coa_(A-B, A-C):- reverse(B, C). Kuniaki Mukai > > -- > Michael > -------------- next part -------------- > HTML attachment scrubbed and removed > _______________________________________________ > SWI-Prolog mailing list > [email protected] > https://lists.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 496 bytes Desc: Message signed with OpenPGP using GPGMail URL: <https://lists.iai.uni-bonn.de/pipermail/swi-prolog/attachments/20140802/1f009281/signature.asc>