From b6e8a9bfd57ad64453518c76357f4006ba6e13c3 Mon Sep 17 00:00:00 2001 From: elioat <{ID}+{username}@users.noreply.github.com> Date: Tue, 16 Jul 2024 13:58:44 -0400 Subject: * --- picat/basic.pi | 276 +++++++++++++++++++++++++++ picat/cp.pi | 484 ++++++++++++++++++++++++++++++++++++++++++++++ picat/exs.pi | 594 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1354 insertions(+) create mode 100644 picat/basic.pi create mode 100644 picat/cp.pi create mode 100644 picat/exs.pi (limited to 'picat') diff --git a/picat/basic.pi b/picat/basic.pi new file mode 100644 index 0000000..effe0cf --- /dev/null +++ b/picat/basic.pi @@ -0,0 +1,276 @@ +module basic. % imported by default + +'!='(X,Y) => X != Y. +'!=='(X,Y) => X !== Y. +'*'(X,Y) = X * Y. +'**'(X,Y) = X ** Y. +'+'(X) = X. +'+'(X,Y) = X + Y. +'++'(X,Y) = X ++ Y. +'-'(X) = -X. +'-'(X,Y) = X - Y. +'/'(X,Y) = X / Y. +'//'(X,Y) = X // Y. +'/<'(X,Y) = X /< Y. +'/>'(X,Y) = X /> Y. +'/\\'(X,Y) = X /\ Y. +'<'(X,Y) => X < Y. +'<<'(X,Y) = X << Y. +'<='(X,Y) => X <= Y. +'='(X,Y) => X = Y. +'=:='(X,Y) => X =:= Y. +'=<'(X,Y) => X <= Y. +'=='(X,Y) => X == Y. +'=\\='(X,Y) => X =\= Y. +'=..'(X,Y) => '=..'(X,Y). +'>'(X,Y) => X > Y. +'>='(X,Y) => X >= Y. +'>>'(X,Y) = X >> Y. +'@<'(X,Y) => X @< Y. +'@<='(X,Y) => X @=< Y. +'@=<'(X,Y) => X @=< Y. +'@>'(X,Y) => X @> Y. +'@>='(X,Y) => X @>= Y. +'\\/'(X,Y) = X \/ Y. +'^'(X, Y) = Res => bp.b_XOR_ccf(X,Y,Res). +'~'(X) = ~X. +'\\+'(Call) => throw($meta_meta_call_not_allowed('\\+'(Call))). +acyclic_term(Term) => acyclic_term(Term). +and_to_list(Conjunction) = and_to_list(Conjunction). +append(X,Y, Z) => append(X,Y,Z). +append(X,Y,Z, T) => append(X,Y,Z,T). +apply(S) = _ => throw($meta_meta_call_not_allowed(apply(S))). +apply(S, A1) = _ => throw($meta_meta_call_not_allowed(apply(S,A1))). +apply(S,A1, A2) = _ => throw($meta_meta_call_not_allowed(apply(S,A1,A2))). +apply(S,A1,A2, A3) = _ => throw($meta_meta_call_not_allowed(apply(S,A1,A2,A3))). +apply(S,A1,A2,A3, A4) = _ => throw($meta_meta_call_not_allowed(apply(S,A1,A2,A3,A4))). +apply(S,A1,A2,A3,A4, A5) = _ => throw($meta_meta_call_not_allowed(apply(S,A1,A2,A3,A4,A5))). +apply(S,A1,A2,A3,A4,A5, A6) = _ => throw($meta_meta_call_not_allowed(apply(S,A1,A2,A3,A4,A5,A6))). +apply(S,A1,A2,A3,A4,A5,A6, A7) = _ => throw($meta_meta_call_not_allowed(apply(S,A1,A2,A3,A4,A5,A6,A7))). +apply(S,A1,A2,A3,A4,A5,A6,A7, A8) = _ => throw($meta_meta_call_not_allowed(apply(S,A1,A2,A3,A4,A5,A6,A7,A8))). +apply(S,A1,A2,A3,A4,A5,A6,A7,A8, A9) = _ => throw($meta_meta_call_not_allowed(apply(S,A1,A2,A3,A4,A5,A6,A7,A8,A9))). +apply(S,A1,A2,A3,A4,A5,A6,A7,A8,A9, A10) = _ => throw($meta_meta_call_not_allowed(apply(S,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10))). +arg(I,T, A) => arg(I,T,A). +arity(Term) = arity(Term). +array(Term) => array(Term). +ascii_digit(Char) => digit(Char). +ascii_alpha(Char) => ascii_alpha(Char). +ascii_alpha_digit(Char) => ascii_alpha_digit(Char). +ascii_lowercase(Char) => lowercase(Char). +ascii_uppercase(Char) => uppercase(Char). +atom(Term) => atom(Term). +atom_chars(Atm) = atom_chars(Atm). +atom_codes(Atm) = atom_codes(Atm). +atomic(Term) => atomic(Term). +attr_var(Term) => attr_var(Term). +avg(ListOrArray) = avg(ListOrArray). +between(From,To, X) => between(From,To,X). +bigint(Term) => bigint(Term). +bind_vars(Term, Val) => bind_vars(Term,Val). +call(S) => throw($meta_meta_call_not_allowed(call(S))). +call(S, A1) => throw($meta_meta_call_not_allowed(call(S,A1))). +call(S,A1, A2) => throw($meta_meta_call_not_allowed(call(S,A1,A2))). +call(S,A1,A2, A3) => throw($meta_meta_call_not_allowed(call(S,A1,A2,A3))). +call(S,A1,A2,A3, A4) => throw($meta_meta_call_not_allowed(call(S,A1,A2,A3,A4))). +call(S,A1,A2,A3,A4, A5) => throw($meta_meta_call_not_allowed(call(S,A1,A2,A3,A4,A5))). +call(S,A1,A2,A3,A4,A5, A6) => throw($meta_meta_call_not_allowed(call(S,A1,A2,A3,A4,A5,A6))). +call(S,A1,A2,A3,A4,A5,A6, A7) => throw($meta_meta_call_not_allowed(call(S,A1,A2,A3,A4,A5,A6,A7))). +call(S,A1,A2,A3,A4,A5,A6,A7, A8) => throw($meta_meta_call_not_allowed(call(S,A1,A2,A3,A4,A5,A6,A7,A8))). +call(S,A1,A2,A3,A4,A5,A6,A7,A8, A9) => throw($meta_meta_call_not_allowed(call(S,A1,A2,A3,A4,A5,A6,A7,A8,A9))). +call(S,A1,A2,A3,A4,A5,A6,A7,A8,A9, A10) => throw($meta_meta_call_not_allowed(call(S,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10))). +call_cleanup(S, Cleanup) => throw($meta_meta_call_not_allowed(call_cleanup(S,Cleanup))). +catch(S,Exception, Handler) => throw($meta_meta_call_not_allowed(catch(S,Exception,Handler))). +char(Term) => char(Term). +chr(Code) = chr(Code). +clear(Map) => clear(Map). +compare_terms(Term1, Term2) = compare_terms(Term1,Term2). +compound(Term) => compound(Term). +copy_term(Term) = copy_term(Term). +copy_term_shallow(Term) = copy_term_shallow(Term). +del(Map,Key) => del(Map,Key). +delete(List, X) = delete(List,X). +delete_all(List, X) = delete_all(List,X). +different_terms(Term1, Term2) => different_terms(Term1,Term2). +digit(Char) => digit(Char). +div(X,Y) = X div Y. +dvar(Term) => dvar(Term). +bool_dvar(Term) => bool_dvar(Term). +dvar_or_int(Term) => dvar_or_int(Term). +fail => fail. +false => false. +find_all(Template, S) = _ => throw($meta_meta_call_not_allowed(find_all(Template,S))). +findall(Template, S) = _ => throw($meta_meta_call_not_allowed(findall(Template,S))). +count_all(S) = _ => throw($meta_meta_call_not_allowed(count_all(S))). +first(Compound) = first(Compound). +flatten(List) = flatten(List). +float(Term) => float(Term). +fold(F,Acc, List) = fold(F,Acc,List). +freeze(X, Goal) => throw($meta_meta_call_not_allowed(freeze(X,Goal))). +functor(T,F, N) => functor(T,F,N). +get(Map, Key) = get(Map,Key). +get(Map,Key, Default) = get(Map,Key,Default). +get_attr(AttrVar, Key) = get_attr(AttrVar,Key). +get_attr(AttrVar,Key, DefaultVal) = get_attr(AttrVar,Key,DefaultVal). +get_global_map = get_global_map(). +get_global_map(Id) = get_global_map(Id). +get_heap_map = get_heap_map(). +get_heap_map(Id) = get_heap_map(Id). +get_table_map = get_table_map(). +get_table_map(Id) = get_table_map(Id). +ground(Term) => ground(Term). +handle_exception(Exception, Source) => handle_exception(Exception,Source). +has_key(Map, Key) => has_key(Map,Key). +hash_code(Term) = hash_code(Term). +head(List) = head(List). +heap_is_empty(Heap) => heap_is_empty(Heap). +heap_pop(Heap) = heap_pop(Heap). +heap_push(Heap, Elm) => heap_push(Heap,Elm). +heap_size(Heap) = heap_size(Heap). +heap_to_list(Heap) = heap_to_list(Heap). +heap_top(Heap) = heap_top(Heap). +insert(List,Index, Elm) = insert(List,Index,Elm). +insert_all(List,Index, AList) = insert_all(List,Index,AList). +insert_ordered(OrderedList, Elm) = insert_ordered(OrderedList,Elm). +insert_ordered_no_dup(OrderedList, Elm) = insert_ordered_no_dup(OrderedList,Elm). +insert_ordered_down(OrderedList, Elm) = insert_ordered_down(OrderedList,Elm). +insert_ordered_down_no_dup(OrderedList, Elm) = insert_ordered_down_no_dup(OrderedList,Elm). +int(Term) => int(Term). +integer(Term) => integer(Term). +is(X, Y) => is(X,Y). +keys(Map) = keys(Map). +last(Compound) = last(Compound). +length(ArrayOrList) = length(ArrayOrList). +len(ArrayOrList) = len(ArrayOrList). +list(Term) => list(Term). +list_to_and(List) = list_to_and(List). +lowercase(Char) => lowercase(Char). +map(Func,List1, List2) = map(Func,List1,List2). +map(FuncOrList, ListOrFunc) = map(FuncOrList,ListOrFunc). +map(Term) => map(Term). +map_to_list(Map) = map_to_list(Map). +max(ListOrArray) = max(ListOrArray). +max(X, Y) = max(X,Y). +maxint_small() = maxint_small(). +maxof(Call, Exp) => throw($meta_meta_call_not_allowed(maxof(Call,Exp))). +maxof(Call,Exp, ReportCall) => throw($meta_meta_call_not_allowed(maxof(Call,Exp,ReportCall))). +maxof_inc(Call, Exp) => throw($meta_meta_call_not_allowed(maxof_inc(Call,Exp))). +maxof_inc(Call,Exp, ReportCall) => throw($meta_meta_call_not_allowed(maxof_inc(Call,Exp,ReportCall))). +membchk(Term, List) => membchk(Term,List). +member(Term, List) => member(Term,List). +min(ListOrArray) = min(ListOrArray). +min(X, Y) = min(X,Y). +minint_small() = minint_small(). +minof(Call, Exp) => throw($meta_meta_call_not_allowed(minof(Call,Exp))). +minof(Call,Exp, ReportCall) => throw($meta_meta_call_not_allowed(minof(Call,Exp,ReportCall))). +minof_inc(Call, Exp) => throw($meta_meta_call_not_allowed(minof_inc(Call,Exp))). +minof_inc(Call,Exp, ReportCall) => throw($meta_meta_call_not_allowed(minof_inc(Call,Exp,ReportCall))). +mod(X,Y) = X mod Y. +name(Struct) = name(Struct). +new_array(D1) = new_array(D1). +new_array(D1, D2) = new_array(D1,D2). +new_array(D1,D2, D3) = new_array(D1,D2,D3). +new_array(D1,D2,D3, D4) = new_array(D1,D2,D3,D4). +new_array(D1,D2,D3,D4, D5) = new_array(D1,D2,D3,D4,D5). +new_array(D1,D2,D3,D4,D5, D6) = new_array(D1,D2,D3,D4,D5,D6). +new_array(D1,D2,D3,D4,D5,D6, D7) = new_array(D1,D2,D3,D4,D5,D6,D7). +new_array(D1,D2,D3,D4,D5,D6,D7, D8) = new_array(D1,D2,D3,D4,D5,D6,D7,D8). +new_array(D1,D2,D3,D4,D5,D6,D7,D8, D9) = new_array(D1,D2,D3,D4,D5,D6,D7,D8,D9). +new_array(D1,D2,D3,D4,D5,D6,D7,D8,D9, D10) = new_array(D1,D2,D3,D4,D5,D6,D7,D8,D9,D10). +new_min_heap(IntOrList) = new_min_heap(IntOrList). +new_max_heap(IntOrList) = new_max_heap(IntOrList). +new_list(N) = new_list(N). +new_list(N, InitVal) = new_list(N,InitVal). +new_map() = new_map(). +new_map(Int, PairsList) = new_map(Int,PairsList). +new_map(IntOrPairsList) = new_map(IntOrPairsList). +new_set() = new_set(). +new_set(Int, PairsList) = new_set(Int,PairsList). +new_set(IntOrPairsList) = new_set(IntOrPairsList). +new_struct(Name, IntOrList) = new_struct(Name,IntOrList). +nonvar(Term) => nonvar(Term). +not(Call) => throw($meta_meta_call_not_allowed(not(Call))). +nth(I,L, V) => nth(I,L,V). +number(Term) => number(Term). +number_chars(Num) = number_chars(Num). +number_codes(Num) = number_codes(Num). +number_vars(Term, N0) = number_vars(Term,N0). +number_vars(Term) => number_vars(Term). +once(Call) => throw($meta_meta_call_not_allowed(once(Call))). +ord(Char) = ord(Char). +parse_radix_string(String, Base) = parse_radix_string(String,Base). +parse_term(String) = parse_term(String). +parse_term(String,Term, Vars) => parse_term(String,Term,Vars). +post_event(X, Event) => post_event(X,Event). +post_event_any(X, Event) => post_event_any(X,Event). +post_event_bound(X) => post_event_bound(X). +post_event_dom(X, Event) => post_event_dom(X,Event). +post_event_ins(X) => post_event_ins(X). +prod(ListOrArray) = prod(ListOrArray). +put(Map,Key, Val) => put(Map,Key,Val). +put(Map, Key) => put(Map,Key,not_a_value). +put_attr(AttrVar,Key, Val) => put_attr(AttrVar,Key,Val). +real(Term) => real(Term). +reduce(ListOrF, FOrList) = reduce(ListOrF,FOrList). +reduce(ListOrF,FOrList, InitVal) = reduce(ListOrF,FOrList,InitVal). +rem(X,Y) = X rem Y. +remove_dups(List) = remove_dups(List). +repeat => repeat. +reverse(ListOrArray) = reverse(ListOrArray). +second(Compound) = second(Compound). +select(X,List, ResList) => select(X,List,ResList). +size(Map) = size(Map). +slice(ListOrArray, From) = slice(ListOrArray,From). +slice(ListOrArray,From, To) = slice(ListOrArray,From,To). +sort(ListOrArray) = sort(ListOrArray). +sort(ListOrArray, KeyIndex) = sort(ListOrArray,KeyIndex). +sort_down(ListOrArray) = sort_down(ListOrArray). +sort_down(ListOrArray, KeyIndex) = sort_down(ListOrArray,KeyIndex). +sort_down_remove_dups(ListOrArray) = sort_down_remove_dups(ListOrArray). +sort_down_remove_dups(ListOrArray, KeyIndex) = sort_down_remove_dups(ListOrArray,KeyIndex). +sort_remove_dups(ListOrArray) = sort_remove_dups(ListOrArray). +sort_remove_dups(ListOrArray, KeyIndex) = sort_remove_dups(ListOrArray,KeyIndex). +sorted(ListOrArray) => sorted(ListOrArray). +sorted_down(ListOrArray) => sorted_down(ListOrArray). +string(Term) => string(Term). +struct(Term) => struct(Term). +subsumes(Term1, Term2) => subsumes(Term1,Term2). +sum(ListOrArray) = sum(ListOrArray). +tail(List) = tail(List). +throw(E) => throw(E). +to_array(List) = to_array(List). +to_atom(String) = to_atom(String). +to_binary_string(Int) = to_binary_string(Int). +to_codes(Term) = to_codes(Term). +to_fstring(Term) = to_fstring(Term). +to_fstring(Format, A1) = to_fstring(Format,A1). +to_fstring(Format,A1, A2) = to_fstring(Format,A1,A2). +to_fstring(Format,A1,A2, A3) = to_fstring(Format,A1,A2,A3). +to_fstring(Format,A1,A2,A3, A4) = to_fstring(Format,A1,A2,A3,A4). +to_fstring(Format,A1,A2,A3,A4, A5) = to_fstring(Format,A1,A2,A3,A4,A5). +to_fstring(Format,A1,A2,A3,A4,A5, A6) = to_fstring(Format,A1,A2,A3,A4,A5,A6). +to_fstring(Format,A1,A2,A3,A4,A5,A6, A7) = to_fstring(Format,A1,A2,A3,A4,A5,A6,A7). +to_fstring(Format,A1,A2,A3,A4,A5,A6,A7, A8) = to_fstring(Format,A1,A2,A3,A4,A5,A6,A7,A8). +to_fstring(Format,A1,A2,A3,A4,A5,A6,A7,A8, A9) = to_fstring(Format,A1,A2,A3,A4,A5,A6,A7,A8,A9). +to_fstring(Format,A1,A2,A3,A4,A5,A6,A7,A8,A9, A10) = to_fstring(Format,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10). +to_hex_string(Int) = to_hex_string(Int). +to_integer(NumOrCharOrString) = to_integer(NumOrCharOrString). +to_int(NumOrCharOrString) = to_int(NumOrCharOrString). +to_list(Struct) = to_list(Struct). +to_lowercase(StringOrChar) = to_lowercase(StringOrChar). +to_number(NumOrCharOrString) = to_number(NumOrCharOrString). +to_oct_string(Int) = to_oct_string(Int). +to_radix_string(Int, Base) = to_radix_string(Int,Base). +to_real(NumOrString) = to_real(NumOrString). +to_float(NumOrString) = to_float(NumOrString). +to_string(Term) = to_string(Term). +to_uppercase(StringOrChar) = to_uppercase(StringOrChar). +true => true. +uppercase(Char) => uppercase(Char). +values(Map) = values(Map). +var(Term) => var(Term). +variant(Term1, Term2) => variant(Term1,Term2). +vars(Term) = vars(Term). +zip(Lists) = zip(Lists). +zip(List1, List2) = zip(List1,List2). +zip(List1,List2, List3) = zip(List1,List2,List3). +zip(List1,List2,List3, List4) = zip(List1,List2,List3,List4). diff --git a/picat/cp.pi b/picat/cp.pi new file mode 100644 index 0000000..6663df1 --- /dev/null +++ b/picat/cp.pi @@ -0,0 +1,484 @@ +module cp. +import common_constr. + +% X #!= Y +% X #/\ Y +% X #< Y +% X #<= Y +% X #<=> Y +% X #= Y +% X #=< Y +% X #=> Y +% X #> Y +% X #>= Y +% X #\/ Y +% X #^ Y +% #~ X +% Vars::Exp +% Vars notin Exp +% acyclic(Vs,Es) +% acyclic_d(Vs,Es) +% all_different(FDVars) +% all_different_except_0(FDVars) +% all_distinct(FDVars) +% assignment(FDVars1,FDVars2) +% at_least(N,L,V) +% at_most(N,L,V) +% circuit(FDVars) +% count(V,FDVars,N) +% count(V,FDVars,Rel,N) +% cumulative(Ss,Ds,Rs,Limit) +% decreasing(L) +% decreasing_strict(L) +% diffn(RectangleList) +% disjunctive_tasks(Tasks)(cp only) +% element(I,List,V) +% element0(I,List,V) +% exactly(N,L,V): +% fd_degree(FDVar)=Degree(cp only) +% fd_disjoint(DVar1,DVar2) +% fd_dom(FDVar) = List +% fd_false(FDVar,Elm) +% fd_max(FDVar) = Max +% fd_min(FDVar) = Min +% fd_min_max(FDVar,Min,Max) +% fd_next(FDVar,Elm) = NextElm +% fd_prev(FDVar,Elm) = PrevElm +% fd_set_false(FDVar,Elm)(cp only) +% fd_size(FDVar) = Size +% fd_true(FDVar,Elm) +% fd_vector_min_max(Min,Max) +% global_cardinality(List,Pairs) +% hcp(Vs,Es) +% hcp(Vs,Es,K) +% hcp_grid(A) +% hcp_grid(A,Es) +% hcp_grid(A,Es,K) +% increasing(L) +% increasing_strict(L) +% indomain(Var)(nondet)(cp only) +% indomain_down(Var)(nondet)(cp only) +% lex_le(L_1,L_2) +% lex_lt(L_1,L_2) +% matrix_element(Matrix,I,J,V) +% matrix_element0(Matrix,I,J,V) +% neqs(NeqList)(cp only) +% new_dvar() = FDVar +% new_fd_var() = FDVar +% path(Vs,Es,Src,Dest) +% path_d(Vs,Es,Src,Dest) +% regular(X,Q,S,D,Q0,F) +% scalar_product(A,X,Product) +% scalar_product(A,X,Rel,Product) +% scc(Vs,Es) +% scc(Vs,Es,K) +% scc_d(Vs,Es) +% scc_d(Vs,Es,K) +% scc_grid(A) +% scc_grid(A,K) +% serialized(Starts,Durations) +% solve(Opts,Vars)(nondet) +% solve(Vars)(nondet) +% solve_all(Opts,Vars) = List +% solve_all(Vars) = List +% solve_suspended(Opt)(cp only) +% solve_suspended(cp only) +% subcircuit(FDVars) +% subcircuit_grid(A) +% subcircuit_grid(A,K) +% table_in(DVars,R) +% table_notin(DVars,R) +% tree(Vs,Es) +% tree(Vs,Es,K) + +include "cp_sat_mip_smt.pi". % common built-ins for cp, sat, mip, and smt + +'::'(Vars,Domain) => + bp.'_$_picat_in'(cp,Vars,Domain). + +% '#='(X,Y) => '#='(X,Y) +'#='(X,Y) => bp.'#='(X,Y). + +% '#>='(X,Y) => '#>='(X,Y) +'#>='(X,Y) => bp.'#>='(X,Y). + +% '#>'(X,Y) => '#>'(X,Y) +'#>'(X,Y) => bp.'#>'(X,Y). + +% '#<'(X,Y) => '#<'(X,Y) +'#<'(X,Y) => bp.'#<'(X,Y). + +% '#=<'(X,Y) => '#=<'(X,Y) +'#=<'(X,Y) => bp.'#=<'(X,Y). + +% '#!='(X,Y) => '#!='(X,Y) +'#!='(X,Y) => bp.'#\\='(X,Y). + +% '#\\='(X,Y) => '#\\='(X,Y) +'#\\='(X,Y) => bp.'#\\='(X,Y). + +% '#<=>'(X,Y) => '#<=>'(X,Y) +'#<=>'(X,Y) => bp.'#<=>'(X,Y). + +% '#=>'(X,Y) => '#=>'(X,Y) +'#=>'(X,Y) => bp.'#=>'(X,Y). + +% '#/\\'(X,Y) => '#/\\'(X,Y) +'#/\\'(X,Y) => bp.'#/\\'(X,Y). + +% '#\\/'(X,Y) => '#\\/'(X,Y) +'#\\/'(X,Y) => bp.'#\\/'(X,Y). + +% '#^'(X,Y) => '#^'(X,Y) +'#^'(X,Y) => bp.'#\\'(X,Y). + +% '#~'(X) => '#~'(X) +'#~'(X) => bp.'#\\'(X). + +% solve(Vars) => solve(Vars). +solve(Vars) => + (bp.dvar_or_int_list(Vars) -> VList = Vars; vars(Vars) = VList), + bp.labeling([],VList). + +% solve(Options,Vars) => solve(Options,Vars) +solve(Options,Vars) => + (bp.dvar_or_int_list(Vars) -> VList = Vars; vars(Vars) = VList), + (select($report(ReportCall), Options,Options1) -> + MetaCalls = [$report('$dyna_eval_pred'(['$picat_top_level'],ReportCall))] + ; + Options1 = Options, + MetaCalls = [] + ), + (select($label(LabelPred), Options1,Options2) -> + (atom(LabelPred) -> true; handle_exception($atom_expected(LabelPred), solve)), + (bp.'$dyna_resolve_name'(['$picat_top_level'],LabelPred,1,pred,MLabelPred) -> + true + ; + bp.c_module_qualified_pred_name(glb,LabelPred,MLabelPred) + ), + MetaCalls1 = [$label(MLabelPred)|MetaCalls] + ; + Options2 = Options1, + MetaCalls1 = MetaCalls + ), + bp.labeling(MetaCalls1 ++ Options2,VList). + +% solve_all(Vars) = solve_all(Vars). +solve_all(Vars) = + solve_all([],Vars). + +% solve_all(Options,Vars) = solve_all(Options,Vars). +solve_all(Options,Vars) = + findall(Vars, solve(Options,Vars)). + +% solve_suspended => solve_suspended. +solve_suspended => + bp.frozen(FL), + FVars = [FVar : FVar in vars(FL), dvar(FVar)], + bp.labeling([],FVars). + +solve_suspended(Options) => + bp.frozen(FL), + FVars = [FVar : FVar in vars(FL), dvar(FVar)], + bp.labeling(Options,FVars). + +% fd_degree(FDVar) = fd_degree(FDVar). +fd_degree(FDVar) = Degree, dvar(FDVar) => bp.fd_degree(FDVar,Degree). +fd_degree(FDVar) = Degree, integer(FDVar) => Degree = 0. +fd_degree(FDVar) = _Degree => handle_exception($dvar_expected(FDVar), fd_degree). + +% fd_set_false(FDVar,Elm) => fd_set_false(FDVar,Elm). +fd_set_false(FDVar,Elm), dvar_or_int(FDVar), integer(Elm) => + bp.domain_set_false(FDVar,Elm). +fd_set_false(FDVar,Elm) => + Source = fd_set_false, + (integer(Elm) -> + handle_exception($dvar_expected(FDVar), Source) + ; + handle_exception($integer_expected(Elm), Source) + ). + +% all_different(FDVars) => all_different(FDVars). +all_different(FDVars) => + (array(FDVars) -> to_list(FDVars) = List; List = FDVars), + bp.alldifferent(List). + +% all_distinct(FDVars) => all_distinct(FDVars). +all_distinct(FDVars) => + (array(FDVars) -> to_list(FDVars) = List; List = FDVars), + bp.all_distinct(List). + +% assignment(FDVars1,FDVars2) => assignment(FDVars1,FDVars2). +assignment(FDVars1,FDVars2) => + (array(FDVars1) -> to_list(FDVars1) = List1; List1 = FDVars1), + (array(FDVars2) -> to_list(FDVars2) = List2; List2 = FDVars2), + bp.assignment(List1,List2). + +% circuit(FDVars) => circuit(FDVars). +circuit(FDVars) => + (array(FDVars) -> to_list(FDVars) = List; List = FDVars), + bp.circuit(List). + +% cumulative(Starts,Durations,Resources,Limit) => cumulative(Starts,Durations,Resources,Limit). +cumulative(Starts,Durations,Resources,Limit) => + (array(Starts) -> to_list(Starts) = SList; SList = Starts), + (array(Durations) -> to_list(Durations) = DList; DList = Durations), + (array(Resources) -> to_list(Resources) = RList; RList = Resources), + bp.bp_cumulative(SList,DList,RList,Limit,cp). + +% diffn(RectangleList) => diffn(RectangleList). +diffn(RectangleList) => + (array(RectangleList) -> to_list(RectangleList) = RList; RList = RectangleList), + bp.bp_diffn(RList,cp). + +% disjunctive_tasks(Tasks) => disjunctive_tasks(Tasks). +disjunctive_tasks(Tasks) => + (array(Tasks) -> to_list(Tasks) = TList; TList = Tasks), + bp.post_disjunctive_tasks(TList). + +% element(I,Terms,V) => element(I,Terms,V). +element(I,Terms,V) => + (array(Terms) -> to_list(Terms) = List; List = Terms), + (bp.dvar_or_int_list(List) -> true; handle_exception($dvar_or_int_list_expected(List), element)), + bp.element(I,List,V). + +% 0-based indexing +% element0(I,FDVars,V) => element0(I,FDVars,V). +element0(I,FDVars,V) => + (array(FDVars) -> to_list(FDVars) = List; List = FDVars), + (bp.dvar_or_int_list(List) -> true; handle_exception($dvar_or_int_list_expected(List), element)), + bp.element0(I,List,V). + +% fd_set_false(FDVar,Elm) => fd_set_false(FDVar,Elm). +% global_cardinality(FDVars,Pairs) => global_cardinality(FDVars,Pairs). +global_cardinality(List,Pairs) => + (bp.check_pairs(Pairs) -> true; handle_exception($pairs_expected(Pairs), global_cardinality)), + bp.global_cardinality(List,Pairs). + +% indomain(Var) => indomain(Var). +indomain(Var), dvar(Var) => + bp.indomain_dvar(Var). +indomain(Var), integer(Var) => true. +indomain(Var) => + handle_exception($dvar_expected(Var), indomain). + +% indomain_down(Var) => indomain_down(Var). +indomain_down(Var), dvar(Var) => + bp.domain_min_max(Var,_,Max), + bp.indomain_dvar_backward(Var,Max). +indomain_down(Val), integer(Val) => true. +indomain_down(Var) => + handle_exception($dvar_expected(Var), indomain_down). + +% neqs(Neqs) => neqs(Neqs). +neqs(Neqs) => + (array(Neqs) -> to_list(Neqs) = List; List = Neqs), + check_neqs_args(List,List1), + bp.post_neqs(List1). + +% serialized(Starts,Durations) => serialized(Starts,Durations). +serialized(Starts,Durations) => + (array(Starts) -> to_list(Starts) = SList; SList = Starts), + (array(Durations) -> to_list(Durations) = DList; DList = Durations), + bp.disjunctive_tasks(SList,DList). + +% subcircuit(FDVars) => subcircuit(FDVars). +subcircuit(FDVars) => + (array(FDVars) -> to_list(FDVars) = List; List = FDVars), + bp.subcircuit(List). + +%%%%%%%%%%%%%%%%%%%%%%%% common to cp and sat modules %%%%%%%%%%%%%%%%%%%%%% +%% +table_in(Vars,Tuples) => + bp.table_in(Vars,Tuples). + +%% +notin(Vars,Domain) => + bp.'_$_picat_notin'(cp,Vars,Domain). + +%% +table_notin(Vars,Tuples) => + bp.table_notin(Vars,Tuples). + +/************************************************************************* + regular(L,Q,S,M,Q0,Fs) + + L : A sentence (an IntVar array or list) + Q : number of states + S : input_max, inputs are from 1 to S + M : transition matrix: M[I,J] (I in 1..S, J in 1..Q) is a list of outgoing states for NFA (0 means an error). + Q0: initial state + Fs : accepting states +***************************************************************************/ +regular(L, Q, S, M, Q0, Fs) => + regular_constr(L, Q, S, M, Q0, Fs, cp). + +%% +%% lex_le(L1,L2): collection L1 is lexicographically less than or equal to L2 +%% +lex_le(L1,L2), list(L1), list(L2) => + check_args_lex(L1,L2,L11,L22), + lex_le_aux(L11,L22). +lex_le(L1,L2), array(L1), array(L2) => + check_args_lex(to_list(L1), to_list(L2), L11,L22), + lex_le_aux(L11,L22). +lex_le(L1,L2) => + throw($invalid(lex_le(L1,L2))). + +%% +%% lex_lt(L1,L2): collection L1 is lexicographically less than L2 +%% +lex_lt(L1,L2), list(L1), list(L2) => + check_args_lex(L1,L2,L11,L22), + lex_lt_aux(L11,L22). +lex_lt(L1,L2), array(L1), array(L2) => + check_args_lex(to_list(L1), to_list(L2), L11,L22), + lex_lt_aux(L11,L22). +lex_lt(L1,L2) => + throw($invalid(lex_lt(L1,L2))). + +check_args_lex(L1,L2,L11,L22) => + (bp.dvar_or_int_list(L1) -> true; handle_exception($dvar_list_expected(L1), lex)), + (bp.dvar_or_int_list(L2) -> true; handle_exception($dvar_list_expected(L2), lex)), + N1 = length(L1), + N2 = length(L2), + (N1 == N2 -> + L11 = L1, L22 = L2 + ; N1 < N2 -> + Min = min([fd_min(V) : V in L2]), + Min1 = Min-1, + L1Pad = [Min1 : _ in 1..N2-N1], + L11 = L1++L1Pad, L22 = L2 + ; + Min = min([fd_min(V) : V in L1]), + Min1 = Min-1, + L2Pad = [Min1 : _ in 1..N1-N2], + L11 = L1, L22 = L2++L2Pad + ). + +%%% +lex_le_aux([],_) => true. +lex_le_aux([X],[Y]) => + (var(X) -> + (var(Y) -> + bp.v_ge_v(Y,X) + ; + bp.domain_region_max(X,Y) + ) + ; + (var(Y) -> + bp.domain_region_min(Y,X) + ; + X =< Y + ) + ). +lex_le_aux([X|Xs],[Y|Ys]), integer(X), integer(Y) => + (X < Y -> + true + ; X == Y -> + lex_le_aux(Xs,Ys) + ; + fail + ). +lex_le_aux([X|Xs],[Y|Ys]) => + watch_lex_le(X,Y,Xs,Ys). + +watch_lex_le(X,Y,_Xs,_Ys), var(X), + {generated, ins(X), ins(Y), bound(X), bound(Y)} + => + fd_min_max(X,MinX,_), + fd_min_max(Y,_,MaxY), + (MinX > MaxY -> fail; true). +watch_lex_le(X,Y,_Xs,_Ys), var(Y), + {generated, ins(Y), bound(Y)} + => + fd_min_max(X,MinX,_), + fd_min_max(Y,_,MaxY), + (MinX > MaxY -> fail; true). +watch_lex_le(X,Y,Xs,Ys) => % come here when both X, Y become integers + (X < Y -> + true + ; X == Y -> + lex_le(Xs,Ys) + ; + fail + ). + +%%% +lex_lt_aux([],_) => true. +lex_lt_aux([X],[Y]) => + (var(X) -> + (var(Y) -> + bp.v_gt_v(Y,X) + ; + bp.domain_region_max(X,Y-1) + ) + ; + (var(Y) -> + bp.domain_region_min(Y,X+1) + ; + X < Y + ) + ). +lex_lt_aux([X|Xs],[Y|Ys]), integer(X), integer(Y) => + (X < Y -> + true + ; X == Y -> + lex_lt_aux(Xs,Ys) + ; + fail + ). +lex_lt_aux([X|Xs],[Y|Ys]) => + watch_lex_lt(X,Y,Xs,Ys). + +watch_lex_lt(X,Y,_Xs,_Ys), var(X), + {generated, ins(X), ins(Y), bound(X), bound(Y)} + => + fd_min_max(X,MinX,_), + fd_min_max(Y,_,MaxY), + (MinX > MaxY -> fail; true). +watch_lex_lt(X,Y,_Xs,_Ys), var(Y), + {generated, ins(Y), bound(Y)} + => + fd_min_max(X,MinX,_), + fd_min_max(Y,_,MaxY), + (MinX > MaxY -> fail; true). +watch_lex_lt(X,Y,Xs,Ys) => % come here when both X, Y become integers + (X < Y -> + true + ; X == Y -> + lex_lt(Xs,Ys) + ; + fail + ). + +%% +nvalue(N, L) => bp.nvalue(N,L). + +%% The following constraints are proposed and implemented by Hakan Kjellerstrand +matrix_element(M,I,J,MIJ) => + check_matrix(M,NRows,NCols), + matrix_element(M,NRows,NCols,I,J,MIJ,cp). + +% +% Requires that all non-zero values in Xs are distinct. +% +alldifferent_except_0(Xs) => + all_different_except_0(Xs). + +all_different_except_0(Xs) => + (list(Xs) -> + Arr = to_array(Xs) + ;array(Xs) -> + Arr = Xs + ; + handle_exception($dvar_or_int_collection_expected(Xs), all_different_except_0) + ), + all_different_except_0_aux(Arr). + +all_different_except_0_aux(Xs) => + N = len(Xs), + foreach(I in 1..N-1, J in I+1..N) + Xs[I] #= 0 #\/ Xs[J] #= 0 #\/ Xs[I] #!= Xs[J] + end. + diff --git a/picat/exs.pi b/picat/exs.pi new file mode 100644 index 0000000..17f8083 --- /dev/null +++ b/picat/exs.pi @@ -0,0 +1,594 @@ +/* Several examples in Picat */ +/**** begin file exs.pi ****/ +import cp, planner. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% PREDICATES AND FUNCTIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Here are several versions for computing Fibonacci numbers +% A predicate +fibp(0,F) => F = 1. +fibp(1,F) => F = 1. +fibp(N,F),N>1 => fibp(N-1,F1), fibp(N-2,F2), F = F1+F2. + +% A function +fibf(0)=F => F = 1. +fibf(1)=F => F = 1. +fibf(N)=F, N>1 => F = fibf(N-1)+fibf(N-2). + +% A function with function facts +fibfa(0) = 1. +fibfa(1) = 1. +fibfa(N) = fibfa(N-1)+fibfa(N-2). + +% Using if-then-else +fibi(N) = F => + if N == 0 then + F = 1 + elseif N == 1 then + F = 1 + else + F = fibg(N-1)+fibg(N-2) + end. + +% Using Prolog-style if-then-else +fibg(N) = F => + (N == 0 -> + F = 1 + ;N == 1 -> + F = 1 + ; + F = fibg(N-1)+fibg(N-2) + ). + +% Using a conditional expression +fibc(N) = cond((N == 0; N == 1), 1, fibc(N-1)+fibc(N-2)). + +% A tabled function +table +fibt(0) = 1. +fibt(1) = 1. +fibt(N) = fibt(N-1)+fibt(N-2). + +% A nondeterministic predicate with a backtrackable rule +my_member(Y,[X|_]) ?=> Y = X. +my_member(Y,[_|L]) => my_member(Y,L). + +my_between(From,To,X), From == To => X = From. +my_between(From,To,X),From < To => X = From; my_between(From+1,To,X). + +my_select(Y,[X|L],LR) ?=> Y = X, LR = L. +my_select(Y,[X|L],LR) => LR = [X|LRR], my_select(Y,L,LRR). + +my_permutation([],P) => P = []. +my_permutation(L,P) => + P = [X|PR], + my_select(X,L,LR), + my_permutation(LR,PR). + +% predicate facts +index(+,-) (-,+) +edge(1,2). +edge(1,3). +edge(2,3). +edge(3,2). + +% several sort algorithms +merge_sort([]) = []. +merge_sort([X]) = [X]. +merge_sort(L) = SL => split(L,L1,L2), SL = merge(merge_sort(L1),merge_sort(L2)). + +split([X,Y|Zs],L1,L2) => L1 = [X|LL1], L2 = [Y|LL2], split(Zs,LL1,LL2). +split(Zs,L1,L2) => L1 = Zs,L2 = []. + +merge([],Ys) = Ys. +merge(Xs,[]) = Xs. +merge([X|Xs],Ys@[Y|_]) = [X|Zs], X < Y => Zs = merge(Xs,Ys). % Ys@[Y|_] is an as-pattern +merge(Xs,[Y|Ys]) = [Y|Zs] => Zs = merge(Xs,Ys). + +insert_sort([]) = []. +insert_sort([H|T]) = insert(H,insert_sort(T)). + +private +insert(X,[]) = [X]. +insert(X,Ys@[Y|_]) = Zs, X =< Y => Zs = [X|Ys]. +insert(X,[Y|Ys]) = [Y|insert(X,Ys)]. + +% two versions that return the minumum and maximum of a list +% a predicate +min_max_p([H|T],Min,Max) => min_max_p_aux(T,H,Min,H,Max). + +% A private function is not visiable outside +private +min_max_p_aux([],CMin,Min,CMax,Max) => CMin = Min,CMax = Max. +min_max_p_aux([H|T],CMin,Min,CMax,Max) => min_max_p_aux(T,min(CMin,H),Min,max(CMax,H),Max). + +% a function that returns the minimum and maximum of a list as a pair +min_max([H|T]) = min_max_aux(T,H,H). + +private +min_max_aux([],CMin,CMax) = (CMin,CMax). +min_max_aux([H|T],CMin,CMax) = min_max_aux(T,min(CMin,H),max(CMax,H)). + +% return the sum of a list +sum_list(L) = Sum => + sum_list_aux(L,0,Sum). + +% a private predicate is never exported +private +sum_list_aux([],Acc,Sum) => Sum = Acc. +sum_list_aux([X|L],Acc,Sum) => sum_list_aux(L,Acc+X,Sum). + +% two lists that are structually equal, e.g., struct_equal(X,[a]) fails +struct_equal(A,B),atomic(A) => A == B. +struct_equal([H1|T1],[H2|T2]) => + struct_equal(H1,H2), + struct_equal(T1,T2). + +is_sorted([]) => true. +is_sorted([_]) => true. +is_sorted([X|L@[Y|_]]) =>X @<= Y, is_sorted(L). + +% An empty tree is represented by {}, and a non-empty binary tree is +% represented by its root, which takes form {Val,Left,Right}. + +is_btree({}) => true. +is_btree({_Val,Left,Right}) => + is_btree(Left), + is_btree(Right). + +inorder({}) = []. +inorder({Val,Left,Right}) = inorder(Left) ++ [Val] ++ inorder(Right). + +% binary search tree +is_bstree({}) => true. +is_bstree(BT@{Val,Left,Right}) => + is_bstree(Left,min_bstree(BT),Val), + is_bstree(Right,Val,max_bstree(BT)). + +is_bstree({},_,_) => true. +is_bstree({Val,Left,Right},Min,Max) => + Val @>= Min, Val @=< Max, + is_bstree(Left,Min,Val), + is_bstree(Right,Val,Max). + +min_bstree({Elm,{},_Right}) = Elm. +min_bstree({_Elm,Left,_Right}) = min_bstree(Left). + +max_bstree({Elm,_Left,{}}) = Elm. +max_bstree({_Elm,_Left,Right}) = max_bstree(Right). + +lookup_bstree({Elm,_,_},Elm) => true. +lookup_bstree({Val,Left,_},Elm), Elm < Val => + lookup_bstree(Left,Elm). +lookup_bstree({_,_,Right},Elm) => + lookup_bstree(Right,Elm). + +tree_inst1 = {6, {5, {4, {}, {}}, + {7, {}, {}}}, + {8, {3, {}, {}}, + {9, {}, {}}}}. + +tree_inst2 = {7, {5, {4, {}, {}}, + {6, {}, {}}}, + {8, {8, {}, {}}, + {9, {}, {}}}}. + +test_btree => + Tree1 = tree_inst1(), + println(inorder(Tree1)), + println(cond(is_bstree(Tree1),"a binary search tree","not a binary search tree")), + Tree2 = tree_inst2(), + println(inorder(Tree2)), + println(cond(is_bstree(Tree2),"a binary search tree","not a binary search tree")). + +% An example that uses data constructors +% A term in the form of $f(X) is a data constructor +divide_main => + Exp= $((((((((x/x)/x)/x)/x)/x)/x)/x)/x)/x, + d(Exp,x,D), + writeln(D). + +d(U+V,X,D) => + D = $DU+DV, + d(U,X,DU), + d(V,X,DV). +d(U-V,X,D) => + D = $DU-DV, + d(U,X,DU), + d(V,X,DV). +d(U*V,X,D) => + D = $DU*V+U*DV, + d(U,X,DU), + d(V,X,DV). +d(U/V,X,D) => + D = $(DU*V-U*DV)/(^(V,2)), + d(U,X,DU), + d(V,X,DV). +d(^(U,N),X,D) => + D = $DU*N*(^(U,N1)), + integer(N), + N1 = N-1, + d(U,X,DU). +d(-U,X,D) => + D = $-DU, + d(U,X,DU). +d(exp(U),X,D) => + D = $exp(U)*DU, + d(U,X,DU). +d(log(U),X,D) => + D = $DU/U, + d(U,X,DU). +d(X,X,D) => D=1. +d(_,_,D) => D=0. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% LOOPS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% another version for summing up a list +sum_list_imp(L) = Sum => + S = 0, + foreach (X in L) + S := S+X + end, + Sum = S. + +% using a loop to find the minimum and maximum of a list +min_max_ip([H|T], Min, Max) => + LMin = H, + LMax = H, + foreach (E in T) + LMin := min(LMin, E), + LMax := max(LMax, E) + end, + Min = LMin, + Max = LMax. + +% draw the Pascal triangle +pascal => + print("enter an integer:"), + N = read_int(), + foreach(I in 0..N) + Num := 1, + foreach(K in 1..I+1) + printf("%d ",Num), + Num := Num*(I-K+1) div K + end, + nl + end. + +% another solution +pascal2 => + print("enter an integer:"), + N = read_int(), + Row = [1], + foreach(_I in 1..N) + writeln(Row), + Row := next_row(Row) + end. + +private +next_row(Row)=Res => + NewRow = [1], Prev = 1, + foreach (K in tail(Row)) + NewRow := [Prev+K|NewRow], + Prev := K + end, + Res = [1|NewRow]. + +/* another definition, not so efficient because Row[I] takes O(I) time +private +next_row(Row) = [1] ++ [Row[I]+Row[I+1] : I in 1..Row.length-1] ++ [1]. +*/ + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% LIST COMPREHENSION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% a list comprehension inside another list comprehension +% Picat> L=list_of_lists(5) +% L = [[1],[1,2] [1,2,3],[1,2,3,4],[1,2,3,4,5]] +list_of_lists(N) = [[Y : Y in 1..X] : X in 1..N]. + +% another definition +another_list_of_lists(N) = [1..X : X in 1..N]. + +qsort([]) = []. +qsort([H|T]) = qsort([E : E in T, E =< H])++[H]++qsort([E : E in T, E>H]). + +power_set([]) = [[]]. +power_set([H|T]) = P1++P2 => + P1 = power_set(T), + P2 = [[H|S] : S in P1]. + +% generate permutations +perm([]) = [[]]. +perm(Lst) = [[E|P] : E in Lst, P in perm(Lst.delete(E))]. + +%another definition +perm1([]) = [[]]. +perm1([H|T]) = [insert(P,I,H) : P in Ps, I in 1..P.length+1] => Ps = perm1(T). + +% A*B=C +matrix_multi(A,B) = C => + C = new_array(A.length,B[1].length), + foreach(I in 1..A.length, J in 1..B[1].length) + C[I,J] = sum([A[I,K]*B[K,J] : K in 1..A[1].length]) + end. + +% Sieve of Eratosthenes +my_primes(N) = L => + A = new_array(N), + foreach(I in 2..floor(sqrt(N))) + if (var(A[I])) then + foreach(J in I**2..I..N) + A[J] = 0 + end + end + end, + L = [I : I in 2..N, var(A[I])]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% TABLING +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% mode-directed tabling +% finding shortest paths on a graph given by the relation edge/3. +table(+,+,-,min) +sp(X,Y,Path,W) ?=> + Path=[(X,Y)], + edge(X,Y,W). +sp(X,Y,Path,W) => + Path = [(X,Z)|PathR], + edge(X,Z,W1), + sp(Z,Y,PathR,W2), + W = W1+W2. + +index(+,-,-) (+,+,-) +edge(1,2,1). +edge(1,3,2). +edge(2,3,3). +edge(3,2,4). + +% binomial coefficient +bc(_N,0) = 1. +bc(N,N) = 1. +bc(N,1) = N. +bc(N,K) = bc(N-1,K-1) + bc(N-1,K). + +% computing the minimal editing distance of two given lists +table(+,+,min) +edit([],[],D) => D=0. +edit([X|Xs],[X|Ys],D) => % copy + edit(Xs,Ys,D). +edit(Xs,[_Y|Ys],D) ?=> % insert + edit(Xs,Ys,D1), + D = D1+1. +edit([_X|Xs],Ys,D) => % delete + edit(Xs,Ys,D1), + D = D1+1. + +% the Farmer's problem (use planner) +farmer => + S0 = [s,s,s,s], + plan(S0,Plan), + println(Plan). + +final([n,n,n,n]) => true. + +action([F,F,G,C],S1,Action,ActionCost) ?=> + Action = farmer_wolf, + ActionCost = 1, + opposite(F,F1), + S1 = [F1,F1,G,C], + not unsafe(S1). +action([F,W,F,C],S1,Action,ActionCost) ?=> + Action = farmer_goat, + ActionCost = 1, + opposite(F,F1), + S1 = [F1,W,F1,C], + not unsafe(S1). +action([F,W,G,F],S1,Action,ActionCost) ?=> + Action = farmer_cabbage, + ActionCost = 1, + opposite(F,F1), + S1 = [F1,W,G,F1], + not unsafe(S1). +action([F,W,G,C],S1,Action,ActionCost) => + Action = farmer_alone, + ActionCost = 1, + opposite(F,F1), + S1 = [F1,W,G,C], + not unsafe(S1). + +index (+,-) (-,+) +opposite(n,s). +opposite(s,n). + +unsafe([F,W,G,_C]),W == G,F !== W => true. +unsafe([F,_W,G,C]),G == C,F !== G => true. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% CONSTRAINT PROGRAMS (using cp) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% SEND+MORE=MONEY +sendmory => + Vars = [S,E,N,D,M,O,R,Y], % generate variables + Vars :: 0..9, + all_different(Vars), % generate constraints + S #!= 0, + M #!= 0, + 1000*S+100*E+10*N+D+1000*M+100*O+10*R+E + #= 10000*M+1000*O+100*N+10*E+Y, + solve(Vars), % search + writeln(Vars). + +% N-queens +queens(N) => + Qs = new_array(N), + Qs :: 1..N, + foreach (I in 1..N-1, J in I+1..N) + Qs[I] #!= Qs[J], + abs(Qs[I]-Qs[J]) #!= J-I + end, + solve([ff],Qs), + writeln(Qs). + +% another program for N-queens +queens2(N, Q) => + Q = new_list(N), + Q :: 1..N, + Q2 = [$Q[I]+I : I in 1..N], + Q3 = [$Q[I]-I : I in 1..N], + all_different(Q), + all_different(Q2), + all_different(Q3), + solve([ff],Q). + +% graph coloring (reuse edge/2 defined above) +color(NV,NC) => + A = new_array(NV), + A :: 1..NC, + foreach(I in 1..NV-1, J in I+1..NV) + if edge(I,J);edge(J,I) then + A[I] #!= A[J] + end + end, + solve(A), + writeln(A). + +% a 0-1 integer model for graph coloring +bcolor(NV,NC) => + A = new_array(NV,NC), + A :: [0,1], + foreach(I in 1..NV) + sum([A[I,K] : K in 1..NC]) #= 1 + end, + foreach(I in 1..NV-1, J in I+1..NV) + if edge(I,J);edge(J,I) then + foreach(K in 1..NC) + #~ A[I,K] #\/ #~ A[J,K] + end + end + end, + solve(A), + writeln(A). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% I/O +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Read a list of integers, stopping when 0 is read +read_array_main => + A = new_array(100), + Len = read_array(A), + foreach (I in 1..Len) + writeln(A[I]) + end. + +read_array(A) = Len => + Count = 0, + E = read_int(), % read from stdin + while (E != 0) + Count := Count+1, + A[Count] = E, + E := read_int() + end, + Len = Count. + +% copy a text file line-by-line +copy(IName,OName) => + IStream = open(IName), + OStream = open(OName,write), + Line = IStream.read_line(), + while (Line != end_of_file) + OStream.printf("%s%n",Line), + Line := IStream.read_line() + end, + close(IStream), + close(OStream). + +% Picat> output_students([$student("john","cs",3),$student("mary","math",4.0)]) +% john cs 3.00 +% mary math 4.00 +output_students(Students) => + foreach($student(Name,Major,GPA) in Students) + printf("%10s %10s %5.2f%n",Name,Major,to_real(GPA)) + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% HIGHER-ORDER (not recommended because of poor performance) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Picat> my_map(-,[1,2,3]) = L +% L = [-1,-2,-3] +% Picat> my_map(+,[1,2,3],[4,5,6]) = L +% L = [5,6,7] +% Picat> my_fold(+,0,[1,2,3]) = S +% S = 6 + +my_map(_F,[]) = []. +my_map(F,[X|Xs]) = [apply(F,X)|my_map(F,Xs)]. + +my_map(_F,[],[]) = []. +my_map(F,[X|Xs],[Y|Ys]) = [apply(F,X,Y)|my_map(F,Xs,Ys)]. + +my_fold(_F,Acc,[]) = Acc. +my_fold(F,Acc,[H|T]) = my_fold(F, apply(F,H,Acc),T). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% ACTION RULES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +test_ar => + watch_event(X), + watch_dom(X), + watch_dom_any(X), + watch_ins(X), + watch_bound(X), + X.post_event(event), + X.post_event_dom(dom), + X.post_event_ins(), + X.post_event_bound(), + X.post_event_any(any). + +watch_event(X), + {event(X,T)} +=> + writeln($event(T)). + +watch_dom(X), + {dom(X,T)} +=> + writeln($dom(T)). + +watch_dom_any(X), + {dom_any(X,T)} +=> + writeln($dom_any(T)). + +watch_ins(X), + {ins(X)} +=> + writeln($ins(X)). + +watch_bound(X), + {bound(X)} +=> + writeln($bound(X)). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% EXCEPTIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +catch_divided_by_zero => + catch(write(myd(4,0)),E, $handle(E)). + +myd(X,Y)=X/Y. + +handle(E) => + writeln(E), + throw(E). % just re-throw it + +/**** end file exs.pi ****/ -- cgit 1.4.1-2-gfad0