1 /*
2 * This file is part of the Yices SMT Solver.
3 * Copyright (C) 2017 SRI International.
4 *
5 * Yices is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * Yices is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Yices. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <stdio.h>
20 #include <stdint.h>
21 #include <stdbool.h>
22 #include <inttypes.h>
23
24 #include "solvers/floyd_warshall/dl_vartable.h"
25
26 #ifdef MINGW
27
28 /*
29 * Need some version of random()
30 * rand() exists on mingw
31 */
random(void)32 static inline long int random(void) {
33 return rand();
34 }
35
36 #endif
37
38
39 /*
40 * Print a monomial (copied from term_printer.c)
41 * - variables v is converted to vertex id i-1
42 */
print_monomial(int32_t v,rational_t * coeff,bool first)43 static void print_monomial(int32_t v, rational_t *coeff, bool first) {
44 bool negative;
45 bool abs_one;
46
47 negative = q_is_neg(coeff);
48
49 if (negative) {
50 if (first) {
51 printf("- ");
52 } else {
53 printf(" - ");
54 }
55 abs_one = q_is_minus_one(coeff);
56 } else {
57 if (! first) {
58 printf(" + ");
59 }
60 abs_one = q_is_one(coeff);
61 }
62
63 if (v == const_idx) {
64 q_print_abs(stdout, coeff);
65 } else {
66 if (! abs_one) {
67 q_print_abs(stdout, coeff);
68 printf(" * ");
69 }
70 printf("x!%"PRId32, v-1);
71 }
72 }
73
74
75 /*
76 * Print monomial array a
77 * - n = number of monomials
78 */
print_polynomial(monomial_t * a,uint32_t n)79 static void print_polynomial(monomial_t *a, uint32_t n) {
80 uint32_t i;
81
82 if (n == 0) {
83 printf("0");
84 } else {
85 for (i=0; i<n; i++) {
86 print_monomial(a[i].var, &a[i].coeff, i == 0);
87 }
88 }
89 }
90
91
92 /*
93 * Print the content of a poly_buffer b
94 */
print_poly_buffer(poly_buffer_t * b)95 static void print_poly_buffer(poly_buffer_t *b) {
96 print_polynomial(b->mono, b->nterms);
97 }
98
99
100 /*
101 * Print a triple
102 */
print_dl_triple(dl_triple_t * t)103 static void print_dl_triple(dl_triple_t *t) {
104 bool space;
105
106 space = false;
107 if (t->target >= 0) {
108 printf("x!%"PRId32, t->target);
109 space = true;
110 }
111 if (t->source >= 0) {
112 if (space) printf(" ");
113 printf("- x!%"PRId32, t->source);
114 }
115
116
117 if (! space) {
118 q_print(stdout, &t->constant);
119 } else if (q_is_pos(&t->constant)) {
120 printf(" + ");
121 q_print(stdout, &t->constant);
122 } else if (q_is_neg(&t->constant)) {
123 printf(" - ");
124 q_print_abs(stdout, &t->constant);
125 }
126 }
127
128
129 /*
130 * Print table
131 */
print_dl_vartable(dl_vartable_t * table)132 static void print_dl_vartable(dl_vartable_t *table) {
133 uint32_t i, n;
134
135 printf("DL vartable %p\n", table);
136 printf(" nvars = %"PRIu32"\n", table->nvars);
137 printf(" size = %"PRIu32"\n", table->size);
138 n = table->nvars;
139 if (n == 0) {
140 printf(" empty table\n");
141 } else {
142 printf(" content:\n");
143 for (i=0; i<n; i++) {
144 printf(" var[%"PRIu32"]: ", i);
145 print_dl_triple(dl_var_triple(table, i));
146 printf("\n");
147 }
148 }
149 printf("\n");
150 }
151
152
153
154 /*
155 * Table of rationals for random tests
156 */
157 #define MAX_NUMERATOR (INT32_MAX>>1)
158 #define MIN_NUMERATOR (INT32_MIN>>1)
159 #define MAX_DENOMINATOR MAX_NUMERATOR
160
161 static int32_t num[12] = {
162 1, 1, -1, 0, 120, -120, -120, 120, INT32_MAX, INT32_MIN, MIN_NUMERATOR, MAX_NUMERATOR
163 };
164
165 static uint32_t den[12] = {
166 1, 10, 200, 72, 400, 999, INT32_MAX, MAX_DENOMINATOR, 1000, 120, 168, MAX_DENOMINATOR + 2
167 };
168
169
170 /*
171 * Assign a random rational to a
172 */
random_rational(rational_t * a)173 static void random_rational(rational_t *a) {
174 q_set_int32(a, num[random() % 12], den[random() %12]);
175 }
176
177 /*
178 * Create a random index between 0 and n-1
179 */
random_vertex(uint32_t n)180 static int32_t random_vertex(uint32_t n) {
181 assert(n > 0);
182 return (int32_t) (random() % n);
183 }
184
185
186 /*
187 * Test hash consing: add a random triple in table
188 */
test_random_triple(dl_vartable_t * table)189 static void test_random_triple(dl_vartable_t *table) {
190 dl_triple_t *check;
191 dl_triple_t test;
192 int32_t x, y;
193
194 test.target = random_vertex(6);
195 test.source = random_vertex(6);
196 q_init(&test.constant);
197 random_rational(&test.constant);
198 if (test.target == test.source) {
199 test.target = nil_vertex;
200 test.source = nil_vertex;
201 }
202
203 printf("Test: add triple ");
204 print_dl_triple(&test);
205 printf("\n");
206 x = get_dl_var(table, &test);
207 printf(" ---> var = %"PRId32"\n", x);
208
209 check = dl_var_triple(table, x);
210 if (check->target == test.target &&
211 check->source == test.source &&
212 q_eq(&check->constant, &test.constant)) {
213 printf("Checking descriptor: OK\n");
214 } else {
215 printf("BUG: invalid descriptor for var %"PRId32"\n", x);
216 fflush(stdout);
217 exit(1);
218 }
219
220 y = get_dl_var(table, &test);
221 if (x == y) {
222 printf("Checking hash-consing: OK\n");
223 } else {
224 printf("BUG: hash-consing fails for var %"PRId32"\n", x);
225 fflush(stdout);
226 exit(1);
227 }
228
229 printf("\n");
230 q_clear(&test.constant);
231 }
232
233
234 /*
235 * Test sum of triples for x and y
236 */
test_sum(dl_vartable_t * table,int32_t x,int32_t y,dl_triple_t * aux)237 static void test_sum(dl_vartable_t *table, int32_t x, int32_t y, dl_triple_t *aux) {
238 if (sum_dl_vars(table, x, y, aux)) {
239 printf("--> result = ");
240 print_dl_triple(aux);
241 printf("\n");
242 } else {
243 printf("--> result is not a triple\n");
244 }
245 }
246
247
248 /*
249 * Test difference of triples for x and y
250 */
test_diff(dl_vartable_t * table,int32_t x,int32_t y,dl_triple_t * aux)251 static void test_diff(dl_vartable_t *table, int32_t x, int32_t y, dl_triple_t *aux) {
252 if (diff_dl_vars(table, x, y, aux)) {
253 printf("--> result = ");
254 print_dl_triple(aux);
255 printf("\n");
256 } else {
257 printf("--> result is not a triple\n");
258 }
259 }
260
261
262 /*
263 * Test sum using a poly buffer
264 */
test_sum_buffer(dl_vartable_t * table,poly_buffer_t * buffer,int32_t x,int32_t y,dl_triple_t * aux)265 static void test_sum_buffer(dl_vartable_t *table, poly_buffer_t *buffer, int32_t x, int32_t y, dl_triple_t *aux) {
266 reset_poly_buffer(buffer);
267 add_dl_var_to_buffer(table, buffer, x);
268 add_dl_var_to_buffer(table, buffer, y);
269 normalize_poly_buffer(buffer);
270 printf("--> result = ");
271 print_poly_buffer(buffer);
272 printf("\n");
273 if (convert_poly_buffer_to_dl_triple(buffer, aux)) {
274 printf("--> convertible to triple: ");
275 print_dl_triple(aux);
276 printf("\n");
277 } else {
278 printf("--> not convertible to a triple\n");
279 }
280 if (rescale_poly_buffer_to_dl_triple(buffer, aux)) {
281 printf("--> convertible by rescaling to triple: ");
282 print_dl_triple(aux);
283 printf("\n");
284 } else {
285 printf("--> not convertible to a triple by rescaling\n");
286 }
287 }
288
289
test_diff_buffer(dl_vartable_t * table,poly_buffer_t * buffer,int32_t x,int32_t y,dl_triple_t * aux)290 static void test_diff_buffer(dl_vartable_t *table, poly_buffer_t *buffer, int32_t x, int32_t y, dl_triple_t *aux) {
291 reset_poly_buffer(buffer);
292 add_dl_var_to_buffer(table, buffer, x);
293 sub_dl_var_from_buffer(table, buffer, y);
294 normalize_poly_buffer(buffer);
295 printf("--> result = ");
296 print_poly_buffer(buffer);
297 printf("\n");
298 if (convert_poly_buffer_to_dl_triple(buffer, aux)) {
299 printf("--> convertible to triple: ");
300 print_dl_triple(aux);
301 printf("\n");
302 } else {
303 printf("--> not convertible to a triple\n");
304 }
305 if (rescale_poly_buffer_to_dl_triple(buffer, aux)) {
306 printf("--> convertible by rescaling to triple: ");
307 print_dl_triple(aux);
308 printf("\n");
309 } else {
310 printf("--> not convertible to a triple by rescaling\n");
311 }
312 }
313
314
315
316 /*
317 * Test sum and difference of triples
318 */
test_add_diff(dl_vartable_t * table)319 static void test_add_diff(dl_vartable_t *table) {
320 uint32_t i, j, n;
321 dl_triple_t test;
322 dl_triple_t test2;
323 poly_buffer_t buffer;
324
325 init_poly_buffer(&buffer);
326 q_init(&test.constant);
327 q_init(&test2.constant);
328
329 n = table->nvars;
330 for (i=0; i<n; i++) {
331 for (j=0; j<n; j++) {
332 printf("Testing sum: var!%"PRIu32" + var!%"PRIu32":\n", i, j);
333 printf("--> var!%"PRIu32" : ", i);
334 print_dl_triple(dl_var_triple(table, i));
335 printf("\n");
336 printf("--> var!%"PRIu32" : ", j);
337 print_dl_triple(dl_var_triple(table, j));
338 printf("\n");
339 test_sum_buffer(table, &buffer, i, j, &test2);
340 test_sum(table, i, j, &test);
341 printf("\n");
342
343 printf("Testing diff: var!%"PRIu32" - var!%"PRIu32":\n", i, j);
344 printf("--> var!%"PRIu32" : ", i);
345 print_dl_triple(dl_var_triple(table, i));
346 printf("\n");
347 printf("--> var!%"PRIu32" : ", j);
348 print_dl_triple(dl_var_triple(table, j));
349 printf("\n");
350 test_diff_buffer(table, &buffer, i, j, &test2);
351 test_diff(table, i, j, &test);
352 printf("\n");
353 }
354 }
355
356 q_clear(&test.constant);
357 q_clear(&test2.constant);
358 delete_poly_buffer(&buffer);
359 }
360
361
362
363 /*
364 * GLOBAL VARIABLE TABLE
365 */
366 static dl_vartable_t table;
367
main(void)368 int main(void) {
369 uint32_t i;
370
371 init_rationals();
372 init_dl_vartable(&table);
373 printf("Initial table\n");
374 print_dl_vartable(&table);
375
376 for (i=0; i<10; i++) {
377 test_random_triple(&table);
378 }
379 printf("After 10 additions\n");
380 print_dl_vartable(&table);
381
382 test_add_diff(&table);
383
384 printf("Push\n");
385 dl_vartable_push(&table);
386
387 for (i=0; i<10; i++) {
388 test_random_triple(&table);
389 }
390 printf("After 10 additions\n");
391 print_dl_vartable(&table);
392
393 test_add_diff(&table);
394
395 printf("Push\n");
396 dl_vartable_push(&table);
397
398 printf("Pop\n");
399 dl_vartable_pop(&table);
400 print_dl_vartable(&table);
401
402 printf("Pop\n");
403 dl_vartable_pop(&table);
404 print_dl_vartable(&table);
405
406 printf("Reset\n");
407 reset_dl_vartable(&table);
408 print_dl_vartable(&table);
409
410 printf("Push\n");
411 dl_vartable_push(&table);
412 for (i=0; i<100; i++) {
413 test_random_triple(&table);
414 }
415 printf("After 100 additions\n");
416 print_dl_vartable(&table);
417
418 test_add_diff(&table);
419
420 printf("Pop\n");
421 dl_vartable_pop(&table);
422 print_dl_vartable(&table);
423
424 printf("Reset\n");
425 reset_dl_vartable(&table);
426 print_dl_vartable(&table);
427
428 delete_dl_vartable(&table);
429 cleanup_rationals();
430
431 return 0;
432 }
433