|
1 | 1 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2 | 2 | Presprover -- Prove formulas of Presburger arithmetic
|
3 |
| - Copyright (C) 2005, 2014, 2020 Markus Triska triska@metalevel.at |
| 3 | + Copyright (C) 2005-2023 Markus Triska (triska@metalevel.at) |
4 | 4 |
|
5 | 5 | This program is free software; you can redistribute it and/or modify
|
6 | 6 | it under the terms of the GNU General Public License as published by
|
|
64 | 64 | Some example queries and their results:
|
65 | 65 |
|
66 | 66 | ?- valid(x > 0).
|
67 |
| - false. |
| 67 | + %@ false. |
68 | 68 |
|
69 | 69 | ?- satisfiable(x > 0).
|
70 |
| - true. |
| 70 | + %@ true. |
71 | 71 |
|
72 | 72 | ?- valid(x >= 0).
|
73 |
| - true. |
| 73 | + %@ true. |
74 | 74 |
|
75 | 75 | ?- valid(exists(x, x > 0)).
|
76 |
| - true. |
| 76 | + %@ true. |
77 | 77 |
|
78 | 78 | ?- valid(forall(x, exists(y, 3*x + y > 2))).
|
79 |
| - true. |
| 79 | + %@ true. |
80 | 80 |
|
81 | 81 | ?- valid(2*y + 3*x = 30 /\ x = 0 ==> y = 15).
|
82 |
| - true. |
| 82 | + %@ true. |
83 | 83 |
|
84 | 84 | ?- valid(x = 3 \/ not(x=3)).
|
85 |
| - true. |
| 85 | + %@ true. |
86 | 86 |
|
87 | 87 | ?- valid(x = 5 ==> 2*x = 10).
|
88 |
| - true. |
| 88 | + %@ true. |
89 | 89 |
|
90 | 90 | ?- valid(y > 1 /\ x = 3 /\ x + y < 19 ==> x + 19 > y).
|
91 |
| - true. |
| 91 | + %@ true. |
92 | 92 |
|
93 | 93 | You can use solution/1 to print solutions of satisfiable formulas:
|
94 | 94 |
|
95 | 95 | ?- solution(x > 100_000 /\ y = 20).
|
96 |
| - x=114688. |
97 |
| - y=20. |
98 |
| - true . |
| 96 | + %@ x=114688. |
| 97 | + %@ y=20. |
| 98 | + %@ true |
| 99 | + %@ ; ... |
99 | 100 |
|
100 |
| - For logical variables, solutions are reported as variable bindings: |
| 101 | + For logic variables, solutions are reported as variable bindings: |
101 | 102 |
|
102 | 103 | ?- solution(X > 1_000_000_000 /\ Y > 10*X).
|
103 |
| - X = 1536870912, |
104 |
| - Y = 16106127360 ; |
105 |
| - X = 1536870912, |
106 |
| - Y = 16106128384 ; |
107 |
| - X = 1536870912, |
108 |
| - Y = 16106127872 ; |
109 |
| - etc. |
| 104 | + %@ X = 1536870912, Y = 16106127360 |
| 105 | + %@ ; X = 1536870912, Y = 16106128384 |
| 106 | + %@ ; X = 1536870912, Y = 16106127872 |
| 107 | + %@ ; X = 1536870912, Y = 16106127616 |
| 108 | + %@ ; X = 1536870912, Y = 16106127488 |
| 109 | + %@ ; ... |
110 | 110 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
111 | 111 |
|
112 | 112 | :- module(presprover, [
|
|
209 | 209 |
|
210 | 210 | saturate_eq([], _, AQ, AQ, D, D).
|
211 | 211 | saturate_eq([q(C)|QIterRest], Coeffs, AQ0, AQ, Delta0, Delta) :-
|
212 |
| - eq_mod2(Coeffs, C, Tuples), |
| 212 | + findall(Vs, eq_mod2(Coeffs, C, Vs), Tuples), |
213 | 213 | maplist(eq_tuple_newstate(Coeffs,C), Tuples, NewStates),
|
214 | 214 | maplist(state_tuple_delta(q(C)), NewStates, Tuples, NewDeltas),
|
215 | 215 | append(Delta0, NewDeltas, Delta1),
|
|
223 | 223 |
|
224 | 224 | factor_mod2(C0, C) :- C #= abs(C0 mod 2).
|
225 | 225 |
|
226 |
| -eq_mod2(Coeffs0, C0, Tuples) :- |
| 226 | +eq_mod2(Coeffs0, C0, Vs) :- |
227 | 227 | C #= abs(C0 mod 2),
|
228 | 228 | maplist(factor_mod2, Coeffs0, Coeffs),
|
229 | 229 | same_length(Coeffs, Vs),
|
230 | 230 | Vs ins 0..1,
|
231 | 231 | scalar_product(Coeffs, Vs, #=, S),
|
232 |
| - findall(Vs, (S mod 2 #= C, label(Vs)), Tuples). |
| 232 | + S mod 2 #= C, |
| 233 | + label(Vs). |
233 | 234 |
|
234 | 235 |
|
235 | 236 | eq_tuple_newstate(Coeffs, C, Tuple, q(D)) :-
|
|
249 | 250 | ineq_automaton(Coeffs, Sum, A) :-
|
250 | 251 | Q0 = q(Sum),
|
251 | 252 | same_length(Coeffs, Thetas),
|
252 |
| - Thetas ins 0..1, |
253 |
| - findall(Thetas, label(Thetas), Tuples), |
| 253 | + findall(Thetas, (Thetas ins 0..1,label(Thetas)), Tuples), |
254 | 254 | list_to_assoc([Q0-true], AQ0),
|
255 | 255 | saturate_ineq([Q0], Coeffs, Tuples, AQ0, AQ, [], Delta0),
|
256 | 256 | assoc_to_list(AQ, PQs),
|
|
523 | 523 | )
|
524 | 524 | ; Delta = [delta(_,Seq,_)|_],
|
525 | 525 | same_length(Seq, Bits),
|
526 |
| - Bits ins 0..1, |
527 |
| - findall(Bits, label(Bits), Binaries), |
| 526 | + findall(Bits, (Bits ins 0..1,label(Bits)), Binaries), |
528 | 527 | aut_complete(Binaries, DFA, aut(Qs,QFs,Q0,CompleteDelta)),
|
529 | 528 | list_delete(QFs, Qs, CFinals0),
|
530 | 529 | exclude(pseudo_final_state(QFs,CompleteDelta), CFinals0, CFinals1),
|
|
857 | 856 | We establish the definitive order of variables occurring in the
|
858 | 857 | formula, and thus of the tracks in the automaton, by using
|
859 | 858 | list_to_set/2 on the list of all variables. This is more reliable
|
860 |
| - than sort/2, since the relative (term-)order of logical variables |
| 859 | + than sort/2, since the relative (term-)order of logic variables |
861 | 860 | may change (for example, due to garbage collection or stack
|
862 | 861 | shifting) during program execution in future Scryer versions.
|
863 | 862 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
0 commit comments