public CsAlgebra(IBooleanAlgebra <T> leafAlgebra, ICounter[] counters) { this.counters = counters; this.LeafAlgebra = leafAlgebra; this.NodeAlgebra = new BDDAlgebra <T>(leafAlgebra); __false = new CsPred <T>(this, (BDD <T>)NodeAlgebra.False); __true = new CsPred <T>(this, (BDD <T>)NodeAlgebra.True); this.K = counters.Length; TrueCsConditionSeq = CsConditionSeq.MkTrue(counters.Length); FalseCsConditionSeq = CsConditionSeq.MkFalse(counters.Length); }
/// <summary> /// Complement the sequence from OR to AND and vice versa, /// individual counter conditions are complemented. /// </summary> public static CsConditionSeq operator ~(CsConditionSeq arg) { int length = arg.Length; ulong mask = arg.Mask; ulong empty = mask & ~arg.Empty; ulong low = mask & ~arg.Low; ulong middle = mask & ~arg.Middle; ulong high = mask & ~arg.High; var elems = new Tuple <int, ulong, ulong, ulong, ulong, ulong>(length, mask, empty, low, middle, high); var res = new CsConditionSeq(!arg.isAND, elems); return(res); }
/// <summary> /// Creates counter minterms for the given set of counting states and input predicate. /// </summary> /// <param name="list">list of counting states, possibly empty i.e. null</param> /// <param name="a">input predicate</param> /// <returns></returns> private IEnumerable <CsConditionSeq> GenerateCounterMinterms(ConsList <int> list, S a) { if (list == null) { yield return(CsConditionSeq.MkTrue(countingStates.Count)); } else { var a_moves = new List <Move <Tuple <Maybe <S>, Sequence <CounterOperation> > > >(GetMovesFrom(list.First, a)).ToArray(); var incr_exists = Array.Exists(a_moves, m => m.Label.Item2.First.OperationKind == CounterOp.INCR); var exit_exists = Array.Exists(a_moves, m => m.Label.Item2.First.OperationKind != CounterOp.INCR); var i = GetCounter(list.First).CounterId; foreach (var seq in GenerateCounterMinterms(list.Rest, a)) { if (a_moves.Length > 0) { if (incr_exists && exit_exists) { yield return(seq.Update(i, CsCondition.LOW)); if (!(IsSingletonCountingState(list.First) && GetCounter(list.First).LowerBound == GetCounter(list.First).UpperBound)) { yield return(seq.Update(i, CsCondition.MIDDLE)); } yield return(seq.Update(i, CsCondition.HIGH)); } else if (incr_exists) { yield return(seq.Update(i, CsCondition.CANLOOP)); } else if (exit_exists) { yield return(seq.Update(i, CsCondition.CANEXIT)); } else { throw new AutomataException(AutomataExceptionKind.InternalError_GenerateCounterMinterms); } } else { yield return(seq); } } } }
/// <summary> /// Create a disjunction sequence of two sequences that represent disjunctions /// </summary> public static CsConditionSeq operator |(CsConditionSeq left, CsConditionSeq right) { if (left.Length == right.Length && !left.isAND && !right.isAND) { int length = left.Length; ulong mask = left.Mask; ulong empty = left.Empty | right.Empty; ulong low = left.Low | right.Low; ulong middle = left.Middle | right.Middle; ulong high = left.High | right.High; var elems = new Tuple <int, ulong, ulong, ulong, ulong, ulong>(length, mask, empty, low, middle, high); var res = new CsConditionSeq(false, elems); return(res); } else { throw new InvalidOperationException("Incompatible arguments, | is only supported between disjunction sequences"); } }
/// <summary> /// Update the i'th element to this[i] & cond /// </summary> public CsConditionSeq And(int i, CsCondition cond) { if (i >= Length) { throw new ArgumentOutOfRangeException(); } ulong bit = ((ulong)1) << i; ulong bit_false = ~bit; ulong empty = Empty; ulong low = Low; ulong mid = Middle; ulong high = High; //set the new value if (!cond.HasFlag(CsCondition.LOW)) { low = low & bit_false; } if (!cond.HasFlag(CsCondition.MIDDLE)) { mid = mid & bit_false; } if (!cond.HasFlag(CsCondition.HIGH)) { high = high & bit_false; } if (!cond.HasFlag(CsCondition.EMPTY)) { empty = empty & bit_false; } var elems = new Tuple <int, ulong, ulong, ulong, ulong, ulong>(Length, Mask, empty, low, mid, high); var res = new CsConditionSeq(isAND, elems); return(res); }
/// <summary> /// Make a product between leafpred and vals. /// </summary> /// <param name="leafpred">input predicate</param> /// <param name="vals">this is either a conjunction or disjunction of counter conditions</param> /// <returns></returns> public CsPred <T> MkPredicate(T leafpred, CsConditionSeq vals) { return(MkPredicate(leafpred, vals.IsAND, vals.ToArray())); }
internal CsUpdateSeq GetCounterUpdate(int q, S input, CsConditionSeq guard) { var res = CsUpdateSeq.MkNOOP(countingStates.Count); foreach (var mv in delta[q]) { if (mv.Label.Item1.IsSomething && solver.IsSatisfiable(solver.MkAnd(mv.Label.Item1.Element, input))) { var p = mv.TargetState; if (IsCountingState(p)) { var p_counter = GetCounter(p); if (p == q) { #region loop if (mv.Label.Item2.Length != 1) { throw new AutomataException(AutomataExceptionKind.InternalError); } else { var op = mv.Label.Item2[0]; if (guard[p_counter.CounterId].HasFlag(CsCondition.LOW) || guard[p_counter.CounterId].HasFlag(CsCondition.MIDDLE) || guard[p_counter.CounterId].HasFlag(CsCondition.HIGH)) { if (op.OperationKind == CounterOp.INCR) { res = res.Or(op.Counter.CounterId, CsUpdate.INCR); } else if (op.OperationKind == CounterOp.EXIT_SET0) { res = res.Or(op.Counter.CounterId, CsUpdate.SET0); } else if (op.OperationKind == CounterOp.EXIT_SET1) { res = res.Or(op.Counter.CounterId, CsUpdate.SET1); } else { throw new AutomataException(AutomataExceptionKind.InternalError); } } } #endregion } else if (IsCountingState(q)) { #region q is counting state too var q_counter = GetCounter(q); if (mv.Label.Item2.Length != 2) { throw new AutomataException(AutomataExceptionKind.InternalError); } else { var q_exit = mv.Label.Item2[0]; var p_set = mv.Label.Item2[1]; if (q_exit.Counter.CounterId != q_counter.CounterId || p_set.Counter.CounterId != p_counter.CounterId) { throw new AutomataException(AutomataExceptionKind.InternalError); } if (guard[q_counter.CounterId].HasFlag(CsCondition.HIGH) || guard[q_counter.CounterId].HasFlag(CsCondition.MIDDLE)) { if (p_set.OperationKind == CounterOp.SET0) { res = res.Or(p_set.Counter.CounterId, CsUpdate.SET0); } else if (p_set.OperationKind == CounterOp.SET1) { res = res.Or(p_set.Counter.CounterId, CsUpdate.SET1); } else { throw new AutomataException(AutomataExceptionKind.InternalError); } } } #endregion } else { #region q is non-counting state if (mv.Label.Item2.Length != 1) { throw new AutomataException(AutomataExceptionKind.InternalError); } else { var p_set = mv.Label.Item2[0]; if (p_set.Counter.CounterId != p_counter.CounterId) { throw new AutomataException(AutomataExceptionKind.InternalError); } if (p_set.OperationKind == CounterOp.SET0) { res = res.Or(p_set.Counter.CounterId, CsUpdate.SET0); } else if (p_set.OperationKind == CounterOp.SET1) { res = res.Or(p_set.Counter.CounterId, CsUpdate.SET1); } else { throw new AutomataException(AutomataExceptionKind.InternalError); } } #endregion } } } } return(res); }
private IEnumerable <Move <Tuple <Maybe <S>, Sequence <CounterOperation> > > > GetMovesFrom(List <int> states, S a, CsConditionSeq psi) { throw new NotImplementedException(); }