public static void OptimiseNodeGroup(IReadOnlyCollection <ProductionNode> nodeGroup) { if (nodeGroup.Count == 0) { return; } var solver = new ProductionSolver(); foreach (var node in nodeGroup) { node.AddConstraints(solver); } var solution = solver.Solve(); Debug.WriteLine(solver.ToString()); // TODO: Handle BIG NUMBERS // TODO: Return error in solution!? if (solution == null) { throw new Exception("Solver failed but that shouldn't happen.\n" + solver); } foreach (var node in nodeGroup) { node.SetSolvedRate(solution.ActualRate(node)); foreach (var link in node.OutputLinks.Union(node.InputLinks)) { link.Throughput = solution.Throughput(link); } } }
internal void AddConstraints(ProductionSolver solver) { solver.AddNode(this); double?rate = GetActualDesiredRate(); if (rate != null) { solver.AddTarget(this, (float)rate.Value); } foreach (var itemInputs in InputLinks.GroupBy(x => x.Item)) { var item = itemInputs.Key; solver.AddInputRatio(this, item, itemInputs, InputRateFor(item)); solver.AddInputLink(this, item, itemInputs, InputRateFor(item)); } foreach (var itemOutputs in OutputLinks.GroupBy(x => x.Item)) { var item = itemOutputs.Key; solver.AddOutputRatio(this, item, itemOutputs, OutputRateFor(item)); // Output links do not need to constrained, since they are already covered by adding // the input link above. } }
internal void AddConstraints(ProductionSolver solver) { solver.AddNode(this); if (rateType == RateType.Manual) { solver.AddTarget(this, desiredRate); } foreach (var itemInputs in InputLinks.GroupBy(x => x.Item)) { var item = itemInputs.Key; solver.AddInputRatio(this, item, itemInputs, inputRateFor(item)); solver.AddInputLink(this, item, itemInputs, inputRateFor(item)); } foreach (var itemOutputs in OutputLinks.GroupBy(x => x.Item)) { var item = itemOutputs.Key; solver.AddOutputRatio(this, item, itemOutputs, outputRateFor(item)); // Output links do not need to constrained, since they are already covered by adding // the input link above. } }