@@ -72,6 +72,19 @@ Alternate to lookahead strategy:
7272Revert bias on long strings:
7373- give preference to reset leaves that are assigned to long strings
7474- bake in bias for shorter strings into equation solving?
75+
76+ Equality solving using stochastic Nelson.
77+ - Given equality where current assignment does not satisfy it:
78+ - Xw = v:
79+ - let X' range over prefixes of X that matches v.
80+ - non-deterministic set X <- strval0(X')
81+ - non-deterministic set X <- strval0(X') + 'a' where strval0(X') + 'a' matches prefix of strval0(v), and X' is longest prefix of X that matches v.
82+ - If X fully matches a prefix of v, then, in addition to the rules above:
83+ - consume constant character from strval0(X)w = v
84+ - reveal the next variable to solve for.
85+
86+ - What scores make sense to use for partial solutions?
87+
7588--*/
7689
7790#include " ast/sls/sls_seq_plugin.h"
@@ -411,23 +424,29 @@ namespace sls {
411424 if (m.is_bool (e))
412425 return ;
413426
414- if (seq.is_string (e->get_sort ())) {
415- if (is_value (e))
416- return ;
417- strval0 (e) = strval1 (e);
418- ctx.new_value_eh (e);
427+ if (seq.str .is_itos (e)) {
428+ repair_up_str_itos (e);
429+ return ;
430+ }
431+ if (seq.str .is_stoi (e)) {
432+ repair_up_str_stoi (e);
419433 return ;
420434 }
421-
422435 if (seq.str .is_length (e)) {
423436 repair_up_str_length (e);
424437 return ;
425438 }
426-
427439 if (seq.str .is_index (e)) {
428440 repair_up_str_indexof (e);
429441 return ;
430442 }
443+ if (seq.is_string (e->get_sort ())) {
444+ if (is_value (e))
445+ return ;
446+ strval0 (e) = strval1 (e);
447+ ctx.new_value_eh (e);
448+ return ;
449+ }
431450
432451 verbose_stream () << " repair up nyi: " << mk_bounded_pp (e, m) << " \n " ;
433452 }
@@ -471,6 +490,35 @@ namespace sls {
471490 return apply_update ();
472491 }
473492
493+ void seq_plugin::repair_up_str_stoi (app* e) {
494+ expr* x;
495+ VERIFY (seq.str .is_stoi (e, x));
496+
497+ rational val_e;
498+ rational val_x (strval0 (x).encode ().c_str ());
499+ VERIFY (a.is_numeral (ctx.get_value (e), val_e));
500+ if (val_e.is_unsigned () && val_e == val_x)
501+ return ;
502+ if (val_x < 0 )
503+ update (e, rational (0 ));
504+ else
505+ update (e, val_x);
506+ }
507+
508+ void seq_plugin::repair_up_str_itos (app* e) {
509+ expr* x;
510+ VERIFY (seq.str .is_itos (e, x));
511+ rational val_x;
512+ VERIFY (a.is_numeral (ctx.get_value (x), val_x));
513+ rational val_e (strval0 (e).encode ().c_str ());
514+ if (val_x.is_unsigned () && val_x == val_e)
515+ return ;
516+ if (val_x < 0 )
517+ update (e, zstring ());
518+ else
519+ update (e, zstring (val_x.to_string ()));
520+ }
521+
474522 void seq_plugin::repair_up_str_length (app* e) {
475523 expr* x;
476524 VERIFY (seq.str .is_length (e, x));
@@ -566,21 +614,33 @@ namespace sls {
566614 if (seq.is_string (to_app (e)->get_arg (0 )->get_sort ()))
567615 return repair_down_str_indexof (e);
568616 break ;
617+ case OP_STRING_CONST:
618+ UNREACHABLE ();
619+ break ;
620+ case OP_STRING_ITOS:
621+ return repair_down_str_itos (e);
622+ case OP_STRING_STOI:
623+ return repair_down_str_stoi (e);
624+ case OP_STRING_UBVTOS:
625+ case OP_STRING_SBVTOS:
626+ case OP_STRING_TO_CODE:
627+ case OP_STRING_FROM_CODE:
569628 case OP_SEQ_UNIT:
570- case OP_SEQ_REPLACE:
571629 case OP_SEQ_NTH:
572630 case OP_SEQ_NTH_I:
573631 case OP_SEQ_NTH_U:
574- case OP_SEQ_LAST_INDEX:
575- case OP_SEQ_TO_RE:
576- case OP_SEQ_IN_RE:
632+ case OP_SEQ_REPLACE:
577633 case OP_SEQ_REPLACE_RE_ALL:
578634 case OP_SEQ_REPLACE_RE:
579635 case OP_SEQ_REPLACE_ALL:
580636 case OP_SEQ_MAP:
581637 case OP_SEQ_MAPI:
582638 case OP_SEQ_FOLDL:
583- case OP_SEQ_FOLDLI:
639+ case OP_SEQ_FOLDLI:
640+
641+ case OP_SEQ_TO_RE:
642+ case OP_SEQ_IN_RE:
643+
584644 case OP_RE_PLUS:
585645 case OP_RE_STAR:
586646 case OP_RE_OPTION:
@@ -598,23 +658,43 @@ namespace sls {
598658 case OP_RE_OF_PRED:
599659 case OP_RE_REVERSE:
600660 case OP_RE_DERIVATIVE:
601- case OP_STRING_CONST:
602- case OP_STRING_ITOS:
603- case OP_STRING_STOI:
604- case OP_STRING_UBVTOS:
605- case OP_STRING_SBVTOS:
606661 case OP_STRING_LT:
607662 case OP_STRING_LE:
608- case OP_STRING_IS_DIGIT:
609- case OP_STRING_TO_CODE:
610- case OP_STRING_FROM_CODE:
611- default :
612- break ;
663+ case OP_STRING_IS_DIGIT:
664+ break ;
665+ default :
666+ verbose_stream () << " unexpected repair down " << mk_bounded_pp (e, m) << " \n " ;
667+ UNREACHABLE ();
613668 }
614669 verbose_stream () << " nyi repair down " << mk_bounded_pp (e, m) << " \n " ;
615670 return false ;
616671 }
617672
673+ bool seq_plugin::repair_down_str_itos (app* e) {
674+ expr* x;
675+ VERIFY (seq.str .is_itos (e, x));
676+ zstring se = strval0 (e);
677+ rational r (se.encode ().c_str ());
678+ if (r.is_int ())
679+ m_int_updates.push_back ({ x, r, 1 });
680+ else
681+ m_int_updates.push_back ({ x, rational (-1 - ctx.rand (10 )), 1 });
682+
683+ return apply_update ();
684+ }
685+
686+ bool seq_plugin::repair_down_str_stoi (app* e) {
687+ expr* x;
688+ rational r;
689+ VERIFY (seq.str .is_stoi (e, x));
690+ VERIFY (a.is_numeral (ctx.get_value (e), r) && r.is_int ());
691+ if (r < 0 )
692+ return false ;
693+ zstring r_val (r.to_string ());
694+ m_str_updates.push_back ({ x, r_val, 1 });
695+ return apply_update ();
696+ }
697+
618698 bool seq_plugin::repair_down_str_at (app* e) {
619699 expr* x, * y;
620700 VERIFY (seq.str .is_at (e, x, y));
0 commit comments