public Solution RemoveRedundantConstraints(ConstraintMetric constraintMetric = ConstraintMetric.MostUnsatisfied, int samplingSize = 100, double marginExpansion = 0.5, double angleSimilarityMarigin = 5.0, bool reduceSatisfiedPoints = true) { var randomPoints = Cluster.GenerateRandomPointsAroundCluster(samplingSize, marginExpansion); Func <Constraint, double> constraintUtilityFunction = null; var constraints = Constraints.Cast <Constraint>().ToList(); switch (constraintMetric) { case ConstraintMetric.DistanceFromCentroid: constraintUtilityFunction = c => Algorithm.ConstraintMetric.DistanceFromCentroid(c, new Point(Cluster.Centroid)); break; case ConstraintMetric.DistanceFromMeans: constraintUtilityFunction = c => Algorithm.ConstraintMetric.DistanceFromMeans(c, new Point(Cluster.Means)); break; case ConstraintMetric.DistanceFromSatisfied: constraintUtilityFunction = c => Algorithm.ConstraintMetric.DistanceFromSatisfied(c, randomPoints); break; case ConstraintMetric.DistanceFromUnsatisfied: constraintUtilityFunction = c => Algorithm.ConstraintMetric.DistanceFromUnsatisfied(c, randomPoints); break; case ConstraintMetric.AvgDistanceFromSatisfied: constraintUtilityFunction = c => Algorithm.ConstraintMetric.AvgDistanceFromSatisfied(c, randomPoints); break; case ConstraintMetric.AvgDistanceFromUnsatisfied: constraintUtilityFunction = c => Algorithm.ConstraintMetric.AvgDistanceFromUnsatisfied(c, randomPoints); break; case ConstraintMetric.MostUnsatisfied: constraintUtilityFunction = c => Algorithm.ConstraintMetric.MostUnsatisfied(c, randomPoints); break; default: throw new ArgumentOutOfRangeException(nameof(constraintMetric), constraintMetric, null); } var redundantIndices = RedundantConstraintsFinder.FindRedundantConstraints(constraintUtilityFunction, constraints, randomPoints, angleSimilarityMarigin, reduceSatisfiedPoints).ToList(); redundantIndices.Sort(); redundantIndices.Reverse(); foreach (var indexToRemove in redundantIndices) { _constraints[indexToRemove].IsMarkedRedundant = true; } return(this); }