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); }
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)); }