@@ -429,6 +429,29 @@ void mcarith_check_atom_size(mcarith_solver_t *solver) {
429429static
430430void rba_buffer_add_mono_mcarithvar (mcarith_solver_t * solver , rba_buffer_t * b , rational_t * a , thvar_t v );
431431
432+ /**
433+ * This creates a term from a polynomial while taking care not to
434+ * introduce a polynomial from a constant.
435+ */
436+ static
437+ term_t mcarith_poly (term_table_t * terms , rba_buffer_t * b ) {
438+
439+ if (b -> nterms == 0 ) {
440+ rational_t q ;
441+ q_init (& q );
442+ return arith_constant (terms , & q );
443+ }
444+
445+ if (b -> nterms == 1 ) {
446+ mono_t * m = b -> mono + b -> root ;
447+ if (m -> prod == empty_pp ) {
448+ return arith_constant (terms , & m -> coeff );
449+ }
450+ }
451+
452+ return arith_poly (terms , b );
453+ }
454+
432455static
433456term_t get_term (mcarith_solver_t * solver , thvar_t v ) {
434457 arith_vartable_t * table ;
@@ -469,7 +492,7 @@ term_t get_term(mcarith_solver_t* solver, thvar_t v) {
469492 rba_buffer_add_mono_mcarithvar (solver , & b , r , v );
470493 }
471494 }
472- t = arith_poly (terms , & b );
495+ t = mcarith_poly (terms , & b );
473496 }
474497 break ;
475498 case AVARTAG_KIND_PPROD :
@@ -648,8 +671,6 @@ term_t get_atom(mcarith_solver_t* solver, int32_t atom_index) {
648671 term_t v ;
649672 rational_t * bnd ;
650673 rba_buffer_t b ;
651- term_t polyTerm ;
652-
653674
654675 mcarith_check_atom_size (solver );
655676
@@ -671,26 +692,31 @@ term_t get_atom(mcarith_solver_t* solver, int32_t atom_index) {
671692 // Assert v-b >= 0
672693 case GE_ATM : {
673694 if (q_is_zero (bnd )) {
674- polyTerm = get_term (solver , var_of_atom (ap ));
695+ term_t polyTerm ;
696+ polyTerm = get_term (solver , v );
697+ result = arith_geq_atom (terms , polyTerm );
675698 } else {
699+ term_t polyTerm ;
676700 // Create buffer b = v - bnd
677701 init_rba_buffer (& b , mcarith_solver_pprods (solver ));
678702 rba_buffer_add_mcarithvar (solver , & b , v );
679703 rba_buffer_sub_const (& b , bnd );
680704 // Create term and free buffer.
681- polyTerm = arith_poly (terms , & b );
705+ polyTerm = mcarith_poly (terms , & b );
682706 delete_rba_buffer (& b );
707+ result = arith_geq_atom (terms , polyTerm );
683708 }
684- result = arith_geq_atom (terms , polyTerm );
685709 break ;
686710 }
687711 // Assert v <= b by asserting b-v >= 0
688712 case LE_ATM : {
713+ term_t polyTerm ;
714+
689715 // Create buffer b = bnd - v
690716 init_rba_buffer (& b , mcarith_solver_pprods (solver ));
691717 rba_buffer_sub_mcarithvar (solver , & b , v );
692718 rba_buffer_add_const (& b , bnd );
693- polyTerm = arith_poly (terms , & b );
719+ polyTerm = mcarith_poly (terms , & b );
694720 delete_rba_buffer (& b );
695721 result = arith_geq_atom (terms , polyTerm );
696722 break ;
@@ -716,24 +742,30 @@ thvar_t mcarith_create_pprod(void *s, pprod_t *p, thvar_t *map) {
716742 assert (pprod_degree (p ) > 1 );
717743 assert (!pp_is_empty (p ));
718744 assert (!pp_is_var (p ));
719-
720745 // Create theory variable
721746 thvar_t v = simplex_create_var (& solver -> simplex , false);
722747 // Remap variables in powerproduct
723748 mcarith_check_var_size (solver );
724749 pp_buffer_t b ;
725750 init_pp_buffer (& b , p -> len );
751+ uint32_t n = p -> len ;
752+ int32_t * vars = safe_malloc (sizeof (int32_t ) * n );
753+ uint32_t * exps = safe_malloc (sizeof (uint32_t ) * n );
754+
726755 for (uint32_t i = 0 ; i < p -> len ; ++ i ) {
727756 thvar_t mv = map [i ];
728757 assert (mv < v );
729- term_t t = get_term (solver , mv );
730- pp_buffer_set_varexp ( & b , t , p -> prod [i ].exp ) ;
758+ vars [ i ] = get_term (solver , mv );
759+ exps [ i ] = p -> prod [i ].exp ;
731760 }
732- pp_buffer_normalize (& b );
761+ pp_buffer_set_varexps (& b , n , vars , exps );
762+ free (vars );
763+ free (exps );
733764
734- // Create term
735765 assert (solver -> var_terms_size > v );
736- solver -> var_terms [v ] = pprod_term_from_buffer (mcarith_solver_terms (solver ), & b );
766+
767+ term_t t = pprod_term_from_buffer (mcarith_solver_terms (solver ), & b );
768+ solver -> var_terms [v ] = t ;
737769 // Free buffer and return
738770 delete_pp_buffer (& b );
739771 return v ;
@@ -839,6 +871,23 @@ void init_rba_buffer_from_poly(mcarith_solver_t* solver,
839871 }
840872}
841873
874+ static
875+ bool rba_buffer_get_const (rba_buffer_t * b , rational_t * r ) {
876+ if (b -> nterms == 0 ) {
877+ q_init (r );
878+ return true;
879+ } else if (b -> nterms == 1 ) {
880+ mono_t * m = b -> mono + b -> root ;
881+ if (m -> prod == empty_pp ) {
882+ q_init (r );
883+ q_set (r , & m -> coeff );
884+ return true;
885+ }
886+ }
887+ return false;
888+ }
889+
890+
842891/*
843892 * Check for integer feasibility
844893 */
@@ -847,21 +896,18 @@ fcheck_code_t mcarith_final_check(void* s) {
847896 mcarith_solver_t * solver ;
848897 term_table_t * terms ;
849898 uint32_t acnt ;
850-
899+ term_t t ;
851900
852901 solver = s ;
853902 terms = mcarith_solver_terms (solver );
903+ assert (!solver -> simplex .unsat_before_search );
854904
855- yices_pp_t printer ;
856- pp_area_t area ;
857-
858- area .width = 72 ;
859- area .height = 8 ;
860- area .offset = 2 ;
861- area .stretch = false;
862- area .truncate = true;
905+ fcheck_code_t result ;
863906
864- init_default_yices_pp (& printer , stdout , & area );
907+ result = simplex_final_check (& solver -> simplex );
908+ if (result == FCHECK_CONTINUE ) {
909+ return result ;
910+ }
865911
866912 mcarith_free_mcsat (solver );
867913
@@ -892,18 +938,40 @@ fcheck_code_t mcarith_final_check(void* s) {
892938 p = arith_eq_atom (terms , get_term (solver , a -> def .var ));
893939 break ;
894940 case VAR_GE0 :
895- p = arith_geq_atom (terms , get_term (solver , a -> def .var ));
941+ t = get_term (solver , a -> def .var );
942+ assert (term_kind (terms , t ) != ARITH_CONSTANT );
943+ p = arith_geq_atom (terms , t );
896944 break ;
897- case POLY_EQ0 :
945+ case POLY_EQ0 : {
946+ rational_t br ;
947+
898948 init_rba_buffer_from_poly (solver , & b , a -> def .poly );
899- p = arith_eq_atom (terms , arith_poly (terms , & b ));
949+ if (rba_buffer_get_const (& b , & br )) {
950+ p = bool2term (q_is_zero (& br ));
951+ q_clear (& br );
952+ } else {
953+ t = arith_poly (terms , & b );
954+ assert (term_kind (terms , t ) != ARITH_CONSTANT );
955+ p = arith_eq_atom (terms , t );
956+ }
900957 delete_rba_buffer (& b );
901958 break ;
902- case POLY_GE0 :
959+ }
960+ case POLY_GE0 : {
961+ rational_t br ;
962+
903963 init_rba_buffer_from_poly (solver , & b , a -> def .poly );
904- p = arith_geq_atom (terms , arith_poly (terms , & b ));
964+ if (rba_buffer_get_const (& b , & br )) {
965+ p = bool2term (q_is_nonneg (& br ));
966+ q_clear (& br );
967+ } else {
968+ t = arith_poly (terms , & b );
969+ assert (term_kind (terms , t ) != ARITH_CONSTANT );
970+ p = arith_geq_atom (terms , t );
971+ }
905972 delete_rba_buffer (& b );
906973 break ;
974+ }
907975 case ATOM_ASSERT :
908976 p = get_atom (solver , a -> def .atom );
909977 break ;
@@ -920,10 +988,9 @@ fcheck_code_t mcarith_final_check(void* s) {
920988 literals [literal_count ] = end_clause ;
921989
922990 int32_t r = mcsat_assert_formulas (solver -> mcsat , acnt , assertions );
923- fcheck_code_t result ;
924991 if (r == TRIVIALLY_UNSAT ) {
925992 record_theory_conflict (solver -> simplex .core , literals );
926- mcarith_free_mcsat (solver );
993+ mcarith_free_mcsat (solver );
927994 result = FCHECK_CONTINUE ;
928995 } else if (r == CTX_NO_ERROR ) {
929996 result = FCHECK_SAT ;
@@ -990,7 +1057,10 @@ void mcarith_increase_decision_level(mcarith_solver_t *solver) {
9901057void mcarith_backtrack (mcarith_solver_t * solver , uint32_t back_level ) {
9911058 mcarith_undo_record_t * r = mcarith_undo_backtrack (& solver -> undo_stack , back_level );
9921059 mcarith_backtrack_assertions (solver , r -> n_assertions );
1060+ uint32_t vc = solver -> simplex .vtbl .nvars ;
9931061 simplex_backtrack (& solver -> simplex , back_level );
1062+ uint32_t vc0 = solver -> simplex .vtbl .nvars ;
1063+ assert (vc == vc0 );
9941064}
9951065
9961066/*
@@ -1028,7 +1098,10 @@ void mcarith_pop(mcarith_solver_t *solver) {
10281098 * Reset to the empty solver
10291099 */
10301100void mcarith_reset (mcarith_solver_t * solver ) {
1101+ uint32_t vc = solver -> simplex .vtbl .nvars ;
10311102 simplex_reset (& solver -> simplex );
1103+ uint32_t vc0 = solver -> simplex .vtbl .nvars ;
1104+ assert (vc == vc0 ); // FIXME
10321105
10331106 mcarith_undo_reset (& solver -> undo_stack );
10341107 mcarith_backtrack_assertions (solver , 0 );
@@ -1134,6 +1207,27 @@ thvar_t mcarith_create_poly(void* s, polynomial_t *p, thvar_t *map) {
11341207 return simplex_create_poly (& solver -> simplex , p , map );
11351208}
11361209
1210+ typedef struct {
1211+ uint32_t bstack_top ;
1212+ uint32_t matrix_nrows ;
1213+ } simplex_assertion_count_t ;
1214+
1215+ static simplex_assertion_count_t simplex_assertion_count (simplex_solver_t * simplex ) {
1216+ simplex_assertion_count_t r ;
1217+ r .bstack_top = simplex -> bstack .top ;
1218+ r .matrix_nrows = simplex -> matrix .nrows ;
1219+ return r ;
1220+ }
1221+
1222+ /**
1223+ * Returns true if the simplex solver concluded the assertion just added did not
1224+ * need to get recorded as it was true or false from previous assertions.
1225+ */
1226+ static bool simplex_handled_assertion (simplex_solver_t * simplex , simplex_assertion_count_t c ) {
1227+ return simplex -> unsat_before_search
1228+ || (simplex -> matrix .nrows == c .matrix_nrows && simplex -> bstack .top == c .bstack_top );
1229+ }
1230+
11371231/*
11381232 * Assert a top-level equality constraint (either x == 0 or x != 0)
11391233 * - tt indicates whether the constraint or its negation must be asserted
@@ -1145,7 +1239,11 @@ static void mcarith_assert_eq_axiom(void* s, thvar_t x, bool tt) {
11451239 mcarith_assertion_t * assert ;
11461240
11471241 solver = s ;
1242+ // Get number of assertions
1243+ simplex_assertion_count_t cinit = simplex_assertion_count (& solver -> simplex );
11481244 simplex_assert_eq_axiom (& solver -> simplex , x , tt );
1245+ if (simplex_handled_assertion (& solver -> simplex , cinit ))
1246+ return ;
11491247
11501248 // Record assertion for sending to mcarith solver.
11511249 assert = alloc_top_assertion (solver );
@@ -1166,7 +1264,11 @@ static void mcarith_assert_ge_axiom(void* s, thvar_t x, bool tt){
11661264 mcarith_assertion_t * assert ;
11671265
11681266 solver = s ;
1267+ // Get number of assertions
1268+ simplex_assertion_count_t cinit = simplex_assertion_count (& solver -> simplex );
11691269 simplex_assert_ge_axiom (& solver -> simplex , x , tt );
1270+ if (simplex_handled_assertion (& solver -> simplex , cinit ))
1271+ return ;
11701272
11711273 assert = alloc_top_assertion (solver );
11721274 assert -> type = VAR_GE0 ;
@@ -1188,10 +1290,15 @@ static void mcarith_assert_poly_eq_axiom(void * s, polynomial_t *p, thvar_t *map
11881290 solver = s ;
11891291 assert (p -> nterms > 0 );
11901292
1293+ simplex_assertion_count_t cinit = simplex_assertion_count (& solver -> simplex );
11911294 simplex_assert_poly_eq_axiom (& solver -> simplex , p , map , tt );
1295+ if (simplex_handled_assertion (& solver -> simplex , cinit ))
1296+ return ;
11921297
11931298 assert = alloc_top_assertion (solver );
11941299 assert -> type = POLY_EQ0 ;
1300+ assert (p -> nterms > 0 );
1301+ assert (p -> nterms > 1 || p -> mono [0 ].var != const_idx );
11951302 assert -> def .poly = alloc_polynomial_from_map (p , map , solver -> simplex .vtbl .nvars );
11961303 assert -> tt = tt ;
11971304 assert -> lit = null_literal ;
@@ -1209,10 +1316,15 @@ static void mcarith_assert_poly_ge_axiom(void *s, polynomial_t *p, thvar_t *map,
12091316 solver = s ;
12101317 assert (p -> nterms > 0 );
12111318
1319+ simplex_assertion_count_t cinit = simplex_assertion_count (& solver -> simplex );
12121320 simplex_assert_poly_ge_axiom (& solver -> simplex , p , map , tt );
1321+ if (simplex_handled_assertion (& solver -> simplex , cinit ))
1322+ return ;
12131323
12141324 assert = alloc_top_assertion (solver );
12151325 assert -> type = POLY_GE0 ;
1326+ assert (p -> nterms > 0 );
1327+ assert (p -> nterms > 1 || p -> mono [0 ].var != const_idx );
12161328 assert -> def .poly = alloc_polynomial_from_map (p , map , solver -> simplex .vtbl .nvars );
12171329 assert -> tt = tt ;
12181330 assert -> lit = null_literal ;
@@ -1228,7 +1340,10 @@ void mcarith_assert_vareq_axiom(void* s, thvar_t x, thvar_t y, bool tt) {
12281340 mcarith_assertion_t * assert ;
12291341
12301342 solver = s ;
1343+ simplex_assertion_count_t cinit = simplex_assertion_count (& solver -> simplex );
12311344 simplex_assert_vareq_axiom (& solver -> simplex , x , y , tt );
1345+ if (simplex_handled_assertion (& solver -> simplex , cinit ))
1346+ return ;
12321347
12331348 assert = alloc_top_assertion (solver );
12341349 assert -> type = VAR_EQ ;
@@ -1245,7 +1360,12 @@ static
12451360void mcarith_assert_cond_vareq_axiom (void * s , literal_t c , thvar_t x , thvar_t y ) {
12461361 mcarith_solver_t * solver ;
12471362 solver = s ;
1363+ simplex_assertion_count_t cinit = simplex_assertion_count (& solver -> simplex );
12481364 simplex_assert_cond_vareq_axiom (& solver -> simplex , c , x , y );
1365+ if (simplex_handled_assertion (& solver -> simplex , cinit ))
1366+ return ;
1367+
1368+ assert (false);
12491369}
12501370
12511371/*
@@ -1254,7 +1374,12 @@ void mcarith_assert_cond_vareq_axiom(void* s, literal_t c, thvar_t x, thvar_t y)
12541374static
12551375void mcarith_assert_clause_vareq_axiom (void * s , uint32_t n , literal_t * c , thvar_t x , thvar_t y ) {
12561376 mcarith_solver_t * solver = s ;
1377+ simplex_assertion_count_t cinit = simplex_assertion_count (& solver -> simplex );
12571378 simplex_assert_clause_vareq_axiom (& solver -> simplex , n , c , x , y );
1379+ if (simplex_handled_assertion (& solver -> simplex , cinit ))
1380+ return ;
1381+
1382+ assert (false);
12581383}
12591384
12601385/*
0 commit comments