예제 #1
0
        private void ProcessSubstitutionStep(UnificationContinuation currentProblem, Equation currEq, List <TrsVariable> variableNamesToPreserve)
        {
            // LHS will always be variable here ... preserve matched term variables
            Substitution newSub = null;

            if (currEq.Rhs is TrsVariable &&
                variableNamesToPreserve.Contains(currEq.Lhs))
            {
                newSub = new Substitution
                {
                    Variable         = (TrsVariable)currEq.Rhs,
                    SubstitutionTerm = currEq.Lhs
                };
            }
            else
            {
                newSub = new Substitution
                {
                    Variable         = (TrsVariable)currEq.Lhs,
                    SubstitutionTerm = currEq.Rhs
                };
            }
            currentProblem.ComposeAndApplySubstitutions(newSub);
        }
예제 #2
0
   private static bool ProcessAcUnificationStep(UnificationContinuation currentProblem, Queue<UnificationContinuation> currentContinuations, 
 Func<UnificationContinuation, Equation, bool> processFail, Equation currEq)
   {
       var acLhs = currEq.Lhs as TrsAcTerm;
         var acRhs = currEq.Rhs as TrsAcTerm;
         bool fail = false;
         if (acLhs.Name != acRhs.Name)
         {
       fail = !processFail(currentProblem, currEq);
         }
         else
         {
       // Reduce cardinalities to reduce number of permutations
       foreach (var pair in (from lhsTerm in acLhs.OnfArguments
                        join rhsTerm in acRhs.OnfArguments
                          on lhsTerm.Term equals rhsTerm.Term
                         where lhsTerm.Term.IsGroundTerm
                           && rhsTerm.Term.IsGroundTerm
                         select new {
                           Lhs = lhsTerm,
                           Rhs = rhsTerm
                         }).ToList())
       {
         var diff = Math.Min(pair.Lhs.Cardinality, pair.Rhs.Cardinality);
         if (pair.Lhs.Cardinality > diff) pair.Lhs.Cardinality -= diff;
         else acLhs.OnfArguments.Remove(pair.Lhs);
         if (pair.Rhs.Cardinality > diff) pair.Rhs.Cardinality -= diff;
         else acRhs.OnfArguments.Remove(pair.Rhs);
       }
       // AC partitioning can only take place from the small to the large cardinalities
       List<TrsTermBase> fromArgs = null;
       List<TrsTermBase> toArgs = null;
       if (acLhs.TotalCardinality > acRhs.TotalCardinality)
       {
         fromArgs = acRhs.ExpandedArguments;
         toArgs = acLhs.ExpandedArguments;
       }
       else
       {
         fromArgs = acLhs.ExpandedArguments;
         toArgs = acRhs.ExpandedArguments;
       }
       // Generate mappings ... this is where the AC semantics are applied
       var setPartitionMappings = new SetMapPartitionEnumerator<int, int>(new HashSet<int>(Enumerable.Range(0, fromArgs.Count)),
         new HashSet<int>(Enumerable.Range(0, toArgs.Count)));
       // The first mapping will map to the first continuation, this must be added to the
       // current problem's equations in order to preserve algorithm correctness when the unification result
       // contains no substitutions.
       var isFirstContinuation = true;
       var initialCurrentProblem = currentProblem.CreateCopy(); // currentProblem gets updated in the first iteration
       foreach (var mappings in setPartitionMappings)
       {
         // Cater for multiple unification problems generated by the current AC problem
         UnificationContinuation clone = null;
         if (!isFirstContinuation) clone = initialCurrentProblem.CreateCopy();
         foreach (var mapping in mappings)
         {
       Equation eq = new Equation();
       eq.Lhs = fromArgs[mapping.FromElement];
       if (mapping.ToPartition.Count == 1) eq.Rhs = toArgs[mapping.ToPartition.First()];
       else eq.Rhs = new TrsAcTerm(acLhs.Name, mapping.ToPartition.Select(i => toArgs[i]));
       if (!isFirstContinuation) clone.CurrentEquations.Add(eq);
       else currentProblem.CurrentEquations.Add(eq);
         }
         if (!isFirstContinuation) currentContinuations.Enqueue(clone);
         else isFirstContinuation = false;
       }
         }
         return fail;
   }
