Example #1
0
        private bool EnsureSolutionIsViable(ref SolverErrorCode optionalErrorCode)
        {
            foreach (int desiredInstanceCount in this.desiredContainerInstanceCounts)
            {
                for (int k = 0; k < this.ResourceCount; k++)
                {
                    if (desiredInstanceCount > this.machineConstraintsPerResource[k].Count(c => c > 0))
                    {
                        optionalErrorCode = SolverErrorCode.ContainerRequiresAtLeastOneResourceThatIsNotAvailable;
                    }

                    if (desiredInstanceCount > this.machineConstraintsPerResource[k].Length)
                    {
                        optionalErrorCode = SolverErrorCode.MoreContainerInstancesThanMachinesAvailable;
                        return(false);
                    }
                }
            }

            return(true);
        }
Example #2
0
        public SolverResult Solve()
        {
            double          baselineScore = 0, initialStateScore = 0, score = 0;
            int             iterativeSwappingIterations = 0, fullScanIterations = 0, interContainerIterations = 0;
            SolutionQuality result;
            SolverErrorCode errorCode = SolverErrorCode.None;

            this.stopwatch = Stopwatch.StartNew();

            Dictionary <ResourceKind, AllocationMetric[]> initialGuessMetrics = null, solutionMetrics = null;

            this.initialState = this.InitializeMatrix();
            this.variables    = this.InitializeMatrix();

            if (this.EnsureSolutionIsViable(ref errorCode))
            {
                this.ComputeAverageAvailableResource();

                if (this.parameters.CurrentAllocations == null)
                {
                    if (this.parameters.InitialRandomGuessIterations > 0)
                    {
                        this.variables = this.GenerateSamples(iterations: this.parameters.InitialRandomGuessIterations);
                    }
                    else
                    {
                        this.variables = this.GenerateInitialAllocation();
                    }
                }
                else
                {
                    this.initialState = this.PopulateInitialState();
                    initialStateScore = ComputeVariance(this.Rows, this.Columns, this.ResourceCount, this.variables, this.containerCoefficientsPerResource, this.machineConstraintsPerResource, this.averageAvailableResource, this.resourceWeight);
                    this.variables    = this.GreedyPlacementOverInitialState(this.initialState);
                }

                baselineScore = ComputeVariance(this.Rows, this.Columns, this.ResourceCount, this.variables, this.containerCoefficientsPerResource, this.machineConstraintsPerResource, this.averageAvailableResource, this.resourceWeight);

                initialGuessMetrics = this.CaptureMetrics();

                if (this.parameters.AllowedChurnPercentage.HasValue)
                {
                    int[] currentAllocationsCounts = null;

                    if (this.parameters.CurrentAllocations?.Length > 0)
                    {
                        currentAllocationsCounts = this.GetInitialAllocationCounts();
                    }

                    this.maxDeallocationCount = CalculateMaxDeallocationCounts(
                        this.parameters.AllowedChurnPercentage.Value,
                        this.desiredContainerInstanceCounts,
                        currentAllocationsCounts);
                }

                iterativeSwappingIterations = this.IterativeSwapBestWorstMachinesForContainers(this.parameters.BestWorstSwappingIterations);

                fullScanIterations = this.PerformFullScanSwapping(this.parameters.FullScanIterations);

                interContainerIterations = this.FullScanSwappingContainers(this.parameters.FullScanSwapContainerIterations);

                score = ComputeVariance(this.Rows, this.Columns, this.ResourceCount, this.variables, this.containerCoefficientsPerResource, this.machineConstraintsPerResource, this.averageAvailableResource, this.resourceWeight);

                solutionMetrics = this.CaptureMetrics();

                bool satisfiesContainerInstanceCount = this.AllContainerInstanceCountSatisfied();
                bool satisfiesConstraints            = this.AllConstraintsAreSatisfied();

                if (satisfiesContainerInstanceCount && satisfiesConstraints)
                {
                    result = SolutionQuality.FoundExact;
                }
                else if (double.IsNegativeInfinity(score) || double.IsNaN(score))
                {
                    errorCode = SolverErrorCode.AdjustingErrorNegativeInfinityOrNaN;
                    result    = SolutionQuality.Unfeasible;
                }
                else if (this.hardConstraintResourceIndex.HasValue && !this.AreHardConstraintsSatisfied())
                {
                    errorCode = SolverErrorCode.HardConstraintUnsatisfied;
                    result    = SolutionQuality.Unfeasible;
                }
                else
                {
                    errorCode = SolverErrorCode.NotEnoughResourcesToAllocateAllInstances;
                    result    = SolutionQuality.Partial;
                }
            }
            else
            {
                result = SolutionQuality.Unfeasible;
            }

            this.stopwatch.Stop();
            AllocationPlan allocationPlan = this.GetAllocationPlan();

            score = ComputeVariance(this.Rows, this.Columns, this.ResourceCount, this.variables, this.containerCoefficientsPerResource, this.machineConstraintsPerResource, this.averageAvailableResource, this.resourceWeight);

            return(new SolverResult(
                       result,
                       errorCode,
                       baselineScore,
                       initialStateScore,
                       score,
                       iterativeSwappingIterations,
                       fullScanIterations,
                       interContainerIterations,
                       this.stopwatch.Elapsed,
                       this.variables,
                       allocationPlan.Allocations,
                       allocationPlan.NewAllocations,
                       allocationPlan.Deallocations,
                       initialGuessMetrics,
                       solutionMetrics));
        }