#region License Information /* HeuristicLab * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Collections.Generic; using System.Text; using HeuristicLab.Core; using HeuristicLab.Constraints; using HeuristicLab.Data; namespace HeuristicLab.Constraints { /// /// Analyzes the sub-operators for specific constraints. /// public class SubOperatorsConstraintAnalyser { private ICollection allPossibleOperators; /// /// Gets or sets all possible operators. /// public ICollection AllPossibleOperators { get { return allPossibleOperators; } set { allPossibleOperators = value; } } /// /// Gets all operators that fulfill the expression of the constraints of the given operator. /// /// The operator whose constraints to check. /// The index of the child. /// All allowed operators. public IList GetAllowedOperators(IOperator op, int childIndex) { AndConstraint andConstraint = new AndConstraint(); foreach (IConstraint constraint in op.Constraints) { andConstraint.Clauses.Add(constraint); } return GetAllowedOperators(andConstraint, childIndex); } private IList GetAllowedOperators(IConstraint constraint, int childIndex) { // manual dispatch on dynamic type if (constraint is AndConstraint) return GetAllowedOperators((AndConstraint)constraint, childIndex); else if (constraint is OrConstraint) return GetAllowedOperators((OrConstraint)constraint, childIndex); else if (constraint is NotConstraint) return GetAllowedOperators((NotConstraint)constraint, childIndex); else if (constraint is AllSubOperatorsTypeConstraint) return GetAllowedOperators((AllSubOperatorsTypeConstraint)constraint, childIndex); else if (constraint is SubOperatorTypeConstraint) return GetAllowedOperators((SubOperatorTypeConstraint)constraint, childIndex); else return new List(allPossibleOperators); // ignore all other constraints } #region static set management methods // better to use HashSets from .NET 3.5 // however we would need to switch the whole Constraints project to .NET 3.5 for that private static IList Intersect(ICollection a, ICollection b) { if (a.Count > b.Count) { return Intersect(b, a); } List intersection = new List(a.Count); foreach (IOperator element in a) { if (InSet(element, b)) { intersection.Add(element); } } return intersection; } private static IList Union(ICollection a, ICollection b) { List union = new List(a); foreach (IOperator candidateElement in b) { if (!InSet(candidateElement, union)) { union.Add(candidateElement); } } return union; } private static IList Substract(ICollection minuend, ICollection subtrahend) { List difference = new List(); foreach (IOperator element in minuend) { if (!InSet(element, subtrahend)) { difference.Add(element); } } return difference; } private static bool InSet(IOperator op, ICollection set) { foreach (IOperator element in set) { if (element == op) return true; } return false; } #endregion /// /// Gets all allowed operators that fulfill the expression of the given AndConstraint. /// /// The constraint that must be fulfilled. /// The index of the child. /// All allowed operators. public IList GetAllowedOperators(AndConstraint constraint, int childIndex) { IList allowedOperators = new List(allPossibleOperators); // keep only the intersection of all subconstraints foreach (ConstraintBase clause in constraint.Clauses) { allowedOperators = Intersect(allowedOperators, GetAllowedOperators(clause, childIndex)); } return allowedOperators; } /// /// Gets all allowed operators that fulfill the expression of the given OrConstraint. /// /// The constraint that must be fulfilled. /// The index of the child. /// All allowed operators. public IList GetAllowedOperators(OrConstraint constraint, int childIndex) { IList allowedOperators = new List(); foreach (ConstraintBase clause in constraint.Clauses) { allowedOperators = Union(allowedOperators, GetAllowedOperators(clause, childIndex)); } return allowedOperators; } /// /// Gets all allowed operators that fulfill the expression of the given NotConstraint. /// /// The constraint that must be fulfilled. /// The index of the child. /// All allowed operators. public IList GetAllowedOperators(NotConstraint constraint, int childIndex) { return Substract(allPossibleOperators, GetAllowedOperators(constraint.SubConstraint, childIndex)); } /// /// Gets all allowed operators that fulfill the expression of the given AllSubOperatorsTypeConstraint. /// /// The constraint that must be fulfilled. /// The index of the child. /// All allowed operators. public IList GetAllowedOperators(AllSubOperatorsTypeConstraint constraint, int childIndex) { return Intersect(allPossibleOperators, constraint.AllowedSubOperators); } /// /// Gets all allowed operators that fulfill the expression of the given SubOperatorTypeConstraint. /// /// The constraint that must be fulfilled. /// The index of the child. /// All allowed operators. public IList GetAllowedOperators(SubOperatorTypeConstraint constraint, int childIndex) { if (childIndex != constraint.SubOperatorIndex.Data) { return new List(allPossibleOperators); } else { return Intersect(allPossibleOperators, constraint.AllowedSubOperators); } } } }