/// <summary> /// A pairwise invariant for a list of elements. /// </summary> /// <param name="list">The list.</param> /// <param name="f">The pairwise invariant.</param> /// <returns>A zen value for the invariant.</returns> internal static Zen <bool> PairwiseInvariant <T>(Zen <IList <T> > list, Func <Zen <T>, Zen <T>, Zen <bool> > f) { return(list.Case( empty: true, cons: (hd1, tl1) => tl1.Case( empty: true, cons: (hd2, tl2) => And(f(hd1, hd2), PairwiseInvariant(tl1, f))))); }
/// <summary> /// Ensure all storms are ended. /// </summary> /// <param name="es">The events.</param> /// <param name="isPreviousStart">Whether a start is open and waiting to be closed.</param> /// <param name="priorityClass">The priority class.</param> /// <returns></returns> private static Zen <bool> AreStartEndStormsValid(Zen <IList <Event> > es, Zen <bool> isPreviousStart, byte priorityClass) { var startType = Event.EventTypeAsByte(EventType.PfcStormStartEvent); var endType = Event.EventTypeAsByte(EventType.PfcStormEndEvent); return(es.Case(empty: Not(isPreviousStart), cons: (hd, tl) => { var isCorrectPriority = hd.GetPriorityClass() == priorityClass; var isStart = And(hd.GetEventType() == startType, isCorrectPriority); var isEnd = And(hd.GetEventType() == endType, isCorrectPriority); var isEvent = Or(isStart, isEnd); var isInvalid = Or(And(isPreviousStart, isStart), And(Not(isPreviousStart), isEnd)); var previousStart = If(isStart, true, If(isEnd, false, isPreviousStart)); return And(Not(isInvalid), AreStartEndStormsValid(tl, previousStart, priorityClass)); })); }
static Zen <ushort> IsolatedCheckHelper(Zen <IList <bool> > list, Zen <ushort> index, Zen <ushort> quota) { return(list.Case( empty: index, cons: (hd, tl) => If(Not(hd), IsolatedCheckHelper(tl, index, quota), If(quota > 0, IsolatedCheckHelper(tl, index, quota - 1), ushort.MaxValue)))); }