/// <summary>Check whether give proposition is contradiction</summary> /// <param name="expr">Proposition to check</param> /// <exception cref="InvaildPropositionException"></exception> /// <returns>True if contradiction</returns> public bool IsContradiction(Proposition expr) { if (expr == null || !expr.IsVaild()) { throw new InvalidPropositionException("INVAILD"); } return(GetTrueAssignmentList(expr).Count == 0); }
/// <summary>Find assignment list which each assignment table make give proposition true</summary> /// <param name="expr">Proposition to get true assignment list</param> /// <exception cref="InvaildPropositionException"></exception> /// <returns>Assignment list</returns> public List <Dictionary <string, bool> > GetTrueAssignmentList(Proposition expr) { if (expr == null || !expr.IsVaild()) { throw new InvalidPropositionException("INVAILD"); } trueList = new List <Dictionary <string, bool> >(); GetTrueAssignmentListCore(expr, new Dictionary <string, bool>()); return(trueList); }
/// <summary>Check whether give proposition is tautology</summary> /// <param name="expr">Proposition to check</param> /// <exception cref="InvaildPropositionException"></exception> /// <returns>True if tautology</returns> public bool IsTautology(Proposition expr) { if (expr == null || !expr.IsVaild()) { throw new InvalidPropositionException("INVAILD"); } if (!expr.IsCNF()) { expr = ConvertToCNF(ConvertToNNF(expr)); } return(IsTautologyCore(expr)); }
/// <summary>Check this proposition is vaild</summary> /// <returns>True if vaild</returns> public bool IsVaild() { if (op == Operator.Null) { return(false); } else if (op == Operator.Atom) { return(atom != null); } else if (op == Operator.Not) { return(left != null && left.IsVaild()); } else if (op == Operator.Or || op == Operator.And || op == Operator.Imply || op == Operator.IfOnlyIf) { return(left != null && right != null && left.IsVaild() && right.IsVaild()); } else { return(false); } }
/// <summary>Evaluate proposition with given data</summary> /// <param name="value">Result of evaluation</param> /// <param name="error">Error Message</param> /// <param name="expr">Proposition to evaluate</param> /// <param name="data">Assignment table</param> /// <returns>True if successed evaluate</returns> public bool TryEvaluate(out bool value, out string error, Proposition expr, Dictionary <string, bool> data) { value = false; error = ""; if (expr == null || !expr.IsVaild()) { error = InvalidPropositionException.REASON_INVAILD; return(false); } List <string> atomList = expr.GetAtomList(); List <string> keyList = data.Keys.ToList(); if (atomList.Intersect(keyList).Count() != atomList.Count) { error = "모든 atom에 대해 적절한 대입값이 없습니다."; return(false); } evalData = data; value = Evaluate(expr); return(true); }
/// <summary>Convert given proposition to negative normal form</summary> /// <param name="expr">Proposition to convert</param> /// <exception cref="InvaildPropositionException"></exception> /// <returns>NNF proposition</returns> public Proposition ConvertToNNF(Proposition expr) { if (expr == null || !expr.IsVaild()) { throw new InvalidPropositionException("INVAILD"); } if (expr.op == Operator.Atom) { return(expr); } else if (expr.op == Operator.Or) // S(P|Q) => S(P)|S(Q) { return(new Proposition(Operator.Or, ConvertToNNF(expr.left), ConvertToNNF(expr.right))); } else if (expr.op == Operator.And) // S(P&Q) => S(P)&S(Q) { return(new Proposition(Operator.And, ConvertToNNF(expr.left), ConvertToNNF(expr.right))); } else if (expr.op == Operator.Imply) // S(P->Q) => S(~P)|S(Q) { return(new Proposition(Operator.Or, ConvertToNNF(new Proposition(Operator.Not, expr.left)), ConvertToNNF(expr.right))); } else if (expr.op == Operator.IfOnlyIf) // S(P<->Q) => S(P->Q)&S(Q->P) { return(new Proposition(Operator.And, ConvertToNNF(new Proposition(Operator.Imply, expr.left, expr.right)), ConvertToNNF(new Proposition(Operator.Imply, expr.right, expr.left)))); } else if (expr.op == Operator.Not) // S(~P) => { Proposition nexpr = expr.left; if (nexpr.op == Operator.Atom) // S(T) => F, S(F) => T, S(~P) => ~P { if (nexpr.atom.Symbol == "T") { return(new Proposition(Operator.Atom, new Atom("F"))); } else if (nexpr.atom.Symbol == "F") { return(new Proposition(Operator.Atom, new Atom("T"))); } else { return(expr); } } if (nexpr.op == Operator.Imply) // S(P->Q) => S(~P)|S(Q) { nexpr = new Proposition(Operator.Or, ConvertToNNF(new Proposition(Operator.Not, nexpr.left)), ConvertToNNF(nexpr.right)); } else if (nexpr.op == Operator.IfOnlyIf) // S(P<->Q) => S(P->Q)&S(Q->P) { nexpr = new Proposition(Operator.And, ConvertToNNF(new Proposition(Operator.Imply, nexpr.left, nexpr.right)), ConvertToNNF(new Proposition(Operator.Imply, nexpr.right, nexpr.left))); } if (nexpr.op == Operator.Or) // S(~(P|Q)) => ~S(P)&~S(Q) { return(new Proposition(Operator.And, ConvertToNNF(new Proposition(Operator.Not, nexpr.left)), ConvertToNNF(new Proposition(Operator.Not, nexpr.right)))); } else if (nexpr.op == Operator.And) // S(~(P&Q)) => ~S(P)|~S(Q) { return(new Proposition(Operator.Or, ConvertToNNF(new Proposition(Operator.Not, nexpr.left)), ConvertToNNF(new Proposition(Operator.Not, nexpr.right)))); } else if (nexpr.op == Operator.Not) // S(~(~P))) => S(P) { return(ConvertToNNF(nexpr.left)); } } return(null); }