CsLabel(bool isFinalCondition, CsPred <S> guard, CsUpdateSeq updates, Func <S, string> inputToString) { this.isFinalCondition = isFinalCondition; this.Guard = guard; this.Updates = updates; this.InputToString = inputToString; }
public CsUpdateSeq Or(int i, CsUpdate upd) { ulong bit = ((ulong)1) << i; ulong set0 = vals.Item2; ulong set1 = vals.Item3; ulong incr = vals.Item4; if (upd.HasFlag(CsUpdate.SET0)) { set0 = set0 | bit; } if (upd.HasFlag(CsUpdate.SET1)) { set1 = set1 | bit; } if (upd.HasFlag(CsUpdate.INCR)) { incr = incr | bit; } CsUpdateSeq res = new CsUpdateSeq(vals.Item1, set0, set1, incr); return(res); }
public static CsLabel <S> MkTransitionLabel(CsPred <S> guard, CsUpdateSeq updates, Func <S, string> inputToString = null) { return(new CsLabel <S>(false, guard, updates, inputToString)); }
public static CsAutomaton <S> CreateFrom(CountingAutomaton <S> ca) { var productmoves = new List <Move <CsPred <S> > >(); var counters = ca.counters; var alg = new CsAlgebra <S>(((CABA <S>)ca.Algebra).builder.solver, counters); foreach (var move in ca.GetMoves()) { var ccond = alg.TrueCsConditionSeq; if (ca.IsCountingState(move.SourceState)) { var counter = ca.GetCounter(move.SourceState); var cid = counter.CounterId; if (move.Label.Item2.First.OperationKind == CounterOp.EXIT || move.Label.Item2.First.OperationKind == CounterOp.EXIT_SET0 || move.Label.Item2.First.OperationKind == CounterOp.EXIT_SET1) { if (counter.LowerBound == counter.UpperBound && !ca.HasMovesTo(move.SourceState, move.Label.Item1.Element)) { ccond = ccond.And(cid, CsCondition.HIGH); } else if (counter.LowerBound > 0) { ccond = ccond.And(cid, CsCondition.CANEXIT); } else { ccond.And(cid, CsCondition.NONEMPTY); } } else { if (move.Label.Item2.First.OperationKind != CounterOp.INCR) { throw new AutomataException(AutomataExceptionKind.InternalError); } if (counter.LowerBound == counter.UpperBound && !ca.HasMovesTo(move.SourceState, move.Label.Item1.Element)) { ccond = ccond.And(cid, CsCondition.LOW); } else { ccond = ccond.And(cid, CsCondition.CANLOOP); } } } if (ccond.IsSatisfiable) { var pmove = Move <CsPred <S> > .Create(move.SourceState, move.TargetState, alg.MkPredicate(move.Label.Item1.Element, ccond)); productmoves.Add(pmove); } } var prodaut = Automaton <CsPred <S> > .Create(alg, ca.InitialState, ca.GetFinalStates(), productmoves); PowerSetStateBuilder sb; var det = prodaut.Determinize(out sb); //add predicate that all counters associated with the state are nonempty var counterFilter = new Dictionary <int, CsConditionSeq>(); foreach (var state in det.GetStates()) { var stateCounterFilter = alg.TrueCsConditionSeq; foreach (var q in sb.GetMembers(state)) { if (ca.IsCountingState(q)) { stateCounterFilter = stateCounterFilter.And(ca.GetCounter(q).CounterId, CsCondition.NONEMPTY); } } counterFilter[state] = stateCounterFilter; } var csmoves = new List <Move <CsLabel <S> > >(); //make disjunction of the guards of transitions with same update sequence var trans = new Dictionary <Tuple <int, int>, Dictionary <CsUpdateSeq, CsPred <S> > >(); foreach (var dmove in det.GetMoves()) { foreach (var prodcond in dmove.Label.GetSumOfProducts()) { var upd = CsUpdateSeq.MkNOOP(ca.NrOfCounters); foreach (var q in sb.GetMembers(dmove.SourceState)) { upd = upd | ca.GetCounterUpdate(q, prodcond.Item2, prodcond.Item1); } //make sure all counter guards are nonempty //determinization may create EMPTY counter conditions that are unreachable //while all counters associated with a state are always nonempty var counterGuard = prodcond.Item1 & counterFilter[dmove.SourceState]; if (counterGuard.IsSatisfiable) { #region replace set with incr if possible for (int i = 0; i < upd.Length; i++) { var guard_i = counterGuard[i]; if (guard_i == CsCondition.HIGH) { var upd_i = upd[i]; switch (upd_i) { case CsUpdate.SET0: upd = upd.Set(i, CsUpdate.INCR0); break; case CsUpdate.SET1: upd = upd.Set(i, CsUpdate.INCR1); break; case CsUpdate.SET01: upd = upd.Set(i, CsUpdate.INCR01); break; default: break; } } } #endregion var guard = alg.MkPredicate(prodcond.Item2, counterGuard); var statepair = new Tuple <int, int>(dmove.SourceState, dmove.TargetState); Dictionary <CsUpdateSeq, CsPred <S> > labels; if (!trans.TryGetValue(statepair, out labels)) { labels = new Dictionary <CsUpdateSeq, CsPred <S> >(); trans[statepair] = labels; } CsPred <S> pred; if (!labels.TryGetValue(upd, out pred)) { pred = guard; } else { pred = guard | pred; } labels[upd] = pred; } else { ; } } } Func <S, string> pp = ((CABA <S>)ca.Algebra).builder.solver.PrettyPrint; foreach (var entry in trans) { var s = entry.Key.Item1; var t = entry.Key.Item2; foreach (var label in entry.Value) { var upd = label.Key; var psi = label.Value; csmoves.Add(Move <CsLabel <S> > .Create(s, t, CsLabel <S> .MkTransitionLabel(psi, upd, pp))); } } var csa_aut = Automaton <CsLabel <S> > .Create(null, det.InitialState, det.GetFinalStates(), csmoves, true, true); var fs = new HashSet <int>(ca.GetFinalStates()); var csa = new CsAutomaton <S>(alg, csa_aut, sb, ca.countingStates, fs); return(csa); }
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); }