示例#1
0
        /// <summary>
        /// Returns empty list if the terms in the equation cannot be unified or if Lhs = Rhs with no variables,
        /// otherwise a list of substitutions defining the MGU
        /// 
        /// Based on Unification chapter from Handbook of Automated Reasoning.
        /// </summary>
        private List<UnificationResult> GetMgu(Equation unificationProblem, List<TrsVariable> variableNamesToPreserve)
        {
            if (unificationProblem == null) throw new ArgumentException();
              if (unificationProblem.Lhs == null) throw new ArgumentException();
              if (unificationProblem.Rhs == null) throw new ArgumentException();
              if (variableNamesToPreserve == null) throw new ArgumentException();

              Equation initialEquation = unificationProblem.CreateCopy();
              UnificationContinuation currentProblem = new UnificationContinuation
              {
            CurrentEquations = new List<Equation>(),
            CurrentSubstitutions = new List<Substitution>()
              };
              currentProblem.CurrentEquations.Add(initialEquation);
              Queue<UnificationContinuation> currentContinuations = new Queue<UnificationContinuation>();
              currentContinuations.Enqueue(currentProblem);
              HashSet<UnificationResult> results = new HashSet<UnificationResult>();

              Func<UnificationContinuation, Equation, bool> processFail = delegate (UnificationContinuation curr, Equation currEq)
              {
            var failResult = CustomFail(currentProblem, currEq, variableNamesToPreserve);
            var succeed = true;
            if (failResult.Count == 0) succeed = false;
            else if (failResult.Count == 1) currentProblem = failResult.First();
            else foreach (var continuation in failResult) currentContinuations.Enqueue(continuation);
            return succeed;
              };

              while (currentContinuations.Count > 0)
              {
            currentProblem = currentContinuations.Dequeue();
            bool fail = false;
            while (currentProblem.CurrentEquations.Count > 0 && !fail)
            {
              var currEq = currentProblem.CurrentEquations[currentProblem.CurrentEquations.Count - 1];
              currentProblem.CurrentEquations.RemoveAt(currentProblem.CurrentEquations.Count - 1);
              if (currEq.Lhs.Equals(currEq.Rhs))
              {
            // Elimination by omission (this is a "succeed" case)
              }
              else if (currEq.Lhs is TrsAtom && currEq.Rhs is TrsAtom)
              {
            if (!currEq.Lhs.Equals(currEq.Rhs)) {
              fail = !processFail(currentProblem, currEq);
            }
              }
              else if (currEq.Lhs is TrsAtom && currEq.Rhs is TrsTerm
            || currEq.Lhs is TrsTerm && currEq.Rhs is TrsAtom
            || currEq.Lhs is TrsAtom && currEq.Rhs is TrsAcTerm
            || currEq.Lhs is TrsAcTerm && currEq.Rhs is TrsAtom
            || currEq.Lhs is TrsTerm && currEq.Rhs is TrsAcTerm
            || currEq.Lhs is TrsAcTerm && currEq.Rhs is TrsTerm)
              {
            fail = !processFail(currentProblem, currEq);
              }
              else if (currEq.Lhs is TrsTerm && currEq.Rhs is TrsTerm)
              {
            TrsTerm lhs = currEq.Lhs as TrsTerm;
            TrsTerm rhs = currEq.Rhs as TrsTerm;
            if (lhs.Name != rhs.Name || lhs.Arguments.Count != rhs.Arguments.Count)
              fail = !processFail(currentProblem, currEq);
            else
              currentProblem.CurrentEquations.AddRange(Enumerable.Range(0, lhs.Arguments.Count).
                Select(i => new Equation { Lhs = lhs.Arguments[i], Rhs = rhs.Arguments[i] }));
              }
              else if (currEq.Lhs is TrsAcTerm && currEq.Rhs is TrsAcTerm)
              {
            // Note: Failure is already processed internally in the next function call (ie. custom unifiers are called)
            fail = ProcessAcUnificationStep(currentProblem, currentContinuations, processFail, currEq);
              }
              else if (!(currEq.Lhs is TrsVariable) && (currEq.Rhs is TrsVariable))
              {
            TrsTermBase lhsSwap = currEq.Lhs;
            currEq.Lhs = currEq.Rhs;
            currEq.Rhs = lhsSwap;
            currentProblem.CurrentEquations.Add(currEq);
              }
              else if (currEq.Lhs is TrsVariable)
              {
            // Occurs check
            if (currEq.Rhs.ContainsVariable((TrsVariable)currEq.Lhs))
              fail = !processFail(currentProblem, currEq);
            else ProcessSubstitutionStep(currentProblem, currEq, variableNamesToPreserve);
              }
              else throw new Exception("Invalid program state");
            }
            if (!fail)
              results.Add(new UnificationResult
              {
            Succeed = true,
            Unifier = currentProblem.CurrentSubstitutions
              });
              }
              return results.ToList();
        }
