@@ -371,9 +371,7 @@ static obligationst property_obligations_rec(
371371 return obligationst{no_timeframes - 1 , true_exprt ()}; // works on NNF only
372372 }
373373 }
374- else if (
375- property_expr.id () == ID_sva_until ||
376- property_expr.id () == ID_sva_s_until || property_expr.id () == ID_U)
374+ else if (property_expr.id () == ID_sva_s_until || property_expr.id () == ID_U)
377375 {
378376 auto &p = to_binary_expr (property_expr).lhs ();
379377 auto &q = to_binary_expr (property_expr).rhs ();
@@ -383,11 +381,11 @@ static obligationst property_obligations_rec(
383381
384382 return property_obligations_rec (tmp, current, no_timeframes, ns);
385383 }
386- else if (property_expr.id () == ID_weak_U)
384+ else if (property_expr.id () == ID_sva_until || property_expr. id () == ID_weak_U)
387385 {
388386 // we expand: p W q ≡ q ∨ ( p ∧ X(p W q) )
389- auto &p = to_weak_U_expr (property_expr).lhs ();
390- auto &q = to_weak_U_expr (property_expr).rhs ();
387+ auto &p = to_binary_expr (property_expr).lhs ();
388+ auto &q = to_binary_expr (property_expr).rhs ();
391389
392390 // Once we reach the end of the unwinding, replace X(p W q) by 'true'.
393391 auto tmp = or_exprt{
@@ -411,23 +409,33 @@ static obligationst property_obligations_rec(
411409
412410 return property_obligations_rec (expansion, current, no_timeframes, ns);
413411 }
414- else if (
415- property_expr.id () == ID_sva_until_with ||
416- property_expr.id () == ID_sva_s_until_with)
412+ else if (property_expr.id () == ID_strong_R)
417413 {
418- // overlapping until
419-
420- // we rewrite using 'next'
421- binary_exprt tmp = to_binary_expr (property_expr);
422- if (property_expr.id () == ID_sva_until_with)
423- tmp.id (ID_sva_until);
424- else
425- tmp.id (ID_sva_s_until);
414+ auto &p = to_strong_R_expr (property_expr).lhs ();
415+ auto &q = to_strong_R_expr (property_expr).rhs ();
426416
427- tmp.op1 () = X_exprt{tmp.op1 ()};
417+ // p strongR q ≡ Fp ∧ (p R q)
418+ exprt tmp = and_exprt{F_exprt{q}, weak_U_exprt{p, q}};
428419
429420 return property_obligations_rec (tmp, current, no_timeframes, ns);
430421 }
422+ else if (property_expr.id () == ID_sva_until_with)
423+ {
424+ // Rewrite to LTL (weak) R.
425+ // Note that lhs and rhs are flipped.
426+ auto &until_with = to_sva_until_with_expr (property_expr);
427+ auto R = R_exprt{until_with.rhs (), until_with.lhs ()};
428+ return property_obligations_rec (R, solver, current, no_timeframes, ns);
429+ }
430+ else if (property_expr.id () == ID_sva_s_until_with)
431+ {
432+ // Rewrite to LTL (strong) R.
433+ // Note that lhs and rhs are flipped.
434+ auto &s_until_with = to_sva_s_until_with_expr (property_expr);
435+ auto strong_R = strong_R_exprt{s_until_with.rhs (), s_until_with.lhs ()};
436+ return property_obligations_rec (
437+ strong_R, solver, current, no_timeframes, ns);
438+ }
431439 else if (property_expr.id () == ID_and)
432440 {
433441 // Generate seperate sets of obligations for each conjunct,
@@ -571,6 +579,40 @@ static obligationst property_obligations_rec(
571579 return property_obligations_rec (
572580 to_not_expr (op).op (), current, no_timeframes, ns);
573581 }
582+ else if (op.id () == ID_sva_until)
583+ {
584+ // ¬(φ W ψ) ≡ (¬φ strongR ¬ψ)
585+ auto &W = to_sva_until_expr (op);
586+ auto strong_R = strong_R_exprt{not_exprt{W.lhs ()}, not_exprt{W.rhs ()}};
587+ return property_obligations_rec (
588+ strong_R, solver, current, no_timeframes, ns);
589+ }
590+ else if (op.id () == ID_sva_s_until)
591+ {
592+ // ¬(φ U ψ) ≡ (¬φ R ¬ψ)
593+ auto &U = to_sva_s_until_expr (op);
594+ auto R = R_exprt{not_exprt{U.lhs ()}, not_exprt{U.rhs ()}};
595+ return property_obligations_rec (R, solver, current, no_timeframes, ns);
596+ }
597+ else if (op.id () == ID_sva_until_with)
598+ {
599+ // ¬(φ R ψ) ≡ (¬φ U ¬ψ)
600+ // Note LHS and RHS are swapped.
601+ auto &until_with = to_sva_until_with_expr (op);
602+ auto R = R_exprt{until_with.rhs (), until_with.lhs ()};
603+ auto U = sva_until_exprt{not_exprt{R.lhs ()}, not_exprt{R.rhs ()}};
604+ return property_obligations_rec (U, solver, current, no_timeframes, ns);
605+ }
606+ else if (op.id () == ID_sva_s_until_with)
607+ {
608+ // ¬(φ strongR ψ) ≡ (¬φ W ¬ψ)
609+ // Note LHS and RHS are swapped.
610+ auto &s_until_with = to_sva_s_until_with_expr (op);
611+ auto strong_R = strong_R_exprt{s_until_with.rhs (), s_until_with.lhs ()};
612+ auto W =
613+ weak_U_exprt{not_exprt{strong_R.lhs ()}, not_exprt{strong_R.rhs ()}};
614+ return property_obligations_rec (W, solver, current, no_timeframes, ns);
615+ }
574616 else
575617 return obligationst{
576618 instantiate_property (property_expr, current, no_timeframes)};
0 commit comments