YAP 7.1.0
coinduction.yap
Go to the documentation of this file.
1/*************************************************************************
2* *
3* YAP Prolog *
4* *
5* Yap Prolog was developed at NCCUP - Universidade do Porto *
6* *
7* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
8* *
9**************************************************************************
10* *
11* File: coinduction.yap *
12* Last rev: 8/2/88 *
13* mods: *
14* comments: coinduction support for Prolog *
15* *
16*************************************************************************/
17
18/**
19 * @file coinduction.yap
20 * @author VITOR SANTOS COSTA <vsc@VITORs-MBP.lan>, Arvin Bansal,
21 * @author Includes nice extensions from Jan Wielemaker (from the SWI version). *
22 *
23 * @date Tue Nov 17 14:55:02 2015
24 *
25 * @brief Co-inductive execution
26 *
27 *
28*/
29
30/**
31 * @defgroup coinduction Co-Logic Programming
32 * @ingroup YAPLibrary
33 * @{
34 *
35 */
36
37% :- yap_flag(unknown,error).
38% :- style_check(all).
39
40
41:- module(coinduction,
42 [ (coinductive)/1,
43 op(1150, fx, (coinductive))
44 ]).
45
46:- use_module(library(error)).
47
48/**
49
50@addtogroup coinduction Co-induction
51@ingroup YAPLibrary
52@{
53
54
55This simple module implements the directive coinductive/1 as described
56in "Co-Logic Programming: Extending Logic Programming with Coinduction"
57by Luke Somin et al. The idea behind coinduction is that a goal succeeds
58if it unifies to a parent goal. This enables some interesting programs,
59notably on infinite trees (cyclic terms).
60
61```
62 :- use_module(library(coinduction)).
63
64 :- coinductive stream/1.
65 stream([H|T]) :- i(H), stream(T).
66
67 % inductive
68 i(0).
69 i(s(N)) :- i(N).
70
71 ?- X=[s(s(A))|X], stream(X).
72 X= [s(s(A))|X], stream(X).
73 A = 0,
74 X = [s(s(0)),**]
75```
76
77This predicate is true for any cyclic list containing only 1-s,
78regardless of the cycle-length.
79
80`@bug` Programs mixing normal predicates and coinductive predicates must
81 be _stratified_. The theory does not apply to normal Prolog calling
82 coinductive predicates, calling normal Prolog predicates, etc.
83
84 Stratification is not checked or enforced in any other way and thus
85 left as a responsibility to the user.
86`@see` "Co-Logic Programming: Extending Logic Programming with Coinduction"
87 by Luke Somin et al.
88
89*/
90
91:- meta_predicate coinductive(:).
92
93:- dynamic coinductive/3.
94
95
96%-----------------------------------------------------
97
98coinductive(Spec) :-
99 var(Spec),
100 var,
101 throw(error(instantiation_error,coinductive(Spec))).
102coinductive(Module:Spec) :-
103 coinductive_declaration(Spec, Module, coinductive(Module:Spec)).
104coinductive(Spec) :-
105 prolog_load_context(module, Module),
106 coinductive_declaration(Spec, Module, coinductive(Spec)).
107
108coinductive_declaration(Spec, _M, G) :-
109 var(Spec),
110 var,
111 throw(error(instantiation_error,G)).
112coinductive_declaration((A,B), M, G) :- coinductive_declaration,
113 coinductive_declaration(A, M, G),
114 coinductive_declaration(B, M, G).
115coinductive_declaration(M:Spec, _, G) :- coinductive_declaration,
116 coinductive_declaration(Spec, M, G).
117coinductive_declaration(Spec, M, _G) :-
118 valid_pi(Spec, F, N),
119 functor(S,F,N),
120 atomic_concat(['__coinductive__',F,'/',N],NF),
121 functor(NS,NF,N),
122 match_args(N,S,NS),
123 atomic_concat(['__stack_',M,':',F,'/',N],SF),
124 nb_setval(SF, _),
125 assert((M:S :-
126 b_getval(SF,L),
127 coinduction:in_stack(S, L, End),
128 (
129 nonvar(End)
130 ->
131 true
132 ;
133 End = [S|_],
134 M:NS)
135 )
136 ),
137 assert(coinduction:coinductive(S,M,NS)).
138
139valid_pi(Name/Arity, Name, Arity) :-
140 must_be(atom, Name),
141 must_be(integer, Arity).
142
143match_args(0,_,_) :- match_args.
144match_args(I,S1,S2) :-
145 arg(I,S1,A),
146 arg(I,S2,A),
147 I1 is I-1,
148 match_args(I1,S1,S2).
149
150%-----------------------------------------------------
151
152co_term_expansion((M:H :- B), _, (M:NH :- B)) :- co_term_expansion,
153 co_term_expansion((H :- B), M, (NH :- B)).
154co_term_expansion((H :- B), M, (NH :- B)) :- co_term_expansion,
155 coinductive(H, M, NH), coinductive.
156co_term_expansion(H, M, NH) :-
157 coinductive(H, M, NH), coinductive.
158
159/** user:term_expansion(+M:Cl,-M:NCl )
160
161rule preprocessor
162*/
163coinductive:term_expansion(M:Cl,M:NCl ) :- term_expansion,
164 co_term_expansion(Cl, M, NCl).
165
166co_term_expansion:term_expansion(G, NG) :-
167 prolog_load_context(module, Module),
168 co_term_expansion(G, Module, NG).
169
170
171%-----------------------------------------------------
172
173in_stack(_, V, V) :- var(V), var.
174in_stack(G, [G|_], [G|_]) :- in_stack.
175in_stack(G, [_|T], End) :- in_stack(G, T, End).
176
177writeG_val(G_var) :-
178 b_getval(G_var, G_val),
179 write(G_var), write(' ==> '), write(G_val), write.
180
181%-----------------------------------------------------
182
183/**
184
185 Some examples from Coinductive Logic Programming and its Applications by Gopal Gupta et al, ICLP 97
186
187```
188:- coinductive stream/1.
189stream([H|T]) :- i(H), stream(T).
190
191% inductive
192i(0).
193i(s(N)) :- i(N).
194
195 % Are there infinitely many "occurrences" of arg1 in arg2?
196 :- coinductive comember/2.
197
198 comember(X, L) :-
199 drop(X, L, L1),
200 comember(X, L1).
201
202 % Drop some prefix of arg2 upto an "occurrence" of arg1 from arg2,
203 % yielding arg3.
204 % ("Occurrence" of X = something unifiable with X.)
205 %:- table(drop/3). % not working; needs tabling supporting cyclic terms!
206 drop(H, [H| T], T).
207 drop(H, [_| T], T1) :-
208 drop(H, T, T1).
209
210
211% X = [1, 2, 3| X], comember(E, X).
212
213 user:p(E) :-
214 X = [1, 2, 3| X],
215 comember(E, X),
216 format('~w~n',[E]),
217 get_code(_),
218 fail.
219
220
221
222```
223*/
224
225/**
226@}
227*/
228
229
throw(+ Ball)
assert(+ C)
nb_setval(+ Name,+ Value)
use_module( +Files )
term_expansion( T,- X)
b_getval(+ Name, - Value)
prolog_load_context(? Key, ? Value)
Definition: consult.yap:479
arg(+ N,+ T, A)
functor( T, F, N)
var( T)