public void SetParents(MuFormula parent) { Parent = parent; foreach (var f in SubFormulas) { f.SetParents(this); } }
private static void OutputResult(MuFormula f, LTS lts) { Log("Formula {0}", f); Log("\t ND: {0}, AD: {1}, DAD: {2}", f.NestingDepth, f.AlternationDepth, f.DependentAlternationDepth); var naiveSol = NaiveSolver.Solve(f, lts, new Environment()); Log("\tNAIVE: {0}", naiveSol.Contains(lts.InitialState)); var emersonLeiSol = EmersonLei.Solve(f, lts, new Environment()); Log("\tEMLEI: {0}", emersonLeiSol.Contains(lts.InitialState)); }
static MuFormula RewriteBoxDia(MuFormula form) { // We extended our grammar from the assignment by allowing regular formulas instead of single-letter actions. // Here, we rewrite such extended formulas to their more primitive versions for which we impemented evaluators. if (form is Diamond) { var dia = form as Diamond; if (dia.RegularFormula.Multiplier == "+") { // <R+>f = <R><R*>f var rf2 = dia.RegularFormula.Clone(); rf2.Multiplier = "*"; dia.RegularFormula.Multiplier = ""; dia.Formula = new Diamond(dia.RegularFormula, new Diamond(rf2, dia.Formula)); } else if (dia.RegularFormula.Multiplier == "*") { // <R*>f = mu X . (<R> X || f) var var = new Variable(GetFreeVar()); dia.RegularFormula.Multiplier = ""; return Rewrite(new Mu(var, new Disjunction(new Diamond(dia.RegularFormula, var), dia.Formula))); } dia.Formula = Rewrite(dia.Formula); } else if (form is Box) { var box = form as Box; if (box.RegularFormula.Multiplier == "+") { // [R+]f = [R][R*]f var rf2 = box.RegularFormula.Clone(); rf2.Multiplier = "*"; box.RegularFormula.Multiplier = ""; return new Box(box.RegularFormula, new Box(rf2, box.Formula)); } else if (box.RegularFormula.Multiplier == "*") { // [R*]f = nu X . ([R] X && f) var var = new Variable(GetFreeVar()); box.RegularFormula.Multiplier = ""; return Rewrite(new Nu(var, new Disjunction(new Box(box.RegularFormula, var), box.Formula))); } box.Formula = Rewrite(box.Formula); } // we also need to perform this on all subformulas else if (form is Disjunction) form = new Disjunction(Rewrite(((Disjunction)form).Left), Rewrite(((Disjunction)form).Right)); else if (form is Conjunction) form = new Conjunction(Rewrite(((Conjunction)form).Left), Rewrite(((Conjunction)form).Right)); else if (form is Mu) form = new Mu(((Mu)form).Variable, Rewrite(((Mu)form).Formula)); else if (form is Nu) form = new Nu(((Nu)form).Variable, Rewrite(((Nu)form).Formula)); else if (form is Negation) form = new Negation(Rewrite(((Negation)form).Formula)); return form; }
public bool IsBound(MuFormula subFormula) { // returns whether this variable is bound in the given subformula var parent = Parent; do { if (parent is Mu && ((Mu)parent).Formula.Equals(this)) { return(true); } else if (parent is Nu && ((Nu)parent).Formula.Equals(this)) { return(true); } parent = parent.Parent; } while (parent != subFormula); return(false); }
public void SetParents(MuFormula parent) { Parent = parent; foreach (var f in SubFormulas) f.SetParents(this); }
public Diamond(RegularFormula regForm, MuFormula formula) { RegularFormula = regForm; Formula = formula; }
public Disjunction(MuFormula left, MuFormula right) { Left = left; Right = right; }
public Nu(Variable var, MuFormula pred) { Variable = var; Formula = pred; }
public Box(RegularFormula regForm, MuFormula formula) { RegularFormula = regForm; Formula = formula; }
public Mu(Variable var, MuFormula pred) { Variable = var; Formula = pred; }
public static MuFormula Rewrite(MuFormula form) { form = RewriteBoxDia(form); form = RewriteRFs(form); return(form); }
// rewrite regular formulas inside box/diamond to multiple boxes/diamonds static MuFormula RewriteRFs(MuFormula form) { // connectives on regular formulas // <a.rf>f = <a><rf>f if (form is Box) { var box = form as Box; // [rf1+rf2]f = [rf1]f || [rf2]f /*if (box.RegularFormula is UnionFormula) { * var un = box.RegularFormula as UnionFormula; * return Rewrite(new Disjunction(new Box(un.Left, box.Formula), new Box(un.Right, box.Formula))); * }*/ // directly supported by RegularFormula now! // [a.rf]f = [a][rf]f if (box.RegularFormula is SequenceFormula) { var seq = box.RegularFormula as SequenceFormula; return(Rewrite(new Box(seq.First, new Box(seq.Sequence, RewriteRFs(box.Formula))))); } // by now all *s should be gone, so we can rewrite // [(a.b)] to [a.b] else if (box.RegularFormula is NestedFormula) { var nested = box.RegularFormula as NestedFormula; if (nested.Multiplier != "") { throw new InvalidProgramException("by now all multipliers should have been removed"); } box.RegularFormula = nested.Inner; return(Rewrite(box)); } } else if (form is Diamond) { var dia = form as Diamond; // <rf1+rf2>f = <[rf1>f || <rf2>f /*if (dia.RegularFormula is UnionFormula) { * var un = dia.RegularFormula as UnionFormula; * return Rewrite(new Disjunction(new Diamond(un.Left, dia.Formula), new Diamond(un.Right, dia.Formula))); * }*/ // directly supported now! // <a.rf>f = <a><rf>f if (dia.RegularFormula is SequenceFormula) { var seq = dia.RegularFormula as SequenceFormula; dia.RegularFormula = seq.First; dia.Formula = new Diamond(seq.Sequence, dia.Formula); return(Rewrite(dia)); } else if (dia.RegularFormula is NestedFormula) { var nested = dia.RegularFormula as NestedFormula; if (nested.Multiplier != "") { throw new InvalidProgramException("by now all multipliers should have been removed"); } dia.RegularFormula = nested.Inner; return(Rewrite(dia)); } } // we also need to perform this on all subformulas else if (form is Disjunction) { form = new Disjunction(Rewrite(((Disjunction)form).Left), Rewrite(((Disjunction)form).Right)); } else if (form is Conjunction) { form = new Conjunction(Rewrite(((Conjunction)form).Left), Rewrite(((Conjunction)form).Right)); } else if (form is Mu) { form = new Mu(((Mu)form).Variable, Rewrite(((Mu)form).Formula)); } else if (form is Nu) { form = new Nu(((Nu)form).Variable, Rewrite(((Nu)form).Formula)); } return(form); }
static MuFormula RewriteBoxDia(MuFormula form) { // We extended our grammar from the assignment by allowing regular formulas instead of single-letter actions. // Here, we rewrite such extended formulas to their more primitive versions for which we impemented evaluators. if (form is Diamond) { var dia = form as Diamond; if (dia.RegularFormula.Multiplier == "+") { // <R+>f = <R><R*>f var rf2 = dia.RegularFormula.Clone(); rf2.Multiplier = "*"; dia.RegularFormula.Multiplier = ""; dia.Formula = new Diamond(dia.RegularFormula, new Diamond(rf2, dia.Formula)); } else if (dia.RegularFormula.Multiplier == "*") { // <R*>f = mu X . (<R> X || f) var var = new Variable(GetFreeVar()); dia.RegularFormula.Multiplier = ""; return(Rewrite(new Mu(var, new Disjunction(new Diamond(dia.RegularFormula, var), dia.Formula)))); } dia.Formula = Rewrite(dia.Formula); } else if (form is Box) { var box = form as Box; if (box.RegularFormula.Multiplier == "+") { // [R+]f = [R][R*]f var rf2 = box.RegularFormula.Clone(); rf2.Multiplier = "*"; box.RegularFormula.Multiplier = ""; return(new Box(box.RegularFormula, new Box(rf2, box.Formula))); } else if (box.RegularFormula.Multiplier == "*") { // [R*]f = nu X . ([R] X && f) var var = new Variable(GetFreeVar()); box.RegularFormula.Multiplier = ""; return(Rewrite(new Nu(var, new Disjunction(new Box(box.RegularFormula, var), box.Formula)))); } box.Formula = Rewrite(box.Formula); } // we also need to perform this on all subformulas else if (form is Disjunction) { form = new Disjunction(Rewrite(((Disjunction)form).Left), Rewrite(((Disjunction)form).Right)); } else if (form is Conjunction) { form = new Conjunction(Rewrite(((Conjunction)form).Left), Rewrite(((Conjunction)form).Right)); } else if (form is Mu) { form = new Mu(((Mu)form).Variable, Rewrite(((Mu)form).Formula)); } else if (form is Nu) { form = new Nu(((Nu)form).Variable, Rewrite(((Nu)form).Formula)); } else if (form is Negation) { form = new Negation(Rewrite(((Negation)form).Formula)); } return(form); }
public static HashSet <LTSState> Solve(MuFormula formula, LTS lts, Environment env, bool init = true) { if (init) { var allVariables = new List <Variable>(); if (formula is Variable) { allVariables.Add((Variable)formula); } allVariables.AddRange(formula.AllSubFormulas.OfType <Variable>()); allVariables.AddRange(formula.AllSubFormulas.OfType <Mu>().Select(mu => mu.Variable)); allVariables.AddRange(formula.AllSubFormulas.OfType <Nu>().Select(nu => nu.Variable)); Init(allVariables.Distinct(), lts, env); } if (formula is Proposition) { var prop = formula as Proposition; return(bool.Parse(prop.Value) ? lts.States : new HashSet <LTSState>()); } else if (formula is Variable) { return(env.GetVariable(formula as Variable)); } else if (formula is Negation) { var neg = formula as Negation; return(new HashSet <LTSState>(lts.States.Except( Solve(neg.Formula, lts, env, false)))); } else if (formula is Conjunction) { var conj = formula as Conjunction; var leftStates = Solve(conj.Left, lts, env, false); var rightStates = Solve(conj.Right, lts, env, false); return(new HashSet <LTSState>(leftStates.Intersect(rightStates))); } else if (formula is Disjunction) { var disj = formula as Disjunction; var leftStates = Solve(disj.Left, lts, env, false); var rightStates = Solve(disj.Right, lts, env, false); return(new HashSet <LTSState>(leftStates.Union(rightStates))); } else if (formula is Box) { var box = formula as Box; // box a f = { s | forall t. s -a-> t ==> t in [[f]]e } // i.e. the set of states for which all a-transitions go to a state in which f holds var fe = Solve(box.Formula, lts, env, false); var hashSet = new HashSet <LTSState>(); foreach (var state in lts.States) { var outTransitions = state.GetOutTransitions(box.RegularFormula); if (outTransitions.All(tr => fe.Contains(tr.Right))) { hashSet.Add(state); } } return(hashSet); } else if (formula is Diamond) { var diamond = formula as Diamond; var shorthand = new Negation( // <a>f == [a](not f) new Box(diamond.RegularFormula, new Negation(diamond.Formula)) ); return(Solve(shorthand, lts, env, false)); } else if (formula is Mu) { var mu = formula as Mu; if (mu.Parent is Nu) { // surrounding binder is nu // reset open subformulae of form mu Xk.g set env[k]=false foreach (var innerMu in formula.AllSubFormulas.OfType <Mu>().Where(m => m.FreeVariables.Count > 0)) { env[innerMu.Variable] = new HashSet <LTSState>(); } } HashSet <LTSState> Xold; do { Xold = env.GetVariable(mu.Variable); env[mu.Variable] = Solve(mu.Formula, lts, env, false); } while (Xold.Count != env[mu.Variable].Count); return(env[mu.Variable]); } else if (formula is Nu) { var nu = formula as Nu; if (nu.Parent is Mu) { // surrounding binder is mu // reset open subformulae of form nu Xk.g set env[k]=true foreach (var innerNu in formula.AllSubFormulas.OfType <Nu>().Where(m => m.FreeVariables.Count > 0)) { env[innerNu.Variable] = lts.States; } } HashSet <LTSState> Xold; do { Xold = env.GetVariable(nu.Variable); env[nu.Variable] = Solve(nu.Formula, lts, env, false); } while (Xold.Count != env[nu.Variable].Count); return(env[nu.Variable]); } throw new InvalidDataException("formula not valid in our grammar"); }
public static HashSet<LTSState> Solve(MuFormula formula, LTS lts, Environment env) { if (formula is Proposition) { var prop = formula as Proposition; return bool.Parse(prop.Value) ? lts.States : new HashSet<LTSState>(); } else if (formula is Variable) { return env.GetVariable(formula as Variable); } else if (formula is Negation) { var neg = formula as Negation; return new HashSet<LTSState>(lts.States.Except( Solve(neg.Formula, lts, env))); } else if (formula is Conjunction) { var conj = formula as Conjunction; var leftStates = Solve(conj.Left, lts, env); var rightStates = Solve(conj.Right, lts, env); return new HashSet<LTSState>(leftStates.Intersect(rightStates)); } else if (formula is Disjunction) { var disj = formula as Disjunction; var leftStates = Solve(disj.Left, lts, env); var rightStates = Solve(disj.Right, lts, env); return new HashSet<LTSState>(leftStates.Union(rightStates)); } else if (formula is Box) { var box = formula as Box; // box a f = { s | forall t. s -a-> t ==> t in [[f]]e } // i.e. the set of states for which all a-transitions go to a state in which f holds var fe = Solve(box.Formula, lts, env); return new HashSet<LTSState>(lts.States.Where( // states where, for all outtransitions with action a, the Formula holds in the direct successor state => state.GetOutTransitions(box.RegularFormula).All(tr => fe.Contains(tr.Right)) )); } else if (formula is Diamond) { var diamond = formula as Diamond; var shorthand = new Negation( // <a>f == [a](not f) new Box(diamond.RegularFormula, new Negation(diamond.Formula)) ); return Solve(shorthand, lts, env); } else if (formula is Mu) { var mu = formula as Mu; env[mu.Variable] = new HashSet<LTSState>(); return FixedPoint.LFP(delegate(Tuple<HashSet<LTSState>, LTS, Environment> tuple) { // repeats tau: X := solve(f) var X = tuple.Item1; X = Solve(mu.Formula, lts, env); env[mu.Variable] = X; return Tuple.Create(X, lts, env); }, lts, env); } else if (formula is Nu) { var nu = formula as Nu; env[nu.Variable] = lts.States; return FixedPoint.GFP(delegate(Tuple<HashSet<LTSState>, LTS, Environment> tuple) { // repeats tau: X := solve(f) var X = tuple.Item1; X = Solve(nu.Formula, lts, env); env[nu.Variable] = X; return Tuple.Create(X, lts, env); }, lts, env); } throw new InvalidDataException("not a valid formula in our grammar"); }
public Negation(MuFormula formula) { Formula = formula; }
public bool IsBound(MuFormula subFormula) { // returns whether this variable is bound in the given subformula var parent = Parent; do { if (parent is Mu && ((Mu)parent).Formula.Equals(this)) return true; else if (parent is Nu && ((Nu)parent).Formula.Equals(this)) return true; parent = parent.Parent; } while (parent != subFormula); return false; }
public static HashSet<LTSState> Solve(MuFormula formula, LTS lts, Environment env, bool init = true) { if (init) { var allVariables = new List<Variable>(); if (formula is Variable) allVariables.Add((Variable)formula); allVariables.AddRange(formula.AllSubFormulas.OfType<Variable>()); allVariables.AddRange(formula.AllSubFormulas.OfType<Mu>().Select(mu => mu.Variable)); allVariables.AddRange(formula.AllSubFormulas.OfType<Nu>().Select(nu => nu.Variable)); Init(allVariables.Distinct(), lts, env); } if (formula is Proposition) { var prop = formula as Proposition; return bool.Parse(prop.Value) ? lts.States : new HashSet<LTSState>(); } else if (formula is Variable) { return env.GetVariable(formula as Variable); } else if (formula is Negation) { var neg = formula as Negation; return new HashSet<LTSState>(lts.States.Except( Solve(neg.Formula, lts, env, false))); } else if (formula is Conjunction) { var conj = formula as Conjunction; var leftStates = Solve(conj.Left, lts, env, false); var rightStates = Solve(conj.Right, lts, env, false); return new HashSet<LTSState>(leftStates.Intersect(rightStates)); } else if (formula is Disjunction) { var disj = formula as Disjunction; var leftStates = Solve(disj.Left, lts, env, false); var rightStates = Solve(disj.Right, lts, env, false); return new HashSet<LTSState>(leftStates.Union(rightStates)); } else if (formula is Box) { var box = formula as Box; // box a f = { s | forall t. s -a-> t ==> t in [[f]]e } // i.e. the set of states for which all a-transitions go to a state in which f holds var fe = Solve(box.Formula, lts, env, false); var hashSet = new HashSet<LTSState>(); foreach (var state in lts.States) { var outTransitions = state.GetOutTransitions(box.RegularFormula); if (outTransitions.All(tr => fe.Contains(tr.Right))) hashSet.Add(state); } return hashSet; } else if (formula is Diamond) { var diamond = formula as Diamond; var shorthand = new Negation( // <a>f == [a](not f) new Box(diamond.RegularFormula, new Negation(diamond.Formula)) ); return Solve(shorthand, lts, env, false); } else if (formula is Mu) { var mu = formula as Mu; if (mu.Parent is Nu) { // surrounding binder is nu // reset open subformulae of form mu Xk.g set env[k]=false foreach (var innerMu in formula.AllSubFormulas.OfType<Mu>().Where(m => m.FreeVariables.Count > 0)) env[innerMu.Variable] = new HashSet<LTSState>(); } HashSet<LTSState> Xold; do { Xold = env.GetVariable(mu.Variable); env[mu.Variable] = Solve(mu.Formula, lts, env, false); } while (Xold.Count != env[mu.Variable].Count); return env[mu.Variable]; } else if (formula is Nu) { var nu = formula as Nu; if (nu.Parent is Mu) { // surrounding binder is mu // reset open subformulae of form nu Xk.g set env[k]=true foreach (var innerNu in formula.AllSubFormulas.OfType<Nu>().Where(m => m.FreeVariables.Count > 0)) env[innerNu.Variable] = lts.States; } HashSet<LTSState> Xold; do { Xold = env.GetVariable(nu.Variable); env[nu.Variable] = Solve(nu.Formula, lts, env, false); } while (Xold.Count != env[nu.Variable].Count); return env[nu.Variable]; } throw new InvalidDataException("formula not valid in our grammar"); }
public static MuFormula Rewrite(MuFormula form) { form = RewriteBoxDia(form); form = RewriteRFs(form); return form; }
public static HashSet <LTSState> Solve(MuFormula formula, LTS lts, Environment env) { if (formula is Proposition) { var prop = formula as Proposition; return(bool.Parse(prop.Value) ? lts.States : new HashSet <LTSState>()); } else if (formula is Variable) { return(env.GetVariable(formula as Variable)); } else if (formula is Negation) { var neg = formula as Negation; return(new HashSet <LTSState>(lts.States.Except( Solve(neg.Formula, lts, env)))); } else if (formula is Conjunction) { var conj = formula as Conjunction; var leftStates = Solve(conj.Left, lts, env); var rightStates = Solve(conj.Right, lts, env); return(new HashSet <LTSState>(leftStates.Intersect(rightStates))); } else if (formula is Disjunction) { var disj = formula as Disjunction; var leftStates = Solve(disj.Left, lts, env); var rightStates = Solve(disj.Right, lts, env); return(new HashSet <LTSState>(leftStates.Union(rightStates))); } else if (formula is Box) { var box = formula as Box; // box a f = { s | forall t. s -a-> t ==> t in [[f]]e } // i.e. the set of states for which all a-transitions go to a state in which f holds var fe = Solve(box.Formula, lts, env); return(new HashSet <LTSState>(lts.States.Where( // states where, for all outtransitions with action a, the Formula holds in the direct successor state => state.GetOutTransitions(box.RegularFormula).All(tr => fe.Contains(tr.Right)) ))); } else if (formula is Diamond) { var diamond = formula as Diamond; var shorthand = new Negation( // <a>f == [a](not f) new Box(diamond.RegularFormula, new Negation(diamond.Formula)) ); return(Solve(shorthand, lts, env)); } else if (formula is Mu) { var mu = formula as Mu; env[mu.Variable] = new HashSet <LTSState>(); return(FixedPoint.LFP(delegate(Tuple <HashSet <LTSState>, LTS, Environment> tuple) { // repeats tau: X := solve(f) var X = tuple.Item1; X = Solve(mu.Formula, lts, env); env[mu.Variable] = X; return Tuple.Create(X, lts, env); }, lts, env)); } else if (formula is Nu) { var nu = formula as Nu; env[nu.Variable] = lts.States; return(FixedPoint.GFP(delegate(Tuple <HashSet <LTSState>, LTS, Environment> tuple) { // repeats tau: X := solve(f) var X = tuple.Item1; X = Solve(nu.Formula, lts, env); env[nu.Variable] = X; return Tuple.Create(X, lts, env); }, lts, env)); } throw new InvalidDataException("not a valid formula in our grammar"); }
// rewrite regular formulas inside box/diamond to multiple boxes/diamonds static MuFormula RewriteRFs(MuFormula form) { // connectives on regular formulas // <a.rf>f = <a><rf>f if (form is Box) { var box = form as Box; // [rf1+rf2]f = [rf1]f || [rf2]f /*if (box.RegularFormula is UnionFormula) { var un = box.RegularFormula as UnionFormula; return Rewrite(new Disjunction(new Box(un.Left, box.Formula), new Box(un.Right, box.Formula))); }*/ // directly supported by RegularFormula now! // [a.rf]f = [a][rf]f if (box.RegularFormula is SequenceFormula) { var seq = box.RegularFormula as SequenceFormula; return Rewrite(new Box(seq.First, new Box(seq.Sequence, RewriteRFs(box.Formula)))); } // by now all *s should be gone, so we can rewrite // [(a.b)] to [a.b] else if (box.RegularFormula is NestedFormula) { var nested = box.RegularFormula as NestedFormula; if (nested.Multiplier != "") throw new InvalidProgramException("by now all multipliers should have been removed"); box.RegularFormula = nested.Inner; return Rewrite(box); } } else if (form is Diamond) { var dia = form as Diamond; // <rf1+rf2>f = <[rf1>f || <rf2>f /*if (dia.RegularFormula is UnionFormula) { var un = dia.RegularFormula as UnionFormula; return Rewrite(new Disjunction(new Diamond(un.Left, dia.Formula), new Diamond(un.Right, dia.Formula))); }*/ // directly supported now! // <a.rf>f = <a><rf>f if (dia.RegularFormula is SequenceFormula) { var seq = dia.RegularFormula as SequenceFormula; dia.RegularFormula = seq.First; dia.Formula = new Diamond(seq.Sequence, dia.Formula); return Rewrite(dia); } else if (dia.RegularFormula is NestedFormula) { var nested = dia.RegularFormula as NestedFormula; if (nested.Multiplier != "") throw new InvalidProgramException("by now all multipliers should have been removed"); dia.RegularFormula = nested.Inner; return Rewrite(dia); } } // we also need to perform this on all subformulas else if (form is Disjunction) form = new Disjunction(Rewrite(((Disjunction)form).Left), Rewrite(((Disjunction)form).Right)); else if (form is Conjunction) form = new Conjunction(Rewrite(((Conjunction)form).Left), Rewrite(((Conjunction)form).Right)); else if (form is Mu) form = new Mu(((Mu)form).Variable, Rewrite(((Mu)form).Formula)); else if (form is Nu) form = new Nu(((Nu)form).Variable, Rewrite(((Nu)form).Formula)); return form; }