예제 #3
0
 private void ProcessSubstitutionStep(UnificationContinuation currentProblem, Equation currEq, List<TrsVariable> variableNamesToPreserve)
 {
     // LHS will always be variable here ... preserve matched term variables
       Substitution newSub = null;
       if (currEq.Rhs is TrsVariable
     && variableNamesToPreserve.Contains(currEq.Lhs))
       {
     newSub = new Substitution
     {
       Variable = (TrsVariable)currEq.Rhs,
       SubstitutionTerm = currEq.Lhs
     };
       }
       else
       {
     newSub = new Substitution
     {
       Variable = (TrsVariable)currEq.Lhs,
       SubstitutionTerm = currEq.Rhs
     };
       }
       currentProblem.ComposeAndApplySubstitutions(newSub);
 }
예제 #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();
        }
예제 #5
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();
       }
 }
예제 #6
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());
            }
        }
예제 #7
0
        private static bool ProcessAcUnificationStep(UnificationContinuation currentProblem, Queue <UnificationContinuation> currentContinuations,
                                                     Func <UnificationContinuation, Equation, bool> processFail, Equation currEq)
        {
            var  acLhs = currEq.Lhs as TrsAcTerm;
            var  acRhs = currEq.Rhs as TrsAcTerm;
            bool fail  = false;

            if (acLhs.Name != acRhs.Name)
            {
                fail = !processFail(currentProblem, currEq);
            }
            else
            {
                // Reduce cardinalities to reduce number of permutations
                foreach (var pair in (from lhsTerm in acLhs.OnfArguments
                                      join rhsTerm in acRhs.OnfArguments
                                      on lhsTerm.Term equals rhsTerm.Term
                                      where lhsTerm.Term.IsGroundTerm &&
                                      rhsTerm.Term.IsGroundTerm
                                      select new {
                    Lhs = lhsTerm,
                    Rhs = rhsTerm
                }).ToList())
                {
                    var diff = Math.Min(pair.Lhs.Cardinality, pair.Rhs.Cardinality);
                    if (pair.Lhs.Cardinality > diff)
                    {
                        pair.Lhs.Cardinality -= diff;
                    }
                    else
                    {
                        acLhs.OnfArguments.Remove(pair.Lhs);
                    }
                    if (pair.Rhs.Cardinality > diff)
                    {
                        pair.Rhs.Cardinality -= diff;
                    }
                    else
                    {
                        acRhs.OnfArguments.Remove(pair.Rhs);
                    }
                }
                // AC partitioning can only take place from the small to the large cardinalities
                List <TrsTermBase> fromArgs = null;
                List <TrsTermBase> toArgs   = null;
                if (acLhs.TotalCardinality > acRhs.TotalCardinality)
                {
                    fromArgs = acRhs.ExpandedArguments;
                    toArgs   = acLhs.ExpandedArguments;
                }
                else
                {
                    fromArgs = acLhs.ExpandedArguments;
                    toArgs   = acRhs.ExpandedArguments;
                }
                // Generate mappings ... this is where the AC semantics are applied
                var setPartitionMappings = new SetMapPartitionEnumerator <int, int>(new HashSet <int>(Enumerable.Range(0, fromArgs.Count)),
                                                                                    new HashSet <int>(Enumerable.Range(0, toArgs.Count)));
                // The first mapping will map to the first continuation, this must be added to the
                // current problem's equations in order to preserve algorithm correctness when the unification result
                // contains no substitutions.
                var isFirstContinuation   = true;
                var initialCurrentProblem = currentProblem.CreateCopy(); // currentProblem gets updated in the first iteration
                foreach (var mappings in setPartitionMappings)
                {
                    // Cater for multiple unification problems generated by the current AC problem
                    UnificationContinuation clone = null;
                    if (!isFirstContinuation)
                    {
                        clone = initialCurrentProblem.CreateCopy();
                    }
                    foreach (var mapping in mappings)
                    {
                        Equation eq = new Equation();
                        eq.Lhs = fromArgs[mapping.FromElement];
                        if (mapping.ToPartition.Count == 1)
                        {
                            eq.Rhs = toArgs[mapping.ToPartition.First()];
                        }
                        else
                        {
                            eq.Rhs = new TrsAcTerm(acLhs.Name, mapping.ToPartition.Select(i => toArgs[i]));
                        }
                        if (!isFirstContinuation)
                        {
                            clone.CurrentEquations.Add(eq);
                        }
                        else
                        {
                            currentProblem.CurrentEquations.Add(eq);
                        }
                    }
                    if (!isFirstContinuation)
                    {
                        currentContinuations.Enqueue(clone);
                    }
                    else
                    {
                        isFirstContinuation = false;
                    }
                }
            }
            return(fail);
        }
예제 #8
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());
        }