示例#2
0
        /// <summary>
        /// Applies the custom unifiers for the current equation in case of failiure ...
        /// it applies the first working unifier from the list of custom unifiers.
        /// </summary>
        private List <UnificationContinuation> CustomFail(UnificationContinuation currentProblem, Equation currEq, List <TrsVariable> variableNamesToPreserve)
        {
            // First try custom unifiers ... use the first one that works.
            HashSet <UnificationResult> unificationResults = new HashSet <UnificationResult>();

            foreach (var unifFunc in customUnifiers)
            {
                // Prevent overwriting of input terms ...
                var input    = currEq.CreateCopy();
                var unifiers = unifFunc.GetUnifier(input.Lhs, input.Rhs);
                if (unifiers != null)
                {
                    foreach (var result in unifiers)
                    {
                        if (result.Succeed)
                        {
                            if (result.Unifier == null)
                            {
                                result.Unifier = new List <Substitution>();
                            }
                            unificationResults.Add(result);
                        }
                    }
                }
            }
            unificationResults = new HashSet <UnificationResult>(unificationResults.Where(result => result.Succeed));
            if (unificationResults.Count == 0)
            {
                return(new List <UnificationContinuation>());
            }
            else
            {
                var retContinuations = new HashSet <UnificationContinuation>();
                foreach (var customUnifier in unificationResults)
                {
                    bool succeed = true;
                    foreach (var customSubstitution in customUnifier.Unifier)
                    {
                        // Do occurs check
                        if (customSubstitution.SubstitutionTerm.ContainsVariable(customSubstitution.Variable))
                        {
                            succeed = false;
                            break;
                        }
                        // Prevent conflicting mappings
                        foreach (var substitution in currentProblem.CurrentSubstitutions)
                        {
                            if (substitution.Variable.Equals(customSubstitution.Variable) &&
                                !substitution.SubstitutionTerm.Equals(customSubstitution.SubstitutionTerm))
                            {
                                succeed = false;
                                break;
                            }
                        }
                    }
                    // Apply the subtitutions
                    if (succeed)
                    {
                        // Create continuations here for injection back into the main algorithm loop
                        UnificationContinuation currentContinuation = currentProblem.CreateCopy();
                        foreach (var substitution in customUnifier.Unifier)
                        {
                            ProcessSubstitutionStep(currentContinuation, new Equation {
                                Lhs = substitution.Variable, Rhs = substitution.SubstitutionTerm
                            }, variableNamesToPreserve);
                        }
                        retContinuations.Add(currentContinuation);
                    }
                }
                return(retContinuations.ToList());
            }
        }
示例#3
0
 /// <summary>
 /// Applies the custom unifiers for the current equation in case of failiure ... 
 /// it applies the first working unifier from the list of custom unifiers.
 /// </summary>
 private List<UnificationContinuation> CustomFail(UnificationContinuation currentProblem, Equation currEq, List<TrsVariable> variableNamesToPreserve)
 {
     // First try custom unifiers ... use the first one that works.
       HashSet<UnificationResult> unificationResults = new HashSet<UnificationResult>();
       foreach (var unifFunc in customUnifiers)
       {
     // Prevent overwriting of input terms ...
     var input = currEq.CreateCopy();
     var unifiers = unifFunc.GetUnifier(input.Lhs, input.Rhs);
     if (unifiers != null)
     {
       foreach (var result in unifiers)
     if (result.Succeed)
     {
       if (result.Unifier == null) result.Unifier = new List<Substitution>();
       unificationResults.Add(result);
     }
     }
       }
       unificationResults = new HashSet<UnificationResult>(unificationResults.Where(result => result.Succeed));
       if (unificationResults.Count == 0)
       {
     return new List<UnificationContinuation>();
       }
       else
       {
     var retContinuations = new HashSet<UnificationContinuation>();
     foreach (var customUnifier in unificationResults)
     {
       bool succeed = true;
       foreach (var customSubstitution in customUnifier.Unifier)
       {
     // Do occurs check
     if (customSubstitution.SubstitutionTerm.ContainsVariable(customSubstitution.Variable))
     {
       succeed = false;
       break;
     }
     // Prevent conflicting mappings
     foreach (var substitution in currentProblem.CurrentSubstitutions)
     {
       if (substitution.Variable.Equals(customSubstitution.Variable)
         && !substitution.SubstitutionTerm.Equals(customSubstitution.SubstitutionTerm))
       {
         succeed = false;
         break;
       }
     }
       }
       // Apply the subtitutions
       if (succeed)
       {
     // Create continuations here for injection back into the main algorithm loop
     UnificationContinuation currentContinuation = currentProblem.CreateCopy();
     foreach (var substitution in customUnifier.Unifier)
       ProcessSubstitutionStep(currentContinuation, new Equation { Lhs = substitution.Variable, Rhs = substitution.SubstitutionTerm }, variableNamesToPreserve);
     retContinuations.Add(currentContinuation);
       }
     }
     return retContinuations.ToList();
       }
 }
