// old search method

        /*
         *      private void search2(IBestChoiceSearcher bestChoiceSearcher, PropagationResult result, List<Solution> solutions)
         *      {
         *              Set[,] s = result.matrix;
         *
         *  // Find the top list of possible choices of Set with maximum minFactor range.
         *              List<FactorRangeRecord> bestRecords = searchForTheBestRecords(s);
         *  // If the it is only one possible Set, after shorten will be matrix singleton
         *              bool isSingleton = bestRecords.Count == 1;
         *
         *  // Find the set to be shortened.
         *              FactorRangeRecord best = bestChoiceSearcher.chooseBestRecord(bestRecords);
         *              Set currentSet = s[best.Row, best.Col];
         *
         *              // Create the order in which we will try to find a solution, best possibility first.
         *              List<int> sortedMinutes = new List<int>(currentSet.MinimizationFactor.Keys);
         *              sortedMinutes.Sort(delegate(int i, int j)
         *              {
         *                      return currentSet.MinimizationFactor[i] - currentSet.MinimizationFactor[j];
         *              });
         *
         *              // Search for the solution.
         *              foreach (int minute in sortedMinutes)
         *              {
         *                      // TODO: Use the branch and bound prunning.
         *
         *                      // Copy the matrix.
         *                      Set[,] newMatrix = GenerationAlgorithmPESPUtil.cloneDiscreteSetMatrix(s);
         *
         *                      // Create a singleton set.
         *                      Set newSet = new Set(currentSet.Modulo);
         *                      newSet.Add(minute, currentSet.MinimizationFactor[minute]);
         *
         *                      // Remeber to the new matrix.
         *                      newMatrix[best.Row, best.Col] = newSet;
         *                      newMatrix[best.Col, best.Row] = new Set(newSet);
         *                      newMatrix[best.Col, best.Row].Reverse();
         *
         *                      // Propagate newly created constraints.
         *                      PropagationUtils.propagate(newMatrix, result.TrainLinesMap);
         *
         *                      // Check if the solution may be found.
         *                      if (!MatrixUtils.isValid(s))
         *                      {
         *                              continue;
         *                      }
         *
         *                      // If the solution is found, remember it, otherwise search for it.
         *                      if (isSingleton)
         *                      {
         *                              solutions.Add(new Solution(newMatrix));
         *                      }
         *                      else
         *                      {
         *                              search(new PropagationResult(newMatrix, result.TrainLinesMap), solutions);
         *                      }
         *              }
         *      }
         */

        /// <summary>
        /// Searches for solution.
        /// It is called recursively, backtracking all possiblities with respect to specific choice searcher.
        /// </summary>
        /// <param name="bestChoiceSearcher">The best choice searcher.</param>
        /// <param name="propagationResult">The propagation result.</param>
        /// <param name="solutions">The solutions.</param>
        /// <returns>True if solution found, terminate recursive calls. Otherwise continue in backtracking.</returns>
        private Boolean search(IBestChoiceSearcher bestChoiceSearcher, PropagationResult propagationResult, List <Solution> solutions)
        {
            //reportProgress();

            // retreive discrete set matrix after propagation from propagation result
            Set[,] discreteSetMatrix = propagationResult.DiscreteSetMatrix;

            // while until you can still find some solution (still can found best record)
            while (true)
            {
                // Propagate newly created constraints.
                PropagationUtil.propagate(discreteSetMatrix, propagationResult.TrainLinesMap);

                // Check if the solution may be found.
                if (!MatrixUtils.isValid(discreteSetMatrix))
                {
                    // No valid matrix - solution can not be found.
                    return(false);
                }

                // Find the set to be shortened.
                FactorRangeRecord bestRecord;

                // if no best record found ()
                if (!bestChoiceSearcher.chooseBestRecord(discreteSetMatrix, out bestRecord))
                {
                    // then solution found, matrix is single (contains singletons only).
                    solutions.Add(new Solution(discreteSetMatrix));

                    // End of recursive calls
                    return(true);
                }

                reportProgress();

                // fix one potential set with item founded as best
                Set[,] newMatrix = fixOnePotentialOfSetInMatrix(discreteSetMatrix, bestRecord);

                // matrix was changed, continue in recursive calls
                Boolean solutionFound = search(bestChoiceSearcher, new PropagationResult(newMatrix, propagationResult.TrainLinesMap), solutions);

                // Test if solution was found
                if (solutionFound)
                {
                    return(true);
                }

                // after return from recursive call, remove fixed object and try to
                discreteSetMatrix[bestRecord.Row, bestRecord.Col].Remove(bestRecord.MinItemOfSet);
                discreteSetMatrix[bestRecord.Col, bestRecord.Row].RemoveReverse(bestRecord.MinItemOfSet);
            }
        }
        // TODO: move to the IPropagator Iface.

        /// <summary>
        /// Runs the propagation algorithm.
        /// Create discrete set for constraints, normalize and merge them, and propagate constraints' sets in matrix.
        /// </summary>
        /// <param name="originalConstraints">The original constraints.</param>
        /// <param name="constraintSetsCreator">The constraint sets creator.</param>
        /// <param name="size">The size.</param>
        /// <returns></returns>
        public static PropagationResult runPropagationAlgorithm(List <Constraint> originalConstraints, IConstraintSetsCreator constraintSetsCreator, int size)
        {
            // create working copy of constraints

            List <Constraint> constraints = GenerationAlgorithmDSAUtil.cloneConstraints(originalConstraints);

            //------createConstraintSet-potential-set-for-constraints-----------------------

            constraints = constraintSetsCreator.createConstraintSets(constraints, size);

            //------modification-constraints----------------------------------

            //LogUtil.printConstraintsToFile(constraints, "originalConstraints");

            // normalize constraints
            constraints = ConstraintUtil.normalizeConstraints(constraints);

            //LogUtil.printConstraintsToFile(constraints, "normalizedConstraints");

            // find equivalent constraints
            List <List <Constraint> > groupOfconstraints = ConstraintUtil.findEquivalentConstraints(constraints);

            // try to merge them
            constraints = ConstraintUtil.mergeEquivalentConstrains(groupOfconstraints);

            //LogUtil.printConstraintsToFile(constraints, "mergedConstraints");

            // createConstraintSet a hashtable only of all trainLines used in constraints
            List <TrainLine> trainLinesMap = GenerationAlgorithmDSAUtil.createTrainLineMap(constraints);

            // store constraints - into constraintCache
            ConstraintCache.getInstance().setCacheContent(constraints);
            // create matrix of discrete sets
            Set[,] setMatrix = GenerationAlgorithmDSAUtil.createDiscretSetMatrix(constraints, trainLinesMap);


            // createConstraintSet constraint's matrix
            //this.constraintMatrix = GenerationAlgorithmPESPUtil.createConstraintMatrix(constraints, trainLinesMap);



            //-------propagation-part-of-algorithm--------------------------------------------------------
            PropagationUtil.propagate(setMatrix, trainLinesMap);

            return(new PropagationResult(setMatrix, trainLinesMap));
        }