public static IProblem RemoveRedundantOperations(this IProblem problem, StringBuilder getReport = null)
        {
            Stopwatch sw = Stopwatch.StartNew();

            int mergeCounter = 0;

            int OpCount() => problem.Jobs
            .SelectMany(j => j.Routes)
            .SelectMany(r => r.Operations)
            .Count();

            var result = new ModifiedIProblem(
                problem.Jobs.Select(
                    j => new ModifiedIJob(j.Routes.Select(
                                              r => new ModifiedIRoute(
                                                  r.RoutingPenalty,
                                                  r.Operations.RemoveRedundantOperations(ref mergeCounter).ToArray()))
                                          .ToArray()))
                .ToArray(),
                problem.Objective,
                problem.ProblemName);

            getReport?
            .AppendLine($"-----------------  Report: Removing redundant operations.  -----------------")
            .Append($"# operation redundant = {mergeCounter} ")
            .AppendLine(
                $"(total {OpCount(),6} operations,   {Math.Round(100.0 * mergeCounter / OpCount()),4}%)")
            .AppendLine($"Simplification took {Math.Round(sw.ElapsedMilliseconds / 1000.0, 2)} sec.")
            .AppendLine("------------------              End Report                ------------------");

            return(result);
        }
        public static IProblem RemoveRedundantMachines(this IProblem problem, StringBuilder getReport = null)
        {
            Stopwatch sw = Stopwatch.StartNew();

            var redundant = problem.GetRedundantMachines();

            int MachineCount() => problem.Jobs
            .SelectMany(j => j.Routes)
            .SelectMany(r => r.Operations)
            .SelectMany(o => o.Machines)
            .Distinct()
            .Count();

            int TotalMachineCount() => problem.Jobs
            .SelectMany(j => j.Routes)
            .SelectMany(r => r.Operations)
            .SelectMany(o => o.Machines)
            .Count();


            int OpCount() => problem.Jobs
            .SelectMany(j => j.Routes)
            .SelectMany(r => r.Operations)
            .Count();

            getReport?
            .AppendLine($"------------------  Report: Removing redundant machines.  ------------------")
            .Append($"# machines redundant        = {redundant.Count,6} ")
            .Append($"(total {MachineCount(),6} machines,   {Math.Round(100.0 * redundant.Count / MachineCount()),4}%)")
            .AppendLine();

            int changedOps             = 0;
            int machinesRemovedFromOps = 0;

            var result = new ModifiedIProblem(
                problem.Jobs.Select(
                    j => new ModifiedIJob(j.Routes.Select(
                                              r => new ModifiedIRoute(r.RoutingPenalty, r.Operations.Select(
                                                                          o =>
            {
                if (getReport != null &&
                    o.Machines.Count() != o.Machines.Except(redundant).Count())
                {
                    changedOps++;
                    machinesRemovedFromOps +=
                        o.Machines.Count() - o.Machines.Except(redundant).Count();
                }

                return(new ModifiedIOperation(
                           o.Runtime, o.EarliestEntry, o.LatestEntry,
                           o.DelayWeight, o.Machines.Except(redundant),
                           o.OutgoingConnections, o.IncomingConnections));
            }).ToArray()))
                                          .ToArray()))
                .ToArray(),
                problem.Objective,
                problem.ProblemName);

            getReport?
            .Append($"# changed operations        = {changedOps,6} ")
            .Append($"(total {OpCount(),6} operations, {Math.Round(100.0 * changedOps / OpCount()),4}%)")
            .AppendLine()

            .Append($"# machine instances removed = {machinesRemovedFromOps,6} ")
            .Append($"(total {TotalMachineCount(),6} instances,  {Math.Round(100.0 * machinesRemovedFromOps / TotalMachineCount()),4}%)")
            .AppendLine()

            .AppendLine($"Simplification took {Math.Round(sw.ElapsedMilliseconds / 1000.0, 2)} sec.")
            .AppendLine("------------------              End Report                ------------------");

            return(result);
        }