示例#4
0
        /// <summary>
        /// Returns empty list if the terms in the equation cannot be unified or if Lhs = Rhs with no variables,
        /// otherwise a list of substitutions defining the MGU
        ///
        /// Based on Unification chapter from Handbook of Automated Reasoning.
        /// </summary>
        private List <UnificationResult> GetMgu(Equation unificationProblem, List <TrsVariable> variableNamesToPreserve)
        {
            if (unificationProblem == null)
            {
                throw new ArgumentException();
            }
            if (unificationProblem.Lhs == null)
            {
                throw new ArgumentException();
            }
            if (unificationProblem.Rhs == null)
            {
                throw new ArgumentException();
            }
            if (variableNamesToPreserve == null)
            {
                throw new ArgumentException();
            }

            Equation initialEquation = unificationProblem.CreateCopy();
            UnificationContinuation currentProblem = new UnificationContinuation
            {
                CurrentEquations     = new List <Equation>(),
                CurrentSubstitutions = new List <Substitution>()
            };

            currentProblem.CurrentEquations.Add(initialEquation);
            Queue <UnificationContinuation> currentContinuations = new Queue <UnificationContinuation>();

            currentContinuations.Enqueue(currentProblem);
            HashSet <UnificationResult> results = new HashSet <UnificationResult>();

            Func <UnificationContinuation, Equation, bool> processFail = delegate(UnificationContinuation curr, Equation currEq)
            {
                var failResult = CustomFail(currentProblem, currEq, variableNamesToPreserve);
                var succeed    = true;
                if (failResult.Count == 0)
                {
                    succeed = false;
                }
                else if (failResult.Count == 1)
                {
                    currentProblem = failResult.First();
                }
                else
                {
                    foreach (var continuation in failResult)
                    {
                        currentContinuations.Enqueue(continuation);
                    }
                }
                return(succeed);
            };

            while (currentContinuations.Count > 0)
            {
                currentProblem = currentContinuations.Dequeue();
                bool fail = false;
                while (currentProblem.CurrentEquations.Count > 0 && !fail)
                {
                    var currEq = currentProblem.CurrentEquations[currentProblem.CurrentEquations.Count - 1];
                    currentProblem.CurrentEquations.RemoveAt(currentProblem.CurrentEquations.Count - 1);
                    if (currEq.Lhs.Equals(currEq.Rhs))
                    {
                        // Elimination by omission (this is a "succeed" case)
                    }
                    else if (currEq.Lhs is TrsAtom && currEq.Rhs is TrsAtom)
                    {
                        if (!currEq.Lhs.Equals(currEq.Rhs))
                        {
                            fail = !processFail(currentProblem, currEq);
                        }
                    }
                    else if (currEq.Lhs is TrsAtom && currEq.Rhs is TrsTerm ||
                             currEq.Lhs is TrsTerm && currEq.Rhs is TrsAtom ||
                             currEq.Lhs is TrsAtom && currEq.Rhs is TrsAcTerm ||
                             currEq.Lhs is TrsAcTerm && currEq.Rhs is TrsAtom ||
                             currEq.Lhs is TrsTerm && currEq.Rhs is TrsAcTerm ||
                             currEq.Lhs is TrsAcTerm && currEq.Rhs is TrsTerm)
                    {
                        fail = !processFail(currentProblem, currEq);
                    }
                    else if (currEq.Lhs is TrsTerm && currEq.Rhs is TrsTerm)
                    {
                        TrsTerm lhs = currEq.Lhs as TrsTerm;
                        TrsTerm rhs = currEq.Rhs as TrsTerm;
                        if (lhs.Name != rhs.Name || lhs.Arguments.Count != rhs.Arguments.Count)
                        {
                            fail = !processFail(currentProblem, currEq);
                        }
                        else
                        {
                            currentProblem.CurrentEquations.AddRange(Enumerable.Range(0, lhs.Arguments.Count).
                                                                     Select(i => new Equation {
                                Lhs = lhs.Arguments[i], Rhs = rhs.Arguments[i]
                            }));
                        }
                    }
                    else if (currEq.Lhs is TrsAcTerm && currEq.Rhs is TrsAcTerm)
                    {
                        // Note: Failure is already processed internally in the next function call (ie. custom unifiers are called)
                        fail = ProcessAcUnificationStep(currentProblem, currentContinuations, processFail, currEq);
                    }
                    else if (!(currEq.Lhs is TrsVariable) && (currEq.Rhs is TrsVariable))
                    {
                        TrsTermBase lhsSwap = currEq.Lhs;
                        currEq.Lhs = currEq.Rhs;
                        currEq.Rhs = lhsSwap;
                        currentProblem.CurrentEquations.Add(currEq);
                    }
                    else if (currEq.Lhs is TrsVariable)
                    {
                        // Occurs check
                        if (currEq.Rhs.ContainsVariable((TrsVariable)currEq.Lhs))
                        {
                            fail = !processFail(currentProblem, currEq);
                        }
                        else
                        {
                            ProcessSubstitutionStep(currentProblem, currEq, variableNamesToPreserve);
                        }
                    }
                    else
                    {
                        throw new Exception("Invalid program state");
                    }
                }
                if (!fail)
                {
                    results.Add(new UnificationResult
                    {
                        Succeed = true,
                        Unifier = currentProblem.CurrentSubstitutions
                    });
                }
            }
            return(results.ToList());
        }