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; }
/// <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()); } }
/// <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(); } }
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); }