public CNF ConvertToCNF(ISentence aSentence) { // I)mplications Out: ISentence implicationsOut = (ISentence)aSentence.Accept( new ImplicationsOut(), null); // N)egations In: ISentence negationsIn = (ISentence)implicationsOut.Accept( new NegationsIn(), null); // S)tandardize variables: // For sentences like: // (ForAll x P(x)) V (Exists x Q(x)), // which use the same variable name twice, change the name of one of the // variables. ISentence saQuantifiers = (ISentence)negationsIn.Accept( new StandardizeQuantiferVariables(substVisitor), new HashSet <Variable>()); // Remove explicit quantifiers, by skolemizing existentials // and dropping universals: // E)xistentials Out // A)lls Out: ISentence andsAndOrs = (ISentence)saQuantifiers.Accept( new RemoveQuantifiers(parser), new HashSet <Variable>()); // D)istribution // V over ^: ISentence orDistributedOverAnd = (ISentence)andsAndOrs.Accept( new DistributeOrOverAnd(), null); // O)perators Out return((new CNFConstructor()).Construct(orDistributedOverAnd)); }
public object VisitQuantifiedSentence(QuantifiedSentence sentence, object arg) { ISentence quantified = sentence.Quantified; var universalScope = (ISet <Variable>)arg; // Skolemize: Skolemization is the process of removing existential // quantifiers by elimination. This is done by introducing Skolem // functions. The general rule is that the arguments of the Skolem // function are all the universally quantified variables in whose // scope the existential quantifier appears. if (Quantifiers.IsExists(sentence.Quantifier)) { IDictionary <Variable, ITerm> skolemSubst = new Dictionary <Variable, ITerm>(); foreach (Variable eVar in sentence.Variables) { if (universalScope.Count > 0) { // Replace with a Skolem Function var skolemFunctionName = parser.GetFOLDomain() .AddSkolemFunction(); skolemSubst[eVar] = new Function(skolemFunctionName, new List <ITerm>((IEnumerable <ITerm>)universalScope)); } else { // Replace with a Skolem Constant String skolemConstantName = parser.GetFOLDomain() .AddSkolemConstant(); skolemSubst[eVar] = new Constant(skolemConstantName); } } ISentence skolemized = substVisitor.Subst(skolemSubst, quantified); return(skolemized.Accept(this, arg)); } // Drop universal quantifiers. if (Quantifiers.IsForall(sentence.Quantifier)) { // Add to the universal scope so that // existential skolemization may be done correctly universalScope.UnionWith(sentence.Variables); ISentence droppedUniversal = (ISentence)quantified.Accept(this, arg); // Enusre my scope is removed before moving back up // the call stack when returning foreach (var v in sentence.Variables) { universalScope.Remove(v); } return(droppedUniversal); } // Should not reach here as have already // handled the two quantifiers. throw new InvalidOperationException("Unhandled Quantifier:" + sentence.Quantifier); }
// Note: The set guarantees the order in which they were // found. public ISet <Variable> CollectAllVariables(ISentence sentence) { ISet <Variable> variables = new HashedSet <Variable>(); sentence.Accept(this, variables); return(variables); }
public CNF Construct(ISentence orDistributedOverAnd) { var ad = new ArgData(); orDistributedOverAnd.Accept(this, ad); return(new CNF(ad.Clauses)); }
public object VisitConnectedSentence(ConnectedSentence sentence, object arg) { ArgData ad = (ArgData)arg; ISentence first = sentence.First; ISentence second = sentence.Second; first.Accept(this, arg); if (Connectors.IsAnd(sentence.Connector)) { ad.Clauses.Add(new Clause()); } second.Accept(this, arg); return(sentence); }
public object VisitQuantifiedSentence(QuantifiedSentence sentence, object arg) { ISet <Variable> seenSoFar = (ISet <Variable>)arg; // Keep track of what I have to subst locally and // what my renamed variables will be. IDictionary <Variable, ITerm> localSubst = new Dictionary <Variable, ITerm>(); IList <Variable> replVariables = new List <Variable>(); foreach (Variable v in sentence.Variables) { // If local variable has be renamed already // then I need to come up with own name if (seenSoFar.Contains(v)) { var sV = new Variable(quantifiedIndexical.GetPrefix() + quantifiedIndexical.GetNextIndex()); localSubst[v] = sV; // Replacement variables should contain new name for variable replVariables.Add(sV); } else { // Not already replaced, this name is good replVariables.Add(v); } } // Apply the local subst ISentence subst = substVisitor.Subst(localSubst, sentence.Quantified); // Ensure all my existing and replaced variable // names are tracked seenSoFar.UnionWith(replVariables); var sQuantified = (ISentence)subst.Accept(this, arg); return(new QuantifiedSentence(sentence.Quantifier, replVariables, sQuantified)); }
public object VisitNotSentence(NotSentence notSentence, object arg) { ISentence negated = notSentence.Negated; return(new NotSentence((ISentence)negated.Accept(this, arg))); }
public object VisitNotSentence(NotSentence notSentence, object arg) { // CNF requires NOT (~) to appear only in literals, so we 'move ~ // inwards' by repeated application of the following equivalences: ISentence negated = notSentence.Negated; // ~(~alpha) equivalent to alpha (double negation elimination) if (negated is NotSentence) { return(((NotSentence)negated).Negated.Accept(this, arg)); } if (negated is ConnectedSentence) { ConnectedSentence negConnected = (ConnectedSentence)negated; ISentence alpha = negConnected.First; ISentence beta = negConnected.Second; // ~(alpha ^ beta) equivalent to (~alpha V ~beta) (De Morgan) if (Connectors.IsAnd(negConnected.Connector)) { // I need to ensure the ~s are moved in deeper ISentence notAlpha = (ISentence)(new NotSentence(alpha)).Accept( this, arg); ISentence notBeta = (ISentence)(new NotSentence(beta)).Accept( this, arg); return(new ConnectedSentence(Connectors.Or, notAlpha, notBeta)); } // ~(alpha V beta) equivalent to (~alpha ^ ~beta) (De Morgan) if (Connectors.IsOr(negConnected.Connector)) { // I need to ensure the ~s are moved in deeper ISentence notAlpha = (ISentence)(new NotSentence(alpha)).Accept( this, arg); ISentence notBeta = (ISentence)(new NotSentence(beta)).Accept( this, arg); return(new ConnectedSentence(Connectors.And, notAlpha, notBeta)); } } // in addition, rules for negated quantifiers: if (negated is QuantifiedSentence) { QuantifiedSentence negQuantified = (QuantifiedSentence)negated; // I need to ensure the ~ is moved in deeper ISentence notP = (ISentence)(new NotSentence(negQuantified .Quantified)).Accept(this, arg); // ~ForAll x p becomes Exists x ~p if (Quantifiers.IsForall(negQuantified.Quantifier)) { return(new QuantifiedSentence(Quantifiers.Exists, negQuantified .Variables, notP)); } // ~Exists x p becomes ForAll x ~p if (Quantifiers.IsExists(negQuantified.Quantifier)) { return(new QuantifiedSentence(Quantifiers.ForAll, negQuantified .Variables, notP)); } } return(new NotSentence((ISentence)negated.Accept(this, arg))); }
private static void CollectAllVariables(ISentence s, IList <Variable> vars) { s.Accept(_collectAllVariables, vars); }
public IList <Predicate> GetPredicates(ISentence s) { return((IList <Predicate>)s.Accept(this, new List <Predicate>())); }
/// <summary> /// Note: Refer to Artificial Intelligence A Modern Approach (3rd Edition): page 323 /// </summary> /// <param name="theta">a substitution.</param> /// <param name="aSentence">the substitution has been applied to.</param> /// <returns>a new Sentence representing the result of applying the substitution theta to aSentence.</returns> public ISentence Subst(IDictionary <Variable, ITerm> theta, ISentence aSentence) { return((ISentence)aSentence.Accept(this, theta)); }