1:- module(scasp_solve,
2 [ solve/4 3 ]). 4:- use_module(clp/call_stack). 5:- use_module(predicates). 6:- use_module(clp/disequality). 7:- use_module(clp/clpq). 8:- use_module(verbose). 9
10:- autoload(library(apply), [maplist/2, include/3]). 11:- autoload(library(assoc),
12 [get_assoc/3, empty_assoc/1, get_assoc/5, put_assoc/4]). 13:- autoload(library(lists), [append/3, member/2]). 14:- autoload(library(terms), [variant/2]). 15
16:- meta_predicate
17 solve(:, +, -, -). 18
21
22:- create_prolog_flag(scasp_no_fail_loop, false, [keep(true)]). 23:- create_prolog_flag(scasp_assume, false, [keep(true)]). 24:- create_prolog_flag(scasp_forall, all_c, [keep(true)]). 25:- create_prolog_flag(scasp_dcc, false, [keep(true)]). 26:- create_prolog_flag(scasp_trace_dcc, false, [keep(true)]). 27
34
35solve(M:Goals, StackIn, StackOut, Model) :-
36 stack_parents(StackIn, Parents),
37 stack_proved(StackIn, ProvedIn),
38 solve(Goals, M, Parents, ProvedIn, _ProvedOut, StackIn, StackOut, Model).
39
40solve([], _, _, Proved, Proved, StackIn, [[]|StackIn], []).
41solve([Goal|Goals], M, Parents, ProvedIn, ProvedOut, StackIn, StackOut, Model) :-
42 verbose(print_check_calls_calling(Goal, StackIn)),
43 check_goal(Goal, M, Parents, ProvedIn, ProvedMid, StackIn, StackMid, Modelx),
44 verbose(format('Check ~@\n', [print_goal(Goal)])),
45 Modelx = [AddGoal|JGoal],
46 verbose(format('Success ~@\n', [print_goal(Goal)])),
47 solve(Goals, M, Parents, ProvedMid, ProvedOut, StackMid, StackOut, Modelxs),
48 Modelxs = JGoals,
49 ( shown_predicate(M:Goal)
50 -> Model = [AddGoal, JGoal|JGoals]
51 ; Model = [JGoal|JGoals]
52 ).
53
54
55proved_relatives(not(Goal), Proved, Relatives) =>
56 proved_relatives(Goal, Proved, Relatives).
57proved_relatives(Goal, Proved, Relatives) =>
58 functor(Goal, Name, Arity),
59 get_assoc(Name/Arity, Proved, Relatives).
60
75
76check_goal(Goal, M, Parents, ProvedIn, ProvedOut, StackIn, StackOut, Model) :-
77 check_CHS(Goal, M, Parents, ProvedIn, StackIn, Check),
78 check_goal_(Check, Goal, M,
79 Parents, ProvedIn, ProvedOut, StackIn, StackOut,
80 Model),
81 ( current_prolog_flag(scasp_dcc, true),
82 ( Check == co_success
83 ; Check == cont
84 )
85 -> dynamic_consistency_check(Goal, M, StackIn)
86 ; true
87 ).
88
90check_goal_(co_success, Goal, _M,
91 _Parents, ProvedIn, ProvedOut, StackIn, StackOut,
92 [AddGoal]) :-
93 AddGoal = chs(Goal),
94 add_proved(AddGoal, ProvedIn, ProvedOut),
95 ( current_prolog_flag(scasp_assume, true)
96 -> mark_prev_goal(Goal, StackIn, StackMark),
97 StackOut = [[],AddGoal|StackMark]
98 ; StackOut = [[],AddGoal|StackIn]
99 ).
101check_goal_(proved, Goal, _M,
102 _Parents, ProvedIn, ProvedOut, StackIn, StackOut,
103 [AddGoal]) :-
104 AddGoal = proved(Goal),
105 add_proved(AddGoal, ProvedIn, ProvedOut),
106 StackOut = [[], proved(Goal)|StackIn].
108check_goal_(cont, Goal, M,
109 Parents, ProvedIn, ProvedOut, StackIn, StackOut,
110 Model) :-
111 solve_goal(Goal, M,
112 [Goal|Parents], ProvedIn, ProvedOut, StackIn, StackOut,
113 Model).
115check_goal_(co_failure, _Goal, _M,
116 _Parents, _ProvedIn, _ProvedOut, _StackIn, _StackOut,
117 _Model) :-
118 fail.
119
120mark_prev_goal(Goal, [I|In], [assume(Goal)|In]) :- Goal == I, !.
121mark_prev_goal(Goal, [I|In], [I|Mk]) :- mark_prev_goal(Goal,In,Mk).
122mark_prev_goal(_Goal,[],[]).
123
127
128dynamic_consistency_check(Goal, M, StackIn) :-
129 user_predicate(M:Goal),
130 ground(Goal),
131 M:pr_dcc_predicate(dcc(Goal), Body),
133 dynamic_consistency_eval(Body, M, StackIn),
134 !,
135 scasp_trace(scasp_trace_dcc, dcc_discard(Goal, Body)),
136 fail.
137dynamic_consistency_check(_, _, _).
138
139
140dynamic_consistency_eval([], _, _).
141dynamic_consistency_eval([SubGoal|Bs], M, StackIn) :-
142 dynamic_consistency_eval_(SubGoal, M, StackIn),
143 dynamic_consistency_eval(Bs, M, StackIn).
144
145dynamic_consistency_eval_(not(SubGoal), M, StackIn) :-
146 user_predicate(M:SubGoal), !,
147 member_stack(not(SubGoal), StackIn).
148dynamic_consistency_eval_(SubGoal, M, StackIn) :-
149 user_predicate(M:SubGoal), !,
150 member_stack(SubGoal, StackIn).
151dynamic_consistency_eval_(SubGoal, _, _) :-
152 solve_goal_builtin(SubGoal, _).
153
154
163
164solve_goal(Goal, M, Parents, ProvedIn, ProvedOut, StackIn, StackOut, GoalModel) :-
165 Goal = forall(_, _),
166 !,
167 ( current_prolog_flag(scasp_forall, prev)
168 -> solve_goal_forall(Goal, M,
169 Parents, ProvedIn, ProvedOut, [Goal|StackIn], StackOut,
170 Model)
171 ; solve_c_forall(Goal, M,
172 Parents, ProvedIn, ProvedOut, [Goal|StackIn], StackOut,
173 Model)
174 ),
175 GoalModel = [Goal|Model].
176solve_goal(Goal, _M,
177 _Parents, ProvedIn, ProvedOut, StackIn, [[], Goal|StackIn],
178 GoalModel) :-
179 Goal = not(is(V, Expresion)),
180 add_proved(Goal, ProvedIn, ProvedOut),
181 !,
182 NV is Expresion,
183 V .\=. NV,
184 GoalModel = [Goal].
185solve_goal(Goal, _, _, _, _, _, _, _) :-
186 Goal = not(true),
187 !,
188 fail.
189solve_goal(Goal, M, Parents, ProvedIn, ProvedOut, StackIn, StackOut, Model) :-
190 table_predicate(M:Goal),
191 !,
192 verbose(format('Solve the tabled goal ~p\n', [Goal])),
193 AttStackIn <~ stack([Goal|StackIn]),
194 solve_goal_table_predicate(Goal, M, Parents, ProvedIn, ProvedOut,
195 AttStackIn, AttStackOut, AttModel),
196 AttStackOut ~> stack(StackOut),
197 AttModel ~> model(Model).
198solve_goal(call(Goal), M, Parents, ProvedIn, ProvedOut, StackIn, StackOut,
199 [call(Goal)|Model]) :-
200 !,
201 solve_goal(Goal, M, Parents, ProvedIn, ProvedOut, StackIn, StackOut, Model).
202solve_goal(not(call(Goal)), M, Parents, ProvedIn, ProvedOut, StackIn, StackOut,
203 [not(call(Goal))|Model]) :-
204 !,
205 solve_goal(not(Goal), M, Parents, ProvedIn, ProvedOut, StackIn, StackOut,
206 Model).
207solve_goal(Goal, M, Parents, ProvedIn, ProvedOut, StackIn, StackOut,
208 [Goal|Model]) :-
209 Goal = findall(_, _, _),
210 !,
211 exec_findall(Goal, M, Parents, ProvedIn, ProvedOut, StackIn, StackOut, Model).
212solve_goal(not(Goal), M, Parents, ProvedIn, ProvedIn, StackIn, StackIn,
213 [not(Goal)]) :-
214 Goal = findall(_, _, _),
215 !,
216 exec_neg_findall(Goal, M, Parents, ProvedIn, StackIn).
217solve_goal(Goal, M, Parents, ProvedIn, ProvedOut, StackIn, StackOut, Model) :-
218 user_predicate(M:Goal),
219 !,
220 ( solve_goal_predicate(Goal, M, Parents, ProvedIn, ProvedOut,
221 StackIn, StackOut, Model)
222 *-> true
223 ; verbose(format(' FAIL~n')),
224 shown_predicate(M:Goal),
225 scasp_trace(scasp_trace_failures,
226 trace_failure(Goal, [Goal|StackIn])),
227 fail
228 ).
229solve_goal(Goal, _M, _Parents, ProvedIn, ProvedIn, StackIn, [[], Goal|StackIn],
230 Model) :-
231 solve_goal_builtin(Goal, Model).
232
233
234mkgoal(Goal, generated(_), Goal ) :- !.
235mkgoal(Goal, Origin , goal_origin(Goal, Origin)).
236
245
246solve_goal_forall(forall(Var, Goal), M,
247 Parents, ProvedIn, ProvedOut, StackIn, [[]|StackOut],
248 Model) :-
249 my_copy_term(Var, Goal, NewVar, NewGoal),
250 my_copy_term(Var, Goal, NewVar2, NewGoal2),
251 solve([NewGoal], M, Parents, ProvedIn, ProvedMid, StackIn, [[]|StackMid],
252 ModelMid),
253 verbose(format('\tSuccess solve ~@\n\t\t for the ~@\n',
254 [print_goal(NewGoal), print_goal(forall(Var, Goal))])),
255 check_unbound(NewVar, List),
256 ( List == ground
257 -> verbose(format('The var ~p is grounded so try with other clause\n',
258 [NewVar])),
259 fail
260 ; List == []
261 -> ProvedOut = ProvedMid,
262 StackOut = StackMid,
263 Model = ModelMid
264 ; List = clpq(NewVar3, Constraints)
265 -> findall(dual(NewVar3, ConDual),
266 dual_clpq(Constraints, ConDual),
267 DualList),
268 verbose(format('Executing ~@ with clpq ConstraintList = ~p\n',
269 [print_goal(Goal), DualList])),
270 exec_with_clpq_constraints(NewVar2, NewGoal2, M,
271 entry(NewVar3, []),
272 DualList,
273 Parents, ProvedMid, ProvedOut,
274 StackMid, StackOut, ModelList),
275 !,
276 append(ModelMid, ModelList, Model)
277 ; !, 278 verbose(format('Executing ~@ with clp_disequality list = ~p\n',
279 [print_goal(Goal), List])),
280 exec_with_neg_list(NewVar2, NewGoal2, M,
281 List, Parents, ProvedMid, ProvedOut,
282 StackMid, StackOut, ModelList),
283 284 285 append(ModelMid, ModelList, Model)
286 ).
287
288check_unbound(Var, ground) :-
289 ground(Var), !.
290check_unbound(Var, List) :-
291 get_neg_var(Var, List), !.
292check_unbound(Var, 'clpq'(NewVar, Constraints)) :-
293 dump_clpq_var([Var], [NewVar], Constraints),
294 Constraints \== [], !.
295check_unbound(Var, []) :-
296 var(Var), !.
297
298exec_with_clpq_constraints(_Var, _Goal, _M, _, [],
299 _Parents, ProvedIn, ProvedIn, StackIn, StackIn, []).
300exec_with_clpq_constraints(Var, Goal, M, entry(ConVar, ConEntry),
301 [dual(ConVar, ConDual)|Duals],
302 Parents, ProvedIn, ProvedOut, StackIn, StackOut,
303 Model) :-
304 my_copy_term(Var, [Goal, Parents, StackIn, ProvedIn],
305 Var01, [Goal01, Parents01, StackIn01, ProvedIn01]),
306 append(ConEntry, ConDual, Con),
307 my_copy_term(ConVar, Con, ConVar01, Con01),
308 my_copy_term(Var, Goal, Var02, Goal02),
309 my_copy_term(ConVar, ConEntry, ConVar02, ConEntry02),
310 Var01 = ConVar,
311 ( apply_clpq_constraints(Con)
312 -> verbose(format('Executing ~p with clpq_constrains ~p\n',
313 [Goal01, Con])),
314 solve([Goal01], M, Parents01, ProvedIn01, ProvedOut01, StackIn01, [[]|StackOut01], Model01),
315 verbose(format('Success executing ~p with constrains ~p\n',
316 [Goal01, Con])),
317 verbose(format('Check entails Var = ~p with const ~p and ~p\n',
318 [Var01, ConVar01, Con01])),
319 ( entails([Var01], ([ConVar01], Con01))
320 -> verbose(format('\tOK\n', [])),
321 StackOut02 = StackOut01,
322 Model03 = Model01
323 ; verbose(format('\tFail\n', [])),
324 dump_clpq_var([Var01], [ConVar01], ExitCon),
325 findall(dual(ConVar01, ConDual01),
326 dual_clpq(ExitCon, ConDual01),
327 DualList),
328 verbose(format('Executing ~p with clpq ConstraintList = ~p\n',
329 [Goal, DualList])),
330 exec_with_clpq_constraints(Var, Goal, M, entry(ConVar01, Con01),
331 DualList,
332 Parents01, ProvedOut01, ProvedOut02,
333 StackOut01, StackOut02, Model02),
334 append(Model01, Model02, Model03)
335 )
336 ; verbose(format('Skip execution of an already checked \c
337 constraint ~p (it is inconsitent with ~p)\n',
338 [ConDual, ConEntry])),
339 StackOut02 = StackIn01,
340 Model03 = []
341 ),
342 verbose(format('Executing ~p with clpq ConstraintList = ~p\n',
343 [Goal, Duals])),
344 exec_with_clpq_constraints(Var02, Goal02, M,
345 entry(ConVar02, ConEntry02),
346 Duals, Parents, ProvedOut02, ProvedOut,
347 StackOut02, StackOut, Model04),
348 append(Model03, Model04, Model).
349
350exec_with_neg_list(_, _, _, [], _, ProvedIn, ProvedIn, StackIn, StackIn, []).
351exec_with_neg_list(Var, Goal, M, [Value|Vs],
352 Parents, ProvedIn, ProvedOut, StackIn, StackOut,
353 Model) :-
354 my_copy_term(Var, [Goal, StackIn], NewVar, [NewGoal, NewStackIn]),
355 NewVar = Value,
356 verbose(format('Executing ~p with value ~p\n', [NewGoal, Value])),
357 solve([NewGoal], M, Parents,
358 ProvedIn, ProvedMid, NewStackIn, [[]|NewStackMid], ModelMid),
359 verbose(format('Success executing ~p with value ~p\n',
360 [NewGoal, Value])),
361 exec_with_neg_list(Var, Goal, M, Vs, Parents,
362 ProvedMid, ProvedOut, NewStackMid, StackOut, Models),
363 append(ModelMid, Models, Model).
364
370
371solve_goal_table_predicate(Goal, M, Parents, ProvedIn, ProvedOut, AttStackIn, AttStackOut, AttModel) :-
372 M:pr_rule(Goal, Body, _Origin),
373 AttStackIn ~> stack(StackIn),
374 solve(Body, M, Parents, ProvedIn, ProvedOut, StackIn, StackOut, Model),
375 AttStackOut <~ stack(StackOut),
376 AttModel <~ model([Goal|Model]).
377
383
384solve_goal_predicate(Goal, M, Parents, ProvedIn, ProvedOut, StackIn, StackOut,
385 GoalModel) :-
386 M:pr_rule(Goal, Body, Origin),
387 mkgoal(Goal, Origin, StackGoal),
388 solve(Body, M, Parents, ProvedIn, ProvedMid, [StackGoal|StackIn], StackOut, BodyModel),
389 add_proved(Goal, ProvedMid, ProvedOut),
390 GoalModel = [Goal|BodyModel].
391
395
396solve_goal_builtin(is(X, Exp), Model) :-
397 exec_goal(is(X, Exp)),
398 Model = [is(X, Exp)]. 399solve_goal_builtin(builtin(Goal), Model) :- !,
400 exec_goal(Goal),
401 Model = [builtin(Goal)].
402solve_goal_builtin(Goal, Model) :-
403 clp_builtin(Goal), !,
404 exec_goal(apply_clpq_constraints(Goal)),
405 Model = [Goal].
406solve_goal_builtin(Goal, Model) :-
407 clp_interval(Goal), !,
408 exec_goal(Goal),
409 Model = [Goal].
410solve_goal_builtin(not(Goal), _Model) :-
411 clp_interval(Goal), !,
412 scasp_warning(scasp(failure_calling_negation(Goal))),
413 fail.
414solve_goal_builtin(Goal, Model) :-
415 clp_builtin(Goal),
416 !,
417 exec_goal(apply_clpq_constraints(Goal)),
418 Model = [Goal].
419solve_goal_builtin(Goal, Model) :-
420 prolog_builtin(Goal), !,
421 exec_goal(Goal),
422 Model = [Goal].
424solve_goal_builtin(Goal, Model) :-
425 verbose(format('The predicate ~p is not user_defined / builtin\n', [Goal])),
426 ( Goal = not(_)
427 -> Model = [Goal] 428 ; fail 429 ).
430
431exec_goal(A \= B) :- !,
432 verbose(format('exec ~@\n', [print_goal(A \= B)])),
433 A .\=. B,
434 verbose(format('ok ~@\n', [print_goal(A \= B)])).
435exec_goal(Goal) :-
436 ( current_prolog_flag(scasp_verbose, true)
437 -> E = error(_,_),
438 verbose(format('exec goal ~@ \n', [print_goal(Goal)])),
439 catch(call(Goal), E, (print_message(warning, E), fail)),
440 verbose(format('ok goal ~@ \n', [print_goal(Goal)]))
441 ; catch(call(Goal), error(_,_), fail)
442 ).
443
447
450
451exec_findall(findall(Var, Call, List), M,
452 Parents, ProvedIn, ProvedOut, StackIn, StackOut, Model) :-
453 verbose(format('execution of findall(~p, ~p, _) \n', [Var, Call])),
454 findall(t(Var, S, Mdl), (
455 solve([Call], M, Parents, ProvedIn, _ProvedOut, StackIn, S0, Mdl),
456 append(S, StackIn, S0)
457 ), VSMList),
458 process_vsmlist(VSMList, List, SOut, Model),
459 append(SOut, [findall(Var, Call, List)|StackIn], StackOut),
460 stack_proved(StackOut, ProvedOut),
461 verbose(format('Result execution = ~p \n', [List])).
462
463process_vsmlist(VSMList, List, [[]|StackOut], Model) :-
464 process_vsmlist_(VSMList, List, StackOut, Model).
465
466process_vsmlist_([], [], [], []).
467process_vsmlist_([t(V, [[]|S], M)|Rs], [V|Vs], S1, M1) :-
468 process_vsmlist_(Rs, Vs, S0, M0),
469 append(S0, S, S1),
470 append(M, M0, M1).
471
473exec_neg_findall(Goal, _, _, _, _) :-
474 verbose(format('PENDING: execution of not ~p \n', [Goal])),
475 fail.
476
477
484
485:- det(check_CHS/6). 486
487check_CHS(Goal, M, Parents, Proved, I, Result) :-
488 ( user_predicate(M:Goal)
489 -> check_CHS_(Goal, M, Parents, Proved, I, Result)
490 ; Result = cont
491 ).
492
494check_CHS_(Goal, _M, _Parents, Proved, _Stack, proved) :-
495 ground(Goal),
496 proved_in_stack(Goal, Proved),
497 !.
499check_CHS_(Goal, _M, Parents, _Proved, _I, co_success) :-
500 check_parents(Goal, Parents, even),
501 !.
504check_CHS_(Goal, _M, Parents, Proved, _Stack, co_failure) :-
505 neg_in_stack(Goal, Parents, Proved), !,
506 verbose(format('Negation of the goal in the stack, failling (Goal = ~w)\n', [Goal])).
509check_CHS_(Goal, M, Parents, _Proved, _Stask, co_failure) :-
510 \+ table_predicate(M:Goal),
511 \+ current_prolog_flag(scasp_no_fail_loop, true),
512 \+ \+ (
513 check_parents(Goal, Parents, fail_pos(S)),
514 verbose(format('Positive loop, failing (Goal == ~w)\n', [Goal])),
515 scasp_warning(scasp_warn_pos_loops, pos_loop(fail, Goal, S))
516 ), !.
517check_CHS_(Goal, M, Parents, _Proved, _Stack, _Cont) :-
518 \+ table_predicate(M:Goal),
519 \+ \+ (
520 check_parents(Goal, Parents, pos(S)),
521 verbose(format('Positive loop, continuing (Goal = ~w)\n', [Goal])),
522 scasp_info(scasp_warn_pos_loops, pos_loop(continue, Goal, S))
523 ), fail.
525check_CHS_(Goal, _M, Parents, Proved, _Stack, cont) :-
526 ( ground(Goal)
527 -> constrained_neg_in_stack(Goal, Parents, Proved)
528 ; ground_neg_in_stack(Goal, Parents, Proved)
529 ).
530
536
537neg_in_stack(Goal, _Parents, Proved) :-
538 proved_relatives(Goal, Proved, Relatives),
539 member(Relative, Relatives),
540 is_negated_goal(Goal, Relative),
541 !.
542neg_in_stack(Goal, Parents, _) :-
543 member(Relative, Parents),
544 is_negated_goal(Goal, Relative),
545 !.
546
547is_negated_goal(Goal, Head) :-
548 ( Goal = not(G)
549 -> ( G == Head
550 -> true
551 ; G =@= Head
552 -> scasp_warning(co_failing_in_negated_loop(G, Head))
553 )
554 ; Head = not(NegGoal)
555 -> ( Goal == NegGoal
556 -> true
557 ; Goal =@= NegGoal
558 -> scasp_warning(co_failing_in_negated_loop(Goal, NegGoal))
559 )
560 ).
561
566
567:- det(ground_neg_in_stack/3). 568
569ground_neg_in_stack(Goal, Parents, Proved) :-
570 ( proved_relatives(Goal, Proved, Relatives)
571 -> maplist(ground_neg_in_stack(Goal), Relatives)
572 ; true
573 ),
574 maplist(ground_neg_in_stack(Goal), Parents).
575
576ground_neg_in_stack(TGoal, SGoal) :-
577 gn_match(TGoal, SGoal, Goal, NegGoal),
578 \+ Goal \= NegGoal,
579 verbose(format('\t\tCheck disequality of ~@ and ~@\n',
580 [print_goal(TGoal), print_goal(SGoal)])),
581 loop_term(Goal, NegGoal),
582 !.
583ground_neg_in_stack(_, _).
584
585gn_match(Goal, chs(not(NegGoal)), Goal, NegGoal) :- !.
586gn_match(not(Goal), chs(NegGoal), Goal, NegGoal) :- !.
587gn_match(not(Goal), NegGoal, Goal, NegGoal) :- !.
588
589
594
595:- det(constrained_neg_in_stack/3). 596
597constrained_neg_in_stack(Goal, Parents, Proved) :-
598 ( proved_relatives(Goal, Proved, Relatives)
599 -> maplist(contrained_neg(Goal), Relatives)
600 ; true
601 ),
602 maplist(contrained_neg(Goal), Parents).
603
604contrained_neg(not(Goal), NegGoal) :-
605 is_same_functor(Goal, NegGoal),
606 verbose(format('\t\tCheck if not(~@) is consistent with ~@\n',
607 [print_goal(Goal), print_goal(NegGoal)])), !,
608 loop_term(Goal, NegGoal),
609 !,
610 verbose(format('\t\tOK\n', [])).
611contrained_neg(Goal, not(NegGoal)) :-
612 is_same_functor(Goal, NegGoal),
613 verbose(format('\t\tCheck if not(~@) is consistent with ~@\n',
614 [print_goal(Goal), print_goal(NegGoal)])), !,
615 loop_term(Goal, NegGoal),
616 !,
617 verbose(format('\t\tOK\n', [])).
618contrained_neg(_,_).
619
620is_same_functor(Term1, Term2) :-
621 functor(Term1, Name, Arity, Type),
622 functor(Term2, Name, Arity, Type).
623
628
629proved_in_stack(Goal, Proved) :-
630 proved_relatives(Goal, Proved, Relatives),
631 member(Relative, Relatives),
632 ( Goal == Relative
633 ; Goal == chs(Relative)
634 ),
635 !.
636
641
642check_parents(not(Goal), Parents, Type) :-
643 !,
644 check_parents(not(Goal), 1, Parents, Type).
645check_parents(Goal, Parents, Type) :-
646 check_parents(Goal, 0, Parents, Type).
647
648check_parents(Goal, 0, [Parent|_Parents], Type) :-
649 ( \+ \+ type_loop_fail_pos(Goal, Parent)
650 -> Type = fail_pos(Parent)
651 ; \+ Goal \= Parent
652 -> Type = pos(Parent)
653 ),
654 !.
655check_parents(Goal, N, [Parent|Parents], Type) :-
656 ( even_loop(Goal, Parent, N)
657 -> Type = even
658 ; Goal \== Parent
659 -> ( Parent = not(_)
660 -> NewN is N + 1,
661 check_parents(Goal, NewN, Parents, Type)
662 ; check_parents(Goal, N, Parents, Type)
663 )
664 ).
665
666even_loop(not(Goal), not(Parent), _) :-
667 Goal =@= Parent,
668 !,
669 Goal = Parent.
670even_loop(Goal, Parent, N) :-
671 Goal \= not(_),
672 Goal == Parent,
673 N > 0,
674 0 =:= mod(N, 2).
675
676type_loop_fail_pos(Goal, S) :-
677 Goal == S, !.
678type_loop_fail_pos(Goal, S) :-
679 variant(Goal, S), !,
680 scasp_warning(variant_loop(Goal, S)).
681type_loop_fail_pos(Goal, S) :-
682 entail_terms(Goal, S),
683 scasp_warning(subsumed_loop(Goal, S)).
684
689
690:- det(stack_parents/2). 691stack_parents(Stack, Parents) :-
692 stack_parents(Stack, 0, Parents).
693
694stack_parents([], _, []).
695stack_parents([[]|T], N, Parents) :-
696 !,
697 N1 is N-1,
698 stack_parents(T, N1, Parents).
699stack_parents([_|T], N, Parents) :-
700 N < 0,
701 !,
702 N1 is N+1,
703 stack_parents(T, N1, Parents).
704stack_parents([goal_origin(H, _)|T], N, [H|TP]) :-
705 !,
706 stack_parents(T, N, TP).
707stack_parents([H|T], N, [H|TP]) :-
708 stack_parents(T, N, TP).
709
719
720:- det(stack_proved/2). 721
722stack_proved(Stack, Proved) :-
723 empty_assoc(Proved0),
724 stack_proved(Stack, 0, -1, Proved0, Proved).
725
726stack_proved([], _, _, Proved, Proved).
727stack_proved([Top|Ss], Intervening, MaxInter, Proved0, Proved) :-
728 ( Top == []
729 -> NewInter is Intervening - 1,
730 stack_proved(Ss, NewInter, MaxInter, Proved0, Proved)
731 ; Intervening > MaxInter
732 -> NewMaxInter is max(MaxInter, Intervening),
733 NewInter is Intervening + 1,
734 stack_proved(Ss, NewInter, NewMaxInter, Proved0, Proved)
735 ; add_proved(Top, Proved0, Proved1),
736 stack_proved(Ss, Intervening, MaxInter, Proved1, Proved)
737 ).
738
739add_proved(goal_origin(Goal, _), Assoc0, Assoc) =>
740 add_proved(Goal, Goal, Assoc0, Assoc).
741add_proved(Goal, Assoc0, Assoc) =>
742 add_proved(Goal, Goal, Assoc0, Assoc).
743
744add_proved(not(Term), Goal, Assoc0, Assoc) =>
745 add_proved(Term, Goal, Assoc0, Assoc).
746add_proved(chs(Term), Goal, Assoc0, Assoc) =>
747 add_proved(Term, Goal, Assoc0, Assoc).
748add_proved(forall(_,_), _Goal, Assoc0, Assoc) =>
749 Assoc = Assoc0.
750add_proved(Term, Goal, Assoc0, Assoc) =>
751 functor(Term, Name, Arity),
752 ( get_assoc(Name/Arity, Assoc0, List, Assoc, [Goal|List])
753 -> true
754 ; put_assoc(Name/Arity, Assoc0, [Goal], Assoc)
755 ).
756
768
769solve_c_forall(Forall, M, Parents, ProvedIn, ProvedOut, StackIn, [[]|StackOut],
770 Model) :-
771 collect_vars(Forall, c_forall(Vars0, Goal0)), 772
773 verbose(format('\nc_forall(~p,\t~p)\n\n',[Vars0, Goal0])),
774
775 my_copy_vars(Vars0, Goal0, Vars1, Goal1), 776 my_diff_term(Goal1, Vars1, OtherVars),
777 Initial_Const = [], 778 ( current_prolog_flag(scasp_forall, all)
779 -> solve_var_forall_(Goal1, M, Parents, ProvedIn, ProvedOut,
780 entry(Vars1, Initial_Const),
781 dual(Vars1, [Initial_Const]),
782 OtherVars, StackIn, StackOut, Model)
783 ; solve_other_forall(Goal1, M, Parents, ProvedIn, ProvedOut,
784 entry(Vars1, Initial_Const),
785 dual(Vars1, [Initial_Const]),
786 OtherVars, StackIn, StackOut, Model)
787 ).
788
789solve_other_forall(Goal, M, Parents, ProvedIn, ProvedOutExit,
790 entry(Vars, Initial_Const),
791 dual(Vars, [Initial_Const]),
792 OtherVars, StackIn, StackOutExit, ModelExit) :-
793 append(Vars,OtherVars,AllVars),
794 my_copy_vars(AllVars, [Goal, Parents, ProvedIn, StackIn, OtherVars, Vars],
795 _AllVars1, [Goal1, Parents1, ProvedIn1, StackIn1, OtherVars1, Vars1]),
796 my_copy_vars(AllVars, [Goal, Parents, ProvedIn, StackIn, OtherVars, Vars],
797 _AllVars2, [Goal2, Parents2, ProvedIn2, StackIn2, OtherVars2, Vars2]),
798
799 verbose(format("solve other forall:\n\c
800 \t Goal \t~p\n\c
801 \t Vars1 \t~p\n\c
802 \t OtherVars \t~p\n\c
803 \t StackIn \t~p\n\n",
804 [Goal,Vars1,OtherVars,StackIn])),
805
806 807 dump_constraint(OtherVars, OtherVars1, Dump, []-[], Pending-Pending1), !,
808 clpqr_dump_constraints(Pending, Pending1, CLP),
809 append(CLP, Dump, Constraints1),
810 my_copy_vars(OtherVars1, Constraints1, OtherVars2, Constraints2),
811
812 verbose(format("solve other forall:\n\c
813 \t OtherVars1 \t~p\n\c
814 \t OtherVars2 \t~p\n\c
815 \t Constraints1 \t~p\n\c
816 \t Constraints2 \t~p\n\n",
817 [OtherVars, OtherVars1, Constraints1, Constraints2])),
818
819 apply_const_store(Constraints1),
820 !,
821
822 solve_var_forall_(Goal1, M, Parents1, ProvedIn1, ProvedOut,
823 entry(Vars1, Initial_Const),
824 dual(Vars1, [Initial_Const]), OtherVars1,
825 StackIn1, StackOut, Model),
826 !,
827 ( OtherVars = OtherVars1,
828 StackOutExit = StackOut,
829 ModelExit = Model,
830 ProvedOutExit = ProvedOut
831 ; \+ ground(OtherVars),
832 apply_const_store(Constraints2),
833 834 dump_constraint(OtherVars1, OtherVars2, Dump1, []-[], Pend-Pend1), !,
835 clpqr_dump_constraints(Pend, Pend1, CLP1),
836 append(CLP1, Dump1, AnsConstraints2),
837 make_duals(AnsConstraints2, Duals),
838 member(Dual, Duals),
839 apply_const_store(Dual),
840 solve_other_forall(Goal2, M, Parents2, ProvedIn2, ProvedOutExit,
841 entry(Vars2, Initial_Const),
842 dual(Vars2, [Initial_Const]),
843 OtherVars2, StackIn2, StackOutExit, ModelExit), !,
844 OtherVars = OtherVars2
845 ).
846
862
863solve_var_forall_(_Goal, _M, _Parents, Proved, Proved, _, dual(_, []),
864 _OtherVars, StackIn, StackIn, []) :- !.
865solve_var_forall_(Goal, M, Parents, ProvedIn, ProvedOut,
866 entry(C_Vars, Prev_Store),
867 dual(C_Vars, [C_St|C_Stores]),
868 OtherVars, StackIn, StackOut, Model) :-
869 verbose(format("solve forall:\n\c
870 \tPrev_Store \t~p\n\c
871 \tC_St \t~p\n\c
872 \tC_Stores \t~p\n\c
873 \tStackIn \t~p\n\n",
874 [Prev_Store,C_St,C_Stores,StackIn])),
875
876 my_copy_vars(C_Vars, [Goal, Prev_Store, C_St], C_Vars1, [Goal1, Prev_Store1, C_St1]),
877 my_copy_vars(C_Vars, [Goal, Prev_Store, C_Stores], C_Vars2, [Goal2, Prev_Store2, C_Stores2]),
878
879 apply_const_store(Prev_Store),
880 ( 881 apply_const_store(C_St) 882 -> solve([Goal], M, Parents, ProvedIn, ProvedOut1, StackIn, [[]|StackOut1], Model1),
883 find_duals(C_Vars, C_Vars1, OtherVars, Duals), 884 verbose(format('Duals = \t ~p\n',[Duals])),
885 append_set(Prev_Store1, C_St1, Current_Store1),
886 solve_var_forall_(Goal1, M, Parents, ProvedOut1, ProvedOut2,
887 entry(C_Vars1, Current_Store1),
888 dual(C_Vars1, Duals),
889 OtherVars, StackOut1, StackOut2, Model2),
890 append(Model1,Model2,Model3)
891 ; verbose(format('Entail: Fail applying \t ~@\n',
892 [print_goal(C_St)])),
893 894 ProvedOut2 = ProvedIn,
895 StackOut2 = StackIn,
896 Model3 = []
897 ),
898 solve_var_forall_(Goal2, M, Parents, ProvedOut2, ProvedOut,
899 entry(C_Vars2, Prev_Store2),
900 dual(C_Vars2, C_Stores2),
901 OtherVars, StackOut2, StackOut, Model4),
902 append(Model3, Model4, Model).
903
904append_set([],X,X):- !.
905append_set([A|As],Bs,Cs) :-
906 \+ \+ memberchk_oc(A, Bs),
907 !,
908 append_set(As,Bs,Cs).
909append_set([A|As],Bs,[A|Cs]) :-
910 append_set(As,Bs,Cs).
911
912memberchk_oc(Term, [H|T]) :-
913 ( unify_with_occurs_check(Term, H)
914 -> true
915 ; memberchk_oc(Term, T)
916 ).
917
918apply_const_store([]) :- !.
919apply_const_store([C|Cs]) :-
920 apply_constraint(C),
921 apply_const_store(Cs).
922
923apply_constraint(A \= B) =>
924 A .\=. B.
925apply_constraint(A = B) =>
926 A = B.
927apply_constraint(CLPConstraint) =>
928 apply_clpq_constraints(CLPConstraint).
929
944
945find_duals(C_Vars, C_Vars1, OtherVars, Duals) :-
946 947 dump_constraint(C_Vars, C_Vars1, Dump, []-[], Pending-Pending1), !,
948 clp_vars_in(OtherVars, OtherCLPVars), 949 append(Pending, OtherCLPVars, CLPVars),
950 append(Pending1, OtherCLPVars, CLPVars1),
951 clpqr_dump_constraints(CLPVars, CLPVars1, CLP),
952 append(CLP, Dump, Constraints),
953 make_duals(Constraints,Duals), !.
954
955make_duals(Ls,Ds) :-
956 make_duals_([],Ls,[],Ds).
957
958make_duals_(_,[],Ds,Ds).
959make_duals_(Prev,[A|As],D0,Ds) :-
960 append(Prev,[A],Prev1),
961 make_duals_(Prev1,As,D0,D1),
962 dual(A,Duals_A),
963 combine(Duals_A,Prev,As,Ls),
964 append(Ls,D1,Ds).
965
966combine([A],Prev,Post,[Rs]) :-
967 append(Prev,[A|Post],Rs).
968combine([A,B|As],Prev,Post,[RA|RAs]) :-
969 append(Prev,[A|Post],RA),
970 combine([B|As],Prev,Post,RAs).
971
972:- det(dual/2). 973
974dual(#=(A,B), [#<(A,B), #>(A,B)]).
975dual(#<(A,B), [#>=(A,B)]).
976dual(#>(A,B), [#=<(A,B)]).
977dual(#=<(A,B), [#>(A,B)]).
978dual(#>=(A,B), [#<(A,B)]).
979
980dual(=(A,B), [\=(A,B)]).
981dual(\=(A,B), [=(A,B)]).
982
983
990
991:- det(dump_constraint/5). 992dump_constraint([], [], [], Pending, Pending).
993dump_constraint([V|Vs], [V1|V1s], [V1 = V | Vs_Dump], P0, P1) :-
994 ground(V), !,
995 dump_constraint(Vs, V1s, Vs_Dump, P0, P1).
996dump_constraint([V|Vs], [V1|V1s], Rs_Dump, P0, P1) :-
997 get_neg_var(V, List),
998 List \== [], !,
999 dump_neg_list(V1, List, V_Dump),
1000 dump_constraint(Vs, V1s, Vs_Dump, P0, P1),
1001 append(V_Dump, Vs_Dump, Rs_Dump).
1002dump_constraint([V|Vs], [V1|V1s], Vs_Dump, PV-PV1, P1) :-
1003 dump_constraint(Vs, V1s, Vs_Dump, [V|PV]-[V1|PV1], P1).
1004
1005dump_neg_list(_,[],[]) :- !.
1006dump_neg_list(V,[L|Ls],[V \= L|Rs]) :- dump_neg_list(V,Ls,Rs).
1007
1008clp_vars_in(Vars, ClpVars) :-
1009 include(is_clpq_var, Vars, ClpVars).
1010
1014
1015collect_vars(Forall, c_forall(Vars, Goal)) :-
1016 collect_vars_(Forall, [], Vars, Goal).
1017
1018collect_vars_(forall(Var, Goal), Vars, [Var|Vars], Goal) :-
1019 Goal \= forall(_, _), !.
1020collect_vars_(forall(Var, Forall), V0, V1, Goal) :-
1021 collect_vars_(Forall, [Var|V0], V1, Goal).
1022
1023
1024 1027
1033
1034:- if(current_predicate(copy_term_nat/4)). 1035
1036my_copy_term(Var0, Term0, Var, Term) :-
1037 copy_term_nat(Var0, Term0, Var, Term).
1038
1039my_copy_vars(Vars0, Term0, Vars, Term) :-
1040 copy_term_nat(Vars0, Term0, Vars, Term).
1041
1042:- else. 1043
1044my_copy_term(Var0, Term0, Var, Term) :-
1045 term_variables(Term0, AllVars),
1046 delete_var(AllVars, Var0, Share0),
1047 copy_term_nat(t(Var0,Share0,Term0), t(Var,Share,Term)),
1048 Share = Share0.
1049
1050delete_var([], _, []).
1051delete_var([H|T0], V, List) :-
1052 ( H == V
1053 -> List = T0
1054 ; List = [H|T],
1055 delete_var(T0, V, T)
1056 ).
1057
1058my_copy_vars(Vars0, Term0, Vars, Term) :-
1059 term_variables(Term0, AllVars),
1060 sort(AllVars, AllVarsSorted),
1061 sort(Vars0, Vars0Sorted),
1062 ord_subtract(AllVarsSorted, Vars0Sorted, Share0),
1063 copy_term_nat(t(Vars0,Share0,Term0), t(Vars,Share,Term)),
1064 Share = Share0.
1065
1066:- endif. 1067
1071
1072my_diff_term(Term, Vars, Others) :-
1073 term_variables(Term, Set),
1074 diff_vars(Set, Vars, Others).
1075
1076diff_vars([], _, []).
1077diff_vars([H|T0], Vars, List) :-
1078 ( member_var(Vars, H)
1079 -> diff_vars(T0, Vars, List)
1080 ; List = [H|T],
1081 diff_vars(T0, Vars, T)
1082 ).
1083
1084member_var(Vars, Var) :-
1085 member(V, Vars),
1086 Var == V,
1087 !.
1088
1089member_stack(Goal, Stack) :- member(goal_origin(Goal, _), Stack).
1090member_stack(Goal, Stack) :- member(Goal, Stack)