Beispiel #1
0
        private void Initialize()
        {
            // entities
            m_arm    = new Arm();
            m_finger = new Finger();

            // processing & tracking
            m_processor = new TouchProcessor(m_arm, m_finger);
            m_optiTrack = new OptiTrack();

            // models
            m_models = new Dictionary <ModelType, LinearModel>();

            LinearModel horizontalModel = new LinearModel(Constants.Models.HorizontalRows,
                                                          Constants.Models.HorizontalColumns, ModelDirection.Landscape);

            horizontalModel.Load(Constants.Models.HorizontalModelFileName);
            m_models.Add(ModelType.Horizontal, horizontalModel);

            LinearModel verticalModel = new LinearModel(Constants.Models.VerticalRows,
                                                        Constants.Models.VerticalColumns, ModelDirection.Portrait);

            verticalModel.Load(Constants.Models.VerticalModelFileName);
            m_models.Add(ModelType.Vertical, verticalModel);

            LinearModel tracingModel = new LinearModel(Constants.Models.TracingRows,
                                                       Constants.Models.TracingColumns, ModelDirection.Landscape);

            tracingModel.Load(Constants.Models.TracingModelFileName);
            m_models.Add(ModelType.Tracing, tracingModel);

            m_arm.AddModel(horizontalModel, ModelType.Horizontal, Constants.Colors.HorizontalGridModelColor);
            m_arm.AddModel(verticalModel, ModelType.Vertical, Constants.Colors.VerticalGridModelColor);
            m_arm.AddModel(tracingModel, ModelType.Tracing, Constants.Colors.TracingGridModelColor);
        }
Beispiel #2
0
        private SolvedModel BuildSolvedModel()
        {
            var x1 = new Variable {
                Name = "X1", Type = VariableType.Input
            };
            var x2 = new Variable {
                Name = "X2", Type = VariableType.Input
            };
            var c1 = new Constraint
            {
                Name           = "C1",
                ConstraintType = ConstraintType.GreaterThanOrEqualTo,
                Variables      = new List <ValueVariable>(new[]
                {
                    new ValueVariable {
                        Variable = x1, Coefficient = 2
                    },
                    new ValueVariable {
                        Variable = x2, Coefficient = 1
                    },
                }),
                ConstraintValue = 4
            };
            var c2 = new Constraint
            {
                Name           = "C2",
                ConstraintType = ConstraintType.GreaterThanOrEqualTo,
                Variables      = new List <ValueVariable>(new[]
                {
                    new ValueVariable {
                        Variable = x1, Coefficient = 1
                    },
                    new ValueVariable {
                        Variable = x2, Coefficient = 7
                    },
                }),
                ConstraintValue = 7
            };
            var objectiveFunction = new List <ValueVariable>(new[]
            {
                new ValueVariable {
                    Variable = x1, Coefficient = 1
                },
                new ValueVariable {
                    Variable = x2, Coefficient = 1
                },
            });

            var linearModel = new LinearModel
            {
                Objective         = Objective.MIN,
                Variables         = new List <Variable>(new[] { x1, x2 }),
                Constraints       = new List <Constraint>(new[] { c1, c2 }),
                ObjectiveFunction = objectiveFunction
            };

            var res = LinearModelSolver.Solve(linearModel);

            return(res);
        }
Beispiel #3
0
        /// <summary>
        /// For outputting the LLS solution results
        /// </summary>
        /// <param name="trainsetpath"></param>
        /// <param name="testsetpath"></param>
        private static void CupTestingLLS(string trainsetpath, string testsetpath)
        {
            CupDataManager dm       = new CupDataManager();
            DataSet        trainset = dm.LoadData(trainsetpath, 10, 2, standardize: true);
            DataSet        testset  = dm.LoadData(testsetpath, 10, 2, standardize: true);



            LinearModel model = new LinearModel {
                bias = true
            };

            //**trying SVD
            LinearLeastSquaresParams passedParams = new LinearLeastSquaresParams {
                model = model, numOfIterations = 5000, learningRate = 0.1, degree = 1
            };

            passedParams.trainingSet   = trainset;
            passedParams.validationSet = testset;
            Console.WriteLine("SVD solution:");
            var svdlearningCurve = new LLSSVD().Train(passedParams);

            Console.WriteLine("Normal Equations Solution:");
            var normallearningCurve = new LLSNormal().Train(passedParams);

            Console.WriteLine("GD  Solution:");
            var gdlearningCurve = new LLSGradientDescent().Train(passedParams);
        }
        public MainViewModel()
        {
            linearModel = new LinearModel();
            linearModel.initTime(100000, 0.000001);
            linearModel.initTimeMoments(100000, 5, 6);
            linearModel.applyLoad();
            linearModel.calcMove();

            //PlotModel model = new PlotModel();
            //LineSeries s1 = new LineSeries();
            //s1.
            //AddPoints(s1.Points, 100000);
            //model.Series.Add(s1);

            //this.Measurements = new Collection<Measurement>();
            //for (int i = 0; i < linearModel.timeMoments.Length; i++)
            //{
            //    for (int j = 0; j < linearModel.timeMoments[i].Nodes.Length; j++)
            //    {
            //        this.Measurements.Add(new Measurement
            //        {
            //            Time = i,
            //            Value = (double)linearModel.timeMoments[i].Nodes[j].force[0],
            //            Maximum = 0,
            //            Minimum = 0
            //        });
            //    }
            //}
        }
    //Generate SolvedModel from LinearModel
    public static SolvedModel Solve(LinearModel linearModel)
    {
        var firstIteration = BuildFirstIteration(linearModel);

        SolvedModel res;

        if (firstIteration.Variables.Any(var => var.Type == VariableType.Artificial))
        {
            res = TwoPhases(firstIteration, linearModel.Constraints);
        }
        else
        {
            res = Simplex(firstIteration, linearModel.Constraints);
        }

        if (linearModel.Objective == Objective.MIN && res.Z != BigRational.Zero) //BigRational.Zero * -1 throws exception
        {
            res.Z *= -1;
        }

        res.ObjectiveOrientation = linearModel.Objective;
        res.Objective            = linearModel.ObjectiveFunction.ToList();

        return(res);
    }
Beispiel #6
0
    [Test] public void TwoPhasesFromLinearModel()
    {
        var x1 = new Variable {
            Name = "X1", Type = VariableType.Input
        };
        var x2 = new Variable {
            Name = "X2", Type = VariableType.Input
        };
        var c1 = new Constraint
        {
            Name      = "C1", ConstraintType = ConstraintType.GreaterThanOrEqualTo,
            Variables = new List <ValueVariable>(new[]
            {
                new ValueVariable {
                    Variable = x1, Coefficient = 2
                },
                new ValueVariable {
                    Variable = x2, Coefficient = 1
                },
            }),
            ConstraintValue = 4
        };
        var c2 = new Constraint
        {
            Name      = "C2", ConstraintType = ConstraintType.GreaterThanOrEqualTo,
            Variables = new List <ValueVariable>(new[]
            {
                new ValueVariable {
                    Variable = x1, Coefficient = 1
                },
                new ValueVariable {
                    Variable = x2, Coefficient = 7
                },
            }),
            ConstraintValue = 7
        };
        var objectiveFunction = new List <ValueVariable>(new[]
        {
            new ValueVariable {
                Variable = x1, Coefficient = 1
            },
            new ValueVariable {
                Variable = x2, Coefficient = 1
            },
        });

        var linearModel = new LinearModel
        {
            Objective         = Objective.MIN,
            Variables         = new List <Variable>(new[] { x1, x2 }),
            Constraints       = new List <Constraint>(new[] { c1, c2 }),
            ObjectiveFunction = objectiveFunction
        };

        var res = LinearModelSolver.Solve(linearModel);

        Assert.AreEqual(new BigRational(31, 13), res.Z);
    }
Beispiel #7
0
 internal void AddModel(LinearModel model, ModelType type, Color color)
 {
     lock (this)
     {
         if (!(m_displayedModels.ContainsKey(type)))
         {
             m_displayedModels.Add(type, model);
             m_model.AddGrid(model.GridPoints, color);
         }
     }
 }
Beispiel #8
0
        /// <summary>
        /// Solves this model.
        /// </summary>
        public void Solve()
        {
            // Init
            LogLine("Solving ...");
            DateTime    before            = DateTime.Now;
            LinearModel model             = new LinearModel(SolverType.Gurobi, (string msg) => { Log(msg); });
            VariableCollection <int> xVar = new VariableCollection <int>(model, VariableType.Continuous, 0, double.PositiveInfinity, (int j) => { return("x" + j.ToString()); });

            // Modify some control parameters
            foreach (var param in _solverArgs)
            {
                model.SetParam(param.Key, param.Value);
            }

            // Prepare non-zero indices
            Dictionary <int, List <int> > nnzs = _coefficientMatrix.Keys.GroupBy(k => (int)k[0]).ToDictionary(k => k.Key, v => v.Select(e => (int)e[1]).ToList());

            // Add objective
            model.SetObjective(
                LinearExpression.Sum(
                    Enumerable.Range(0, N).Select(j => _objCoeffcientVector[j]),
                    Enumerable.Range(0, N).Select(j => xVar[j])),
                OptimizationSense.Minimize);
            // Add constraint
            foreach (var i in nnzs.Keys)
            {
                model.AddConstr(LinearExpression.Sum(
                                    nnzs[i].Select(j => _coefficientMatrix[i, j]),
                                    nnzs[i].Select(j => xVar[j]))
                                == _rhsVector[i],
                                "Con" + i);
            }
            // TODO remove debug
            model.Update();
            model.ExportMPS("mdp.mps");
            // Solve
            model.Optimize();
            TimeSpan solutionTime = DateTime.Now - before;

            // Get solution
            if (model.HasSolution())
            {
                LogLine("Solution found!");
                _solutionVector   = Enumerable.Range(0, N).Select(j => xVar[j].Value).ToList();
                _solutionValue    = model.GetObjectiveValue();
                SolutionAvailable = true;
            }
            else
            {
                LogLine("No solution!");
            }
            // Log performance
            LogPerformance(before, Filename, solutionTime, SolutionAvailable, _solutionValue, _solverArgs.Select(a => a.Key + "=" + a.Value));
        }
Beispiel #9
0
 internal void RemoveModel(LinearModel model, ModelType type)
 {
     lock (this)
     {
         if (m_displayedModels.ContainsKey(type))
         {
             m_displayedModels.Remove(type);
             m_model.RemoveGrid(model.GridPoints);
         }
     }
 }
Beispiel #10
0
    [Test] public void TwoPhasesInfeasibleFromLinearModel()
    {
        var x1 = new Variable {
            Name = "X1", Type = VariableType.Input
        };
        var x2 = new Variable {
            Name = "X2", Type = VariableType.Input
        };
        var x3 = new Variable {
            Name = "X3", Type = VariableType.Input
        };
        var c1 = new Constraint
        {
            ConstraintType = ConstraintType.EqualTo,
            Variables      = new List <ValueVariable>(new[]
            {
                x1.As(-2),
                x2.As(1),
                x3.As(3),
            }),
            ConstraintValue = 2
        };
        var c2 = new Constraint
        {
            ConstraintType = ConstraintType.EqualTo,
            Variables      = new List <ValueVariable>(new[]
            {
                x1.As(2),
                x2.As(3),
                x3.As(4),
            }),
            ConstraintValue = 1
        };
        var objectiveFunctions = new List <ValueVariable>(new[]
        {
            x1.As(1),
            x2.As(-2),
            x3.As(-3)
        });

        var linearModel = new LinearModel
        {
            Constraints       = new List <Constraint>(new[] { c1, c2 }),
            Objective         = Objective.MIN,
            ObjectiveFunction = objectiveFunctions,
            Variables         = new List <Variable>(new[] { x1, x2, x3 })
        };

        var res = LinearModelSolver.Solve(linearModel);

        Assert.IsTrue(res.Result == SolvedResult.Infeasible);
        Assert.IsTrue(res.TwoPhasesIterations.Count == 2);
    }
Beispiel #11
0
        private void AnalyzeServiceUnits()
        {
            // Keep track of count
            int overallCount = _serviceUnits.Count * _config.GroupsIndividuals.Count;
            int counter      = 0;

            // --> Solve all
            _config.LogLine("Analyzing all service units within all given groups - " + overallCount + " to go!");
            // Iterate all groups (use a dummy group if no grouping has to be done - this should work ok with the interior part of the loops)
            foreach (var groupIdents in _config.GroupsIndividuals)
            {
                // Investigate all service units for this group within the given scenario
                foreach (var serviceUnitInFocus in _serviceUnits)
                {
                    // Log
                    _config.Log((++counter) + "/" + overallCount + ": " + serviceUnitInFocus.Ident + "/" + (groupIdents.Any() ? string.Join(",", groupIdents.Select(i => i.Item2)) : "Overall") + " (SU/group)");
                    // Init
                    LinearModel model = new LinearModel(_config.SolverChoice, null /* Disable output flood for now, use following to enable: (string s) => { _config.Log(s); } */);
                    // --> Init variables
                    Variable efficiencyRating = new Variable(model, VariableType.Continuous, double.NegativeInfinity, double.PositiveInfinity, "EfficiencyRating");
                    VariableCollection <ServiceUnit> weights = new VariableCollection <ServiceUnit>(model, VariableType.Continuous, 0, double.PositiveInfinity, (ServiceUnit u) => { return(u.Ident); });

                    // --> Build model
                    // Add objective
                    if (_config.InputOriented)
                    {
                        model.SetObjective(efficiencyRating + 0, OptimizationSense.Minimize);
                    }
                    else
                    {
                        model.SetObjective(efficiencyRating + 0, OptimizationSense.Maximize);
                    }
                    // Add input constraints
                    if (_config.Inputs.Any())
                    {
                        foreach (var inputEntry in _config.Inputs)
                        {
                            // Shift and flip (if required) all values
                            Dictionary <ServiceUnit, double> inputValues = _serviceUnits.ToDictionary(
                                k => k,
                                s => s.GetValue(inputEntry.Item1, (FootprintDatapoint f) => { return(groupIdents.All(g => g.Item2 == f[g.Item1].ToString())); }));
                            // In case of loss values, convert them
                            if (inputEntry.Item2 == InputType.Hindrance)
                            {
                                switch (inputEntry.Item1)
                                {
                                case FootprintDatapoint.FootPrintEntry.SKUs:
                                    // Simply inverse them
                                    foreach (var serviceUnit in inputValues.Keys.ToList())
                                    {
                                        inputValues[serviceUnit] = 1.0 / inputValues[serviceUnit];
                                    }
                                    break;

                                default:
                                    // Simply flip them (next step will convert the numbers to positive ones again)
                                    foreach (var serviceUnit in inputValues.Keys.ToList())
                                    {
                                        inputValues[serviceUnit] *= -1;
                                    }
                                    break;
                                }
                            }
                            // If there is a negative value, shift all values to positive ones
                            double minOutputValue = inputValues.Min(v => v.Value);
                            if (minOutputValue < 0)
                            {
                                foreach (var serviceUnit in inputValues.Keys.ToList())
                                {
                                    inputValues[serviceUnit] += Math.Abs(minOutputValue);
                                }
                            }
                            // Add constraint
                            if (_config.InputOriented)
                            {
                                model.AddConstr(
                                    // Sum of all other weighted inputs
                                    LinearExpression.Sum(_serviceUnits.Select(s => inputValues[s]), _serviceUnits.Select(s => weights[s])) <=
                                    // Shall be smaller than the weighted input of the service unit in focus
                                    efficiencyRating * inputValues[serviceUnitInFocus], "Input" + inputEntry);
                            }
                            else
                            {
                                model.AddConstr(
                                    // Sum of all other weighted inputs
                                    LinearExpression.Sum(_serviceUnits.Select(s => inputValues[s]), _serviceUnits.Select(s => weights[s])) <=
                                    // Shall be smaller than the weighted input of the service unit in focus
                                    inputValues[serviceUnitInFocus], "Input" + inputEntry);
                            }
                        }
                    }
                    else
                    {
                        // Add constant uniform inputs for all service units
                        if (_config.InputOriented)
                        {
                            model.AddConstr(
                                // Sum of all other weighted inputs
                                LinearExpression.Sum(_serviceUnits.Select(s => 1.0), _serviceUnits.Select(s => weights[s])) <=
                                // Shall be smaller than the weighted input of the service unit in focus
                                efficiencyRating * 1.0, "InputConstant");
                        }
                        else
                        {
                            model.AddConstr(
                                // Sum of all other weighted inputs
                                LinearExpression.Sum(_serviceUnits.Select(s => 1.0), _serviceUnits.Select(s => weights[s])) <=
                                // Shall be smaller than the weighted input of the service unit in focus
                                1.0, "InputConstant");
                        }
                    }
                    // Add output constraints
                    if (_config.Outputs.Any())
                    {
                        // Add output constraint using the actual entry
                        foreach (var outputEntry in _config.Outputs)
                        {
                            // Shift and flip (if required) all values
                            Dictionary <ServiceUnit, double> outputValues = _serviceUnits.ToDictionary(
                                k => k,
                                s => s.GetValue(outputEntry.Item1, (FootprintDatapoint f) => { return(groupIdents.All(g => g.Item2 == f[g.Item1].ToString())); }));
                            // Store performance for this measure
                            foreach (var serviceUnit in _serviceUnits)
                            {
                                _serviceUnitOutputMeasures[serviceUnit, outputEntry.Item1] = outputValues[serviceUnit];
                            }
                            // In case of loss values, convert them
                            if (outputEntry.Item2 == OutputType.Loss)
                            {
                                switch (outputEntry.Item1)
                                {
                                case FootprintDatapoint.FootPrintEntry.OrderTurnoverTimeAvg:
                                case FootprintDatapoint.FootPrintEntry.OrderTurnoverTimeMed:
                                case FootprintDatapoint.FootPrintEntry.OrderTurnoverTimeLQ:
                                case FootprintDatapoint.FootPrintEntry.OrderTurnoverTimeUQ:
                                case FootprintDatapoint.FootPrintEntry.OrderThroughputTimeAvg:
                                case FootprintDatapoint.FootPrintEntry.OrderThroughputTimeMed:
                                case FootprintDatapoint.FootPrintEntry.OrderThroughputTimeLQ:
                                case FootprintDatapoint.FootPrintEntry.OrderThroughputTimeUQ:
                                case FootprintDatapoint.FootPrintEntry.BundleTurnoverTimeAvg:
                                case FootprintDatapoint.FootPrintEntry.BundleTurnoverTimeMed:
                                case FootprintDatapoint.FootPrintEntry.BundleTurnoverTimeLQ:
                                case FootprintDatapoint.FootPrintEntry.BundleTurnoverTimeUQ:
                                case FootprintDatapoint.FootPrintEntry.BundleThroughputTimeAvg:
                                case FootprintDatapoint.FootPrintEntry.BundleThroughputTimeMed:
                                case FootprintDatapoint.FootPrintEntry.BundleThroughputTimeLQ:
                                case FootprintDatapoint.FootPrintEntry.BundleThroughputTimeUQ:
                                    // Simply inverse them
                                    foreach (var serviceUnit in outputValues.Keys.ToList())
                                    {
                                        outputValues[serviceUnit] = 1.0 / outputValues[serviceUnit];
                                    }
                                    break;

                                case FootprintDatapoint.FootPrintEntry.OSIdleTimeAvg:
                                case FootprintDatapoint.FootPrintEntry.OSIdleTimeMed:
                                case FootprintDatapoint.FootPrintEntry.OSIdleTimeLQ:
                                case FootprintDatapoint.FootPrintEntry.OSIdleTimeUQ:
                                case FootprintDatapoint.FootPrintEntry.ISIdleTimeAvg:
                                case FootprintDatapoint.FootPrintEntry.ISIdleTimeMed:
                                case FootprintDatapoint.FootPrintEntry.ISIdleTimeLQ:
                                case FootprintDatapoint.FootPrintEntry.ISIdleTimeUQ:
                                case FootprintDatapoint.FootPrintEntry.OSDownTimeAvg:
                                case FootprintDatapoint.FootPrintEntry.OSDownTimeMed:
                                case FootprintDatapoint.FootPrintEntry.OSDownTimeLQ:
                                case FootprintDatapoint.FootPrintEntry.OSDownTimeUQ:
                                case FootprintDatapoint.FootPrintEntry.ISDownTimeAvg:
                                case FootprintDatapoint.FootPrintEntry.ISDownTimeMed:
                                case FootprintDatapoint.FootPrintEntry.ISDownTimeLQ:
                                case FootprintDatapoint.FootPrintEntry.ISDownTimeUQ:
                                case FootprintDatapoint.FootPrintEntry.LateOrdersFractional:
                                    // As these should be values between 0.0 and 1.0 just flip them within the range
                                {
                                    if (outputValues.Values.Any(v => v < 0 || v > 1))
                                    {
                                        throw new ArgumentException("Expected values to be within the range [0,1], but found one out of range!");
                                    }
                                    foreach (var serviceUnit in outputValues.Keys.ToList())
                                    {
                                        outputValues[serviceUnit] = 1.0 - outputValues[serviceUnit];
                                    }
                                }
                                break;

                                case FootprintDatapoint.FootPrintEntry.TimingDecisionsOverall:
                                case FootprintDatapoint.FootPrintEntry.TimingPathPlanningAvg:
                                case FootprintDatapoint.FootPrintEntry.TimingPathPlanningOverall:
                                case FootprintDatapoint.FootPrintEntry.TimingPathPlanningCount:
                                case FootprintDatapoint.FootPrintEntry.TimingTaskAllocationAvg:
                                case FootprintDatapoint.FootPrintEntry.TimingTaskAllocationOverall:
                                case FootprintDatapoint.FootPrintEntry.TimingTaskAllocationCount:
                                case FootprintDatapoint.FootPrintEntry.TimingItemStorageAvg:
                                case FootprintDatapoint.FootPrintEntry.TimingItemStorageOverall:
                                case FootprintDatapoint.FootPrintEntry.TimingItemStorageCount:
                                case FootprintDatapoint.FootPrintEntry.TimingPodStorageAvg:
                                case FootprintDatapoint.FootPrintEntry.TimingPodStorageOverall:
                                case FootprintDatapoint.FootPrintEntry.TimingPodStorageCount:
                                case FootprintDatapoint.FootPrintEntry.TimingRepositioningAvg:
                                case FootprintDatapoint.FootPrintEntry.TimingRepositioningOverall:
                                case FootprintDatapoint.FootPrintEntry.TimingRepositioningCount:
                                case FootprintDatapoint.FootPrintEntry.TimingReplenishmentBatchingAvg:
                                case FootprintDatapoint.FootPrintEntry.TimingReplenishmentBatchingOverall:
                                case FootprintDatapoint.FootPrintEntry.TimingReplenishmentBatchingCount:
                                case FootprintDatapoint.FootPrintEntry.TimingOrderBatchingAvg:
                                case FootprintDatapoint.FootPrintEntry.TimingOrderBatchingOverall:
                                case FootprintDatapoint.FootPrintEntry.TimingOrderBatchingCount:
                                    // Simply inverse them
                                    foreach (var serviceUnit in outputValues.Keys.ToList())
                                    {
                                        outputValues[serviceUnit] = 1.0 / outputValues[serviceUnit];
                                    }
                                    break;

                                default:
                                    // Simply flip them (next step will convert the numbers to positive ones again)
                                    foreach (var serviceUnit in outputValues.Keys.ToList())
                                    {
                                        outputValues[serviceUnit] *= -1;
                                    }
                                    break;
                                }
                            }
                            // If there is a negative value, shift all values to positive ones
                            double minOutputValue = outputValues.Min(v => v.Value);
                            if (minOutputValue < 0)
                            {
                                foreach (var serviceUnit in outputValues.Keys.ToList())
                                {
                                    outputValues[serviceUnit] += Math.Abs(minOutputValue);
                                }
                            }
                            // Add constraint
                            if (_config.InputOriented)
                            {
                                model.AddConstr(
                                    // Sum of all other weighted inputs
                                    LinearExpression.Sum(_serviceUnits.Select(s => outputValues[s]), _serviceUnits.Select(s => weights[s])) >=
                                    // Shall be smaller than the weighted input of the service unit in focus
                                    outputValues[serviceUnitInFocus], "Output" + outputEntry);
                            }
                            else
                            {
                                model.AddConstr(
                                    // Sum of all other weighted inputs
                                    LinearExpression.Sum(_serviceUnits.Select(s => outputValues[s]), _serviceUnits.Select(s => weights[s])) >=
                                    // Shall be smaller than the weighted input of the service unit in focus
                                    efficiencyRating * outputValues[serviceUnitInFocus], "Output" + outputEntry);
                            }
                        }
                    }
                    else
                    {
                        // Add constant uniform outputs for all service units
                        if (_config.InputOriented)
                        {
                            model.AddConstr(
                                // Sum of all other weighted inputs
                                LinearExpression.Sum(_serviceUnits.Select(s => 1.0), _serviceUnits.Select(s => weights[s])) >=
                                // Shall be smaller than the weighted input of the service unit in focus
                                1.0, "OutputConstant");
                        }
                        else
                        {
                            model.AddConstr(
                                // Sum of all other weighted inputs
                                LinearExpression.Sum(_serviceUnits.Select(s => 1.0), _serviceUnits.Select(s => weights[s])) >=
                                // Shall be smaller than the weighted input of the service unit in focus
                                efficiencyRating * 1.0, "OutputConstant");
                        }
                    }

                    // Sum weights
                    if (_config.WeightsSumToOne)
                    {
                        // Summed weights have to be equal to one
                        model.AddConstr(LinearExpression.Sum(_serviceUnits.Select(s => weights[s])) == 1.0, "WeightSum");
                    }

                    // Commit changes
                    model.Update();

                    // --> Solve model
                    model.Optimize();

                    // --> Get solution
                    if (!model.HasSolution())
                    {
                        throw new InvalidOperationException("Model is infeasible for service unit: " + serviceUnitInFocus.Ident);
                    }
                    _serviceUnitScores[groupIdents, serviceUnitInFocus] = efficiencyRating.Value;
                    _config.LogLine(" - Efficiency: " + (efficiencyRating.Value * 100).ToString(IOConstants.FORMATTER) + " %");
                }

                // Transform efficiency
                if (!_config.InputOriented && _config.TransformOutputOrientedEfficiency)
                {
                    //double maxEfficiency = _serviceUnits.Max(s => _serviceUnitScores[groupIdents, s]);
                    foreach (var serviceUnit in _serviceUnits)
                    {
                        _serviceUnitScores[groupIdents, serviceUnit] = 1.0 / _serviceUnitScores[groupIdents, serviceUnit];
                    }
                    // _serviceUnitScores[groupIdents, serviceUnit] /= maxEfficiency;
                }
            }
        }
Beispiel #12
0
        /// <summary>
        /// Transforms the object-model into a mathematical formulation
        /// </summary>
        /// <returns>The model</returns>
        internal override LinearModel Transform()
        {
            // Init
            LinearModel model = new LinearModel(ChosenSolver, Config.Log);
            double      bigMSideLengthOverall       = Instance.Containers.Max(c => Math.Max(Math.Max(c.Mesh.Length, c.Mesh.Width), c.Mesh.Height));
            Dictionary <int, double> bigMSideLength = new Dictionary <int, double>()
            {
                { _betas[0], Instance.Containers.Max(c => c.Mesh.Length) }, { _betas[1], Instance.Containers.Max(c => c.Mesh.Width) }, { _betas[2], Instance.Containers.Max(c => c.Mesh.Height) }
            };
            double slantBigM =
                Instance.Containers.Max(c => Math.Sqrt(Math.Pow(c.Mesh.Length, 2) + Math.Pow(c.Mesh.Width, 2) + Math.Pow(c.Mesh.Height, 2))) /
                Instance.Containers.Min(c => Math.Sqrt(Math.Pow(c.Mesh.Length, 2) + Math.Pow(c.Mesh.Width, 2) + Math.Pow(c.Mesh.Height, 2)));

            // --> Variables
            _itemIsPicked              = new VariableCollection <Piece, Container>(model, VariableType.Integer, 0, 1, (Piece piece, Container container) => { return("ItemPicked" + piece.ToIdentString() + container.ToIdentString()); });
            _containerUsed             = new VariableCollection <Container>(model, VariableType.Integer, 0, 1, (Container container) => { return("ContainerUsed" + container.ToIdentString()); });
            _itemOrientation           = new VariableCollection <int, Piece>(model, VariableType.Integer, 0, 1, (int orientation, Piece piece) => { return("ItemOrientation" + piece.ToIdentString() + "O" + orientation); });
            _localReferenceFrameOrigin = new VariableCollection <int, Piece>(model, VariableType.Continuous, 0, double.PositiveInfinity, (int beta, Piece piece) => { return("LocalReferenceFrameOrigin" + piece.ToIdentString() + "B" + beta); });
            _vertexPosition            = new VariableCollection <int, int, MeshCube, Piece>(model, VariableType.Continuous, 0, double.PositiveInfinity, (int beta, int vertexID, MeshCube cube, Piece piece) => { return("VertexPosition" + piece.ToIdentString() + cube.ToIdentString() + "VID" + vertexID + "Beta" + beta); });
            _lambda          = new VariableCollection <Container, int, int, MeshCube, Piece>(model, VariableType.Continuous, 0, double.PositiveInfinity, (Container container, int gamma, int vertexID, MeshCube cube, Piece piece) => { return("Lambda" + container.ToIdentString() + piece.ToIdentString() + cube.ToIdentString() + "VID" + vertexID + "Gamma" + gamma); });
            _sigmaPlus       = new VariableCollection <int, MeshCube, MeshCube, Piece, Piece>(model, VariableType.Integer, 0, 1, (int beta, MeshCube cube1, MeshCube cube2, Piece piece1, Piece piece2) => { return("SigmaPlus" + piece1.ToIdentString() + piece2.ToIdentString() + cube1.ToIdentString() + cube2.ToIdentString() + "Beta" + beta); });
            _sigmaMinus      = new VariableCollection <int, MeshCube, MeshCube, Piece, Piece>(model, VariableType.Integer, 0, 1, (int beta, MeshCube cube1, MeshCube cube2, Piece piece1, Piece piece2) => { return("SigmaMinus" + piece1.ToIdentString() + piece2.ToIdentString() + cube1.ToIdentString() + cube2.ToIdentString() + "Beta" + beta); });
            _locatedOnGround = new VariableCollection <Piece>(model, VariableType.Integer, 0, 1, (Piece cluster) => { return("LocatedOnGround" + cluster.ToIdentString()); });
            _locatedOn       = new VariableCollection <MeshCube, MeshCube, Piece, Piece>(model, VariableType.Integer, 0, 1, (MeshCube cube1, MeshCube cube2, Piece piece1, Piece piece2) => { return("LocatedOn" + piece1.ToIdentString() + piece2.ToIdentString() + cube1.ToIdentString() + cube2.ToIdentString()); });
            _bothInContainer = new VariableCollection <Container, Piece, Piece>(model, VariableType.Integer, 0, 1, (Container container, Piece piece1, Piece piece2) => { return("BothInContainer" + container.ToIdentString() + piece1.ToIdentString() + piece2.ToIdentString()); });

            // Keep model up-to-date
            model.Update();

            // --> Objective
            switch (Config.Goal)
            {
            case OptimizationGoal.MinContainer:
            {
                // Minimize container count
                model.SetObjective(
                    LinearExpression.Sum(Instance.Containers.Select(container => _containerUsed[container])),
                    OptimizationSense.Minimize);
            }
            break;

            case OptimizationGoal.MaxUtilization:
            {
                // Maximize utilization
                model.SetObjective(
                    LinearExpression.Sum(Instance.Containers.Select(container =>
                                                                    LinearExpression.Sum(Instance.Pieces.Select(piece =>
                                                                                                                _itemIsPicked[piece, container] * piece.Volume)))),
                    OptimizationSense.Maximize);
            }
            break;

            default:
                break;
            }

            // --> Constraints
            // Container usage
            foreach (var container in Instance.Containers)
            {
                foreach (var piece in Instance.Pieces)
                {
                    model.AddConstr(
                        _itemIsPicked[piece, container] <= _containerUsed[container],
                        "ContainerActivity" + container.ToIdentString() + piece.ToIdentString());
                }
            }
            // Orthogonality constraints
            foreach (var piece in Instance.Pieces)
            {
                model.AddConstr(
                    (Config.Goal == OptimizationGoal.MaxUtilization) ?
                    LinearExpression.Sum(Instance.Containers.Select(container => _itemIsPicked[piece, container])) <= 1 :
                    LinearExpression.Sum(Instance.Containers.Select(container => _itemIsPicked[piece, container])) == 1,
                    "ItemSingularity" + piece.ToIdentString());
            }
            foreach (var piece in Instance.Pieces)
            {
                model.AddConstr(
                    LinearExpression.Sum(MeshConstants.ORIENTATIONS.Select(orientation => _itemOrientation[orientation, piece])) ==
                    LinearExpression.Sum(Instance.Containers.Select(container => _itemIsPicked[piece, container])),
                    "UseOneOrientationPerItem" + piece.ToIdentString());
            }
            foreach (var beta in _betas)
            {
                foreach (var piece in Instance.Pieces)
                {
                    foreach (var cube in piece.Original.Components)
                    {
                        foreach (var vertexID in MeshConstants.VERTEX_IDS)
                        {
                            model.AddConstr(
                                _vertexPosition[beta, vertexID, cube, piece]
                                == _localReferenceFrameOrigin[beta, piece]
                                + LinearExpression.Sum(
                                    MeshConstants.ORIENTATIONS.Select(orientation =>
                                                                      piece[orientation][cube.ID][vertexID][beta] * _itemOrientation[orientation, piece])),
                                "LinkVerticesToLocalReferenceFrame" + piece.ToIdentString() + cube.ToIdentString() + "VID" + vertexID + "Beta" + beta);
                        }
                    }
                }
            }
            // Domain constraints
            foreach (var beta in _betas)
            {
                foreach (var piece in Instance.Pieces)
                {
                    foreach (var cube in piece.Original.Components)
                    {
                        foreach (var vertexID in MeshConstants.VERTEX_IDS.Skip(1))
                        {
                            model.AddConstr(
                                _vertexPosition[beta, vertexID, cube, piece]
                                ==
                                LinearExpression.Sum(Instance.Containers.Select(container =>
                                                                                LinearExpression.Sum(MeshConstants.VERTEX_IDS.Skip(1).Select(gamma =>
                                                                                                                                             container.Mesh[gamma][beta] *
                                                                                                                                             _lambda[container, gamma, vertexID, cube, piece])))),
                                "Domain1" + piece.ToIdentString() + cube.ToIdentString() + "VID" + vertexID + "Beta" + beta);
                        }
                    }
                }
            }
            foreach (var piece in Instance.Pieces)
            {
                foreach (var cube in piece.Original.Components)
                {
                    foreach (var vertexID in MeshConstants.VERTEX_IDS.Skip(1))
                    {
                        foreach (var container in Instance.Containers)
                        {
                            model.AddConstr(
                                LinearExpression.Sum(MeshConstants.VERTEX_IDS.Skip(1).Select(gamma =>
                                                                                             _lambda[container, gamma, vertexID, cube, piece]))
                                == _itemIsPicked[piece, container],
                                "Domain2" + container.ToIdentString() + piece.ToIdentString() + cube.ToIdentString() + "VID" + vertexID);
                        }
                    }
                }
            }
            // Non-intersection
            HashSet <Piece> seenPieces = new HashSet <Piece>();

            foreach (var piece1 in Instance.PiecesWithVirtuals.OrderBy(p => p.ID))
            {
                seenPieces.Add(piece1);

                foreach (var piece2 in Instance.PiecesWithVirtuals.OrderBy(p => p.ID).Except(seenPieces))
                {
                    foreach (var cube1 in piece1.Original.Components.OrderBy(c => c.ID))
                    {
                        foreach (var cube2 in piece2.Original.Components.OrderBy(c => c.ID))
                        {
                            foreach (var beta in _betas)
                            {
                                model.AddConstr(
                                    _vertexPosition[beta, 0, cube1, piece1]
                                    - _vertexPosition[beta, 0, cube2, piece2]
                                    >=
                                    (0.5 *
                                     LinearExpression.Sum(MeshConstants.ORIENTATIONS.Select(orientation =>
                                                                                            piece1[orientation][cube1.ID].SideLength(beta) * _itemOrientation[orientation, piece1]
                                                                                            +
                                                                                            piece2[orientation][cube2.ID].SideLength(beta) * _itemOrientation[orientation, piece2])))
                                    -
                                    (bigMSideLength[beta] * (1 - _sigmaPlus[beta, cube1, cube2, piece1, piece2]))
                                    ,
                                    "NonOverlapPos" + piece1.ToIdentString() + piece2.ToIdentString() + cube1.ToIdentString() + cube2.ToIdentString() + "Beta" + beta);
                                model.AddConstr(
                                    _vertexPosition[beta, 0, cube2, piece2]
                                    - _vertexPosition[beta, 0, cube1, piece1]
                                    >=
                                    (0.5 *
                                     LinearExpression.Sum(MeshConstants.ORIENTATIONS.Select(orientation =>
                                                                                            piece1[orientation][cube1.ID].SideLength(beta) * _itemOrientation[orientation, piece1]
                                                                                            +
                                                                                            piece2[orientation][cube2.ID].SideLength(beta) * _itemOrientation[orientation, piece2])))
                                    -
                                    (bigMSideLength[beta] * (1 - _sigmaMinus[beta, cube1, cube2, piece1, piece2]))
                                    ,
                                    "NonOverlapNeg" + piece1.ToIdentString() + piece2.ToIdentString() + cube1.ToIdentString() + cube2.ToIdentString() + "Beta" + beta);
                            }
                        }
                    }
                }
            }
            foreach (var container in Instance.Containers)
            {
                seenPieces.Clear();
                foreach (var piece1 in Instance.PiecesWithVirtuals.OrderBy(p => p.ID))
                {
                    seenPieces.Add(piece1);

                    foreach (var piece2 in Instance.PiecesWithVirtuals.OrderBy(p => p.ID).Except(seenPieces))
                    {
                        foreach (var cube1 in piece1.Original.Components.OrderBy(c => c.ID))
                        {
                            foreach (var cube2 in piece2.Original.Components.OrderBy(c => c.ID))
                            {
                                model.AddConstr(
                                    LinearExpression.Sum(_betas.Select(beta =>
                                                                       _sigmaPlus[beta, cube1, cube2, piece1, piece2] + _sigmaMinus[beta, cube1, cube2, piece1, piece2]))
                                    >=
                                    _itemIsPicked[piece1, container] + _itemIsPicked[piece2, container] - 1,
                                    "NonOverlapLink" +
                                    container.ToIdentString() + piece1.ToIdentString() + piece2.ToIdentString() + cube1.ToIdentString() + cube2.ToIdentString());
                                if (Instance.Containers.Count() <= 1)
                                {
                                    model.AddConstr(
                                        LinearExpression.Sum(_betas.Select(beta =>
                                                                           _sigmaPlus[beta, cube1, cube2, piece1, piece2] + _sigmaMinus[beta, cube1, cube2, piece1, piece2]))
                                        <=
                                        _itemIsPicked[piece1, container],
                                        "NonOverlapRedundant1" +
                                        container.ToIdentString() + piece1.ToIdentString() + piece2.ToIdentString() + cube1.ToIdentString() + cube2.ToIdentString());
                                    model.AddConstr(
                                        LinearExpression.Sum(_betas.Select(beta =>
                                                                           _sigmaPlus[beta, cube1, cube2, piece1, piece2] + _sigmaMinus[beta, cube1, cube2, piece1, piece2]))
                                        <=
                                        _itemIsPicked[piece2, container],
                                        "NonOverlapRedundant2" +
                                        container.ToIdentString() + piece1.ToIdentString() + piece2.ToIdentString() + cube1.ToIdentString() + cube2.ToIdentString());
                                }
                            }
                        }
                    }
                }
            }
            // Redundant volume limitation constraint
            foreach (var container in Instance.Containers)
            {
                model.AddConstr(
                    LinearExpression.Sum(Instance.PiecesWithVirtuals.Select(piece =>
                                                                            _itemIsPicked[piece, container] * piece.Volume))
                    <= (container.Mesh.Length * container.Mesh.Width * container.Mesh.Height),
                    "RedundantVolumeLimitation" + container.ToIdentString());
            }
            // Ensure that pieces do not protrude slants
            foreach (var container in Instance.Containers)
            {
                foreach (var slant in container.Slants)
                {
                    foreach (var piece in Instance.Pieces)
                    {
                        foreach (var component in piece.Original.Components)
                        {
                            // Use vertex depending on the normal vector of the slant
                            model.AddConstr(
                                ((slant.NormalVector.X >= 0 ? _vertexPosition[1, 8, component, piece] : _vertexPosition[1, 1, component, piece]) - slant.Position.X) * slant.NormalVector.X +
                                ((slant.NormalVector.Y >= 0 ? _vertexPosition[2, 8, component, piece] : _vertexPosition[2, 1, component, piece]) - slant.Position.Y) * slant.NormalVector.Y +
                                ((slant.NormalVector.Z >= 0 ? _vertexPosition[3, 8, component, piece] : _vertexPosition[3, 1, component, piece]) - slant.Position.Z) * slant.NormalVector.Z <=
                                0 + (1 - _itemIsPicked[piece, container]) * slantBigM,
                                "StayInSlants" + slant.ToIdentString() + piece.ToIdentString() + component.ToIdentString() + container.ToIdentString()
                                );
                        }
                    }
                }
            }
            // Fix virtual pieces to the predefined positions and orientations
            foreach (var container in Instance.Containers)
            {
                foreach (var virtualPiece in container.VirtualPieces)
                {
                    model.AddConstr(
                        _itemIsPicked[virtualPiece, container] == 1,
                        "VirtualPieceFixContainer" + container.ToIdentString() + virtualPiece.ToIdentString());
                    foreach (var orientation in MeshConstants.ORIENTATIONS)
                    {
                        model.AddConstr(
                            _itemOrientation[orientation, virtualPiece] == ((orientation == virtualPiece.FixedOrientation) ? 1 : 0),
                            "VirtualPieceFixOrientation" + container.ToIdentString() + virtualPiece.ToIdentString() + "O" + orientation.ToString());
                    }
                    foreach (var beta in _betas)
                    {
                        model.AddConstr(
                            _localReferenceFrameOrigin[beta, virtualPiece] == virtualPiece.FixedPosition[beta],
                            "VirtualPieceLocalReferenceFix" + container.ToIdentString() + virtualPiece.ToIdentString() + beta.ToString());
                        foreach (var component in virtualPiece.Original.Components)
                        {
                            foreach (var vertexID in MeshConstants.VERTEX_IDS)
                            {
                                model.AddConstr(
                                    _vertexPosition[beta, vertexID, component, virtualPiece] ==
                                    virtualPiece.FixedPosition[beta] + virtualPiece[virtualPiece.FixedOrientation][component.ID][vertexID][beta],
                                    "VirtualPieceVertexFix" + container.ToIdentString() + virtualPiece.ToIdentString() + component.ToIdentString() + "VID" + vertexID.ToString() + "Beta" + beta.ToString());
                            }
                        }
                    }
                }
            }
            // Ensure gravity-handling only if desired
            if (Config.HandleGravity)
            {
                // Gravity constraints
                foreach (var piece in Instance.Pieces.OrderBy(p => p.ID))
                {
                    model.AddConstr(
                        _localReferenceFrameOrigin[3, piece] <= (1 - _locatedOnGround[piece]) * bigMSideLengthOverall,
                        "GravityGround" + piece.ToIdentString());
                }
                foreach (var piece1 in Instance.Pieces.OrderBy(p => p.ID))
                {
                    foreach (var piece2 in Instance.PiecesWithVirtuals.Where(p => p != piece1))
                    {
                        // Track whether items are put into the same container
                        foreach (var container in Instance.Containers)
                        {
                            model.AddConstr(
                                _itemIsPicked[piece1, container] + _itemIsPicked[piece2, container] >=
                                2 * _bothInContainer[container, piece1, piece2],
                                "BothInSameContainer" + container.ToIdentString() + piece1.ToIdentString() + piece2.ToIdentString());
                        }

                        foreach (var cube1 in piece1.Original.Components.OrderBy(c => c.ID))
                        {
                            foreach (var cube2 in piece2.Original.Components.OrderBy(c => c.ID))
                            {
                                // Ensure that the lower side of piece one has the height of the upper side of piece two if the corresponding gravity variable is activated
                                model.AddConstr(
                                    _vertexPosition[3, 1, cube1, piece1] <=
                                    _vertexPosition[3, 8, cube2, piece2] +
                                    (1 - _locatedOn[cube1, cube2, piece1, piece2]) * bigMSideLengthOverall,
                                    "GravityZ1" + piece1.ToIdentString() + piece2.ToIdentString() + cube1.ToIdentString() + cube2.ToIdentString());
                                model.AddConstr(
                                    _vertexPosition[3, 1, cube1, piece1] +
                                    (1 - _locatedOn[cube1, cube2, piece1, piece2]) * bigMSideLengthOverall >=
                                    _vertexPosition[3, 8, cube2, piece2],
                                    "GravityZ2" + piece1.ToIdentString() + piece2.ToIdentString() + cube1.ToIdentString() + cube2.ToIdentString());
                                // Ensure that the piece is located above the other piece respecting X when activated
                                model.AddConstr(
                                    _vertexPosition[1, 0, cube1, piece1] >=
                                    _vertexPosition[1, 1, cube2, piece2] -
                                    (1 - _locatedOn[cube1, cube2, piece1, piece2]) * bigMSideLengthOverall,
                                    "GravityX1" + piece1.ToIdentString() + piece2.ToIdentString() + cube1.ToIdentString() + cube2.ToIdentString());
                                model.AddConstr(
                                    _vertexPosition[1, 0, cube1, piece1] <=
                                    _vertexPosition[1, 8, cube2, piece2] +
                                    (1 - _locatedOn[cube1, cube2, piece1, piece2]) * bigMSideLengthOverall,
                                    "GravityX2" + piece1.ToIdentString() + piece2.ToIdentString() + cube1.ToIdentString() + cube2.ToIdentString());
                                // Ensure that the piece is located above the other piece respecting Y when activated
                                model.AddConstr(
                                    _vertexPosition[2, 0, cube1, piece1] >=
                                    _vertexPosition[2, 1, cube2, piece2] -
                                    (1 - _locatedOn[cube1, cube2, piece1, piece2]) * bigMSideLengthOverall,
                                    "GravityY1" + piece1.ToIdentString() + piece2.ToIdentString() + cube1.ToIdentString() + cube2.ToIdentString());
                                model.AddConstr(
                                    _vertexPosition[2, 0, cube1, piece1] <=
                                    _vertexPosition[2, 8, cube2, piece2] +
                                    (1 - _locatedOn[cube1, cube2, piece1, piece2]) * bigMSideLengthOverall,
                                    "GravityY2" + piece1.ToIdentString() + piece2.ToIdentString() + cube1.ToIdentString() + cube2.ToIdentString());
                            }
                        }
                        // Ensure the same container when located on another piece
                        model.AddConstr(
                            LinearExpression.Sum(Instance.Containers.Select(container =>
                                                                            _bothInContainer[container, piece1, piece2])) >=
                            LinearExpression.Sum(piece1.Original.Components.Select(cube1 =>
                                                                                   LinearExpression.Sum(piece2.Original.Components.Select(cube2 =>
                                                                                                                                          _locatedOn[cube1, cube2, piece1, piece2])))),
                            "SameContainerWhenLocatedOn" + piece1.ToIdentString() + piece2.ToIdentString());
                    }
                }
                // Ensure that one gravity requirement is met
                foreach (var piece1 in Instance.Pieces)
                {
                    model.AddConstr(
                        LinearExpression.Sum(Instance.PiecesWithVirtuals.Where(p => p != piece1).Select(piece2 =>
                                                                                                        LinearExpression.Sum(piece1.Original.Components.Select(cube1 =>
                                                                                                                                                               LinearExpression.Sum(piece2.Original.Components.Select(cube2 =>
                                                                                                                                                                                                                      _locatedOn[cube1, cube2, piece1, piece2])))))) +
                        _locatedOnGround[piece1]
                        == 1,
                        "GravityEnsurance" + piece1.ToIdentString());
                }
            }
            // Ensure material compatibility only if desired
            if (Config.HandleCompatibility)
            {
                HashSet <VariablePiece> seenVariablePieces = new HashSet <VariablePiece>();

                foreach (var piece1 in Instance.Pieces.OrderBy(p => p.ID))
                {
                    seenVariablePieces.Add(piece1);

                    foreach (var piece2 in Instance.Pieces.OrderBy(p => p.ID).Except(seenVariablePieces).Where(p => p.Material.IncompatibleMaterials.Contains(piece1.Material.MaterialClass)))
                    {
                        foreach (var container in Instance.Containers)
                        {
                            model.AddConstr(
                                _itemIsPicked[piece1, container] + _itemIsPicked[piece2, container]
                                <= 1,
                                "MaterialCompatibility" + container.ToIdentString() + piece1.ToIdentString() + piece2.ToIdentString());
                        }
                    }
                }
            }
            // Ensure that items which are not marked as stackable won't get stacked on
            if (Config.HandleStackability)
            {
                foreach (var piece1 in Instance.Pieces.Where(p => !p.Stackable))
                {
                    foreach (var piece2 in Instance.Pieces.Where(p => p != piece1))
                    {
                        foreach (var cube1 in piece1.Original.Components)
                        {
                            foreach (var cube2 in piece2.Original.Components)
                            {
                                model.AddConstr(
                                    _locatedOn[cube2, cube1, piece2, piece1]
                                    == 0,
                                    "Stackability" + piece1.ToIdentString() + piece2.ToIdentString() + cube1.ToIdentString() + cube2.ToIdentString());
                            }
                        }
                    }
                }
            }
            // Ensure that no forbidden orientations get used
            if (Config.HandleForbiddenOrientations)
            {
                foreach (var piece in Instance.Pieces)
                {
                    foreach (var forbiddenOrientation in piece.ForbiddenOrientations)
                    {
                        model.AddConstr(
                            _itemOrientation[forbiddenOrientation, piece]
                            == 0,
                            "ForbiddenOrientation" + piece.ToIdentString() + "O" + forbiddenOrientation.ToString());
                    }
                }
            }
            // Forbid any kind of rotation if rotatability is not desired
            if (!Config.HandleRotatability)
            {
                foreach (var piece in Instance.Pieces)
                {
                    foreach (var orientation in MeshConstants.ORIENTATIONS.Skip(1))
                    {
                        model.AddConstr(
                            _itemOrientation[orientation, piece]
                            == 0,
                            "NoRotatability" + piece.ToIdentString() + "O" + orientation.ToString());
                    }
                }
            }

            // Keep model up-to-date
            model.Update();

            // Output some model statistics
            Config.Log("Model statistics:" + Environment.NewLine);
            Config.Log("ItemIsPicked: " + _itemIsPicked.Count + Environment.NewLine);
            Config.Log("ContainerUsed: " + _containerUsed.Count + Environment.NewLine);
            Config.Log("ItemOrientation: " + _itemOrientation.Count + Environment.NewLine);
            Config.Log("LocalReferenceFrameOrigin: " + _localReferenceFrameOrigin.Count + Environment.NewLine);
            Config.Log("VertexPosition: " + _vertexPosition.Count + Environment.NewLine);
            Config.Log("Lambda: " + _lambda.Count + Environment.NewLine);
            Config.Log("SigmaPlus: " + _sigmaPlus.Count + Environment.NewLine);
            Config.Log("SigmaMinus: " + _sigmaMinus.Count + Environment.NewLine);
            Config.Log("LocatedOnGround: " + _locatedOnGround.Count + Environment.NewLine);
            Config.Log("LocatedOn: " + _locatedOn.Count + Environment.NewLine);
            Config.Log("BothInContainer: " + _bothInContainer.Count + Environment.NewLine);

            // Return
            return(model);
        }
Beispiel #13
0
        private static void MonksTesting()
        {
            //path where the trained model shall be saved in or loaded from
            string path2SaveModel = Properties.Settings.Default.path2SaveModel;


            // Building a simple network
            Network n = new Network(new List <Layer>()
            {
                new Layer(new ActivationIdentity(), true, 17),
                new Layer(new ActivationSigmoid(), true, 3),

                new Layer(new ActivationSigmoid(), false, 1),
            }, false, AA1_MLP.Enums.WeightsInitialization.He);


            //loading monks Dataset and testing datasets
            MonksDataManager dm = new MonksDataManager();
            DataSet          ds = dm.LoadData(Properties.Settings.Default.TrainingSetLocation, 17);
            DataSet          dt = dm.LoadData(Properties.Settings.Default.TestSetLocation, 17);


            //loading cup like data

            //CupDataManager dm = new CupDataManager();
            //DataSet ds = dm.LoadData(Properties.Settings.Default.TrainingSetLocation, 1);
            //DataSet dt = dm.LoadData(Properties.Settings.Default.TestSetLocation, 1);


            //Loading a network should be like ...
            //var n = AA1_MLP.Utilities.ModelManager.LoadNetwork(PATH TO THE MODEL BINARY FILE);


            //**Creating a backpropagation trainer
            //var learningCurve = TrainWithSGD(n, ds, dt);


            // creating a linear model and training it with linear regression, need to move the model outside of the trainer!!!!
            LinearModel model         = new LinearModel();
            var         learningCurve = SolveWithLinearRegression(ds, dt, model);

            //LLS with normal equations solution
            //var tp = new TrainerParams();

            //**trying SVD
            //LinearLeastSquaresParams passedParams = new LinearLeastSquaresParams { model = model };
            //passedParams.trainingSet = ds;
            //passedParams.validationSet = dt;
            //var learningCurve = new LLSSVD().Train(passedParams);


            //var learningCurve = new LLSNormal().Train(passedParams);

            //creates an ADAM trainer
            //var learningCurve = TrainWithAdam(n, ds, dt);

            //writing the learning curve trainingdataWithBias to desk (ugly for memory, but simple)
            File.WriteAllText(Properties.Settings.Default.LearningCurveLocation, string.Join("\n", learningCurve.Select(s => string.Join(",", s))));


            //saving the trained network to desk
            //AA1_MLP.Utilities.ModelManager.SaveNetowrk(n, path2SaveModel);

            //CAUTION!!!****************$$$$$$$$$$$$$$$$$$$$$-----------------###############
            //CAUTION!!!****************$$$$$$$$$$$$$$$$$$$$$-----------------###############
            //CAUTION!!!****************$$$$$$$$$$$$$$$$$$$$$-----------------###############
            //CAUTION!!!****************$$$$$$$$$$$$$$$$$$$$$-----------------###############
            //This uses only the network for testing, neeeeeed tooooo wrrrriiiitttteeee one for Linear Least Squares uhhhhhhhhhhhhhh
            //Testing the model and outputing the confusion matrix
            AA1_MLP.Utilities.ModelManager.TesterMonkClassification(dt, model, 0.5, Properties.Settings.Default.TestReportLocation);



            //computing the ROC plot parameters

            //var file = new System.IO.StreamWriter(Properties.Settings.Default.ROCParamsStorageLocation);
            //for (float batchIndex = 0.005f; batchIndex <= 1.0f; batchIndex += 0.005f)
            //{
            //    var TprFpr = AA1_MLP.Utilities.ModelManager.TesterMonkClassification(dt, n, batchIndex);
            //    file.WriteLine(string.Format("{0},{1},{2}", batchIndex, TprFpr[0], TprFpr[1]));
            //}
            //file.Close();
        }
Beispiel #14
0
        private void launchthr()
        {
            foreach (plotxy pl in plotxys)
            {
                pl.Close();
            }

            point[] points;
            GC.Collect();
            LinearModel mosd = new LinearModel();

            mosd.initTimeMoments(100, 5, 6);
            mosd.calcMove();
            //mosd.timeMoments[0];
            double ro      = calc.StrPow(textBox_ro.Text, textBox_ropop.Text);
            double L       = calc.StrPow(textBox_L.Text, textBox_Lpop.Text);
            double h       = calc.StrPow(textBox_h.Text, textBox_hpop.Text);
            double b       = calc.StrPow(textBox_b.Text, textBox_bpop.Text);
            double D       = calc.StrPow(textBox_D.Text, textBox_Dpop.Text);
            double v0      = calc.StrPow(textBox_v0.Text, textBox_v0pop.Text);
            double vamp    = calc.StrPow(textBox_vamp.Text, textBox_vamppop.Text);
            int    numP    = Convert.ToInt32(textBox_numP.Text);
            double elastic = calc.StrPow(textBox_elas.Text, textBox_elaspop.Text);
            double Re      = calc.StrPow(textBox_Renum.Text, textBox_Renumpop.Text);
            string flname  = textBox_file.Text;

            ApplyEffect(this);
            thrdraw = new Thread(delegate()
            {
                if (flname != "")
                {
                    //string[] strLoads = new string[1];
                    //int res = myfuncs.getExtStr(flname, ref strLoads);
                    //if (res != 0)
                    //{
                    //    MessageBox.Show("Fail, Err#" + res);
                    //}
                    int[] findIndex = new int[1];
                    //res = myfuncs.getnumExtLoad(strLoads, ref findIndex);
                    //if (res != 0)
                    //{
                    //    MessageBox.Show("Fail, Err#" + res);
                    //}

                    if (findIndex.Length > 0)
                    {
                        //int numP_ext = Convert.ToInt32(strLoads[findIndex[findIndex.Length - 1]].Split(':')[1]);
                        //if (numP < numP_ext)
                        //{
                        //    MessageBoxResult messboxres_numP = MessageBox.Show("Выбрано меньше точек чем в файле эксперимента\r\n\r\nВзять число точек из файла?", "numP < countp", MessageBoxButton.YesNo);
                        //    switch (messboxres_numP)
                        //    {
                        //        case MessageBoxResult.No:
                        //            return;
                        //        case MessageBoxResult.Yes:
                        //            numP = numP_ext;
                        //            break;
                        //    }
                        //}
                        FileStream fs          = new FileStream(flname, FileMode.Open);
                        StreamReader sr        = new StreamReader(fs);
                        string strRead         = sr.ReadLine();
                        int countsExt          = Convert.ToInt32(strRead);
                        double[] time          = new double[countsExt];
                        double[][][] lstF      = new double[countsExt][][];
                        double[][][] lstFem1   = new double[countsExt][][];
                        double[][][] lstFep1   = new double[countsExt][][];
                        double[][][] lsta      = new double[countsExt][][];
                        double[][][] lstv      = new double[countsExt][][];
                        double[][][] lstdispla = new double[countsExt][][];
                        double[][][] lstcoords = new double[countsExt][][];
                        double[][][] lstb      = new double[countsExt][][];

                        double[][][] lstaAN      = new double[countsExt][][];
                        double[][][] lstvAN      = new double[countsExt][][];
                        double[][][] lstdisplAN  = new double[countsExt][][];
                        double[][][] lstcoordsAN = new double[countsExt][][];
                        double[][][] lstFAN      = new double[countsExt][][];

                        double[][][] lstVmp = new double[countsExt][][];

                        strRead              = sr.ReadLine();
                        double dtExt         = Convert.ToDouble(strRead);
                        string[] strload     = sr.ReadLine().Split(':');
                        points               = new point[numP];
                        ExtLoadType loadType = ExtLoad.getPoint(strload[2]);
                        if (Modeltype == Models.particle)
                        {
                            for (int np = 0; np < numP; np++)
                            {
                                points[np] = new point
                                {
                                    ExtLoad = loadType
                                };
                            }
                        }
                        else
                        {
                            for (int np = 0; np < numP; np++)
                            {
                                points[np]         = new point();
                                points[np].ExtLoad = ExtLoadType.none;
                            }
                        }
                        points[Convert.ToInt32(strload[1])].ExtLoad = ExtLoad.getPoint(strload[2]);
                        sr.Close();
                        fs.Close();
                        calc.t(countsExt, dtExt, ref time);
                        initArr._3d(numP, 3, ref lstF);
                        initArr._3d(numP, 3, ref lstdispla);
                        initArr._3d(numP, 3, ref lstcoords);
                        initArr.Coords(L / numP, points, ref lstcoords);
                        initArr._3d(numP, 3, ref lstFem1);
                        initArr._3d(numP, 3, ref lstFep1);
                        initArr._3d(numP, 3, ref lsta);
                        initArr._3d(numP, 3, ref lstv);
                        initArr._3d(numP, 3, ref lstb);
                        initArr._3d(numP, 3, ref lstaAN);
                        initArr._3d(numP, 3, ref lstvAN);
                        initArr._3d(numP, 3, ref lstdisplAN);
                        initArr._3d(numP, 3, ref lstcoordsAN);
                        initArr._3d(numP, 3, ref lstFAN);
                        initArr._3d(numP, 3, ref lstVmp);

                        if (CalcType == CalcTypes.statical)
                        {
                            calc.StaticMovement(flname, points, Modeltype, IntegShematype, CalcType, MaterialModeltype, Retype, IsConsoleOut,
                                                L, b, h, ro, numP, countsExt, elastic, v0, vamp, D, Re, time,
                                                ref lstF, ref lstFep1, ref lstFem1, ref lsta, ref lstb, ref lstv, ref lstdispla, ref lstcoords, ref lstvAN);
                        }
                        else
                        {
                            calc.Movement(flname, points, Modeltype, IntegShematype, CalcType, MaterialModeltype, Retype, IsConsoleOut,
                                          L, b, h, ro, numP, countsExt, elastic, v0, vamp, D, Re, time,
                                          ref lstF, ref lstFep1, ref lstFem1, ref lsta, ref lstb, ref lstv, ref lstdispla, ref lstcoords,
                                          ref lstaAN, ref lstvAN, ref lstdisplAN, ref lstcoordsAN, ref lstFAN, ref lstVmp);
                        }

                        Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                        {
                            plotxy plot = new plotxy();

                            plot = new plotxy();
                            plot.Show();
                            plot.dt     = dtExt;
                            plot.time   = time;
                            plot.coords = lstcoords;
                            plot.draw2d(axistype.t, axistype.x, numP, 1, true, false, "x(t)", "Time", "X", false, System.Drawing.Color.Red);
                            plot.initControls();
                            plotxys.Add(plot);

                            if (Modeltype == Models.particle)
                            {
                                plot = new plotxy();
                                plot.Show();
                                plot.dt     = dtExt;
                                plot.time   = time;
                                plot.coords = lstdisplAN;
                                plot.draw2d(axistype.t, axistype.x, numP, 1, true, false, "displAN(t)", "t", "displAN", false, System.Drawing.Color.Red);
                                plot.initControls();
                                plot.coords = lstdispla;
                                plot.draw2d(axistype.t, axistype.x, numP, 1, true, false, "displ(t)", "t", "displ", true, System.Drawing.Color.Blue);
                                plot.initControls();
                                plotxys.Add(plot);

                                plot = new plotxy();
                                plot.Show();
                                plot.dt     = dtExt;
                                plot.time   = time;
                                plot.coords = lstvAN;
                                plot.draw2d(axistype.t, axistype.x, numP, 1, true, false, "vAN(t)", "t", "vAN", false, System.Drawing.Color.Red);
                                plot.initControls();
                                plot.coords = lstv;
                                plot.draw2d(axistype.t, axistype.x, numP, 1, true, false, "v(t)", "t", "v", true, System.Drawing.Color.Blue);
                                plot.initControls();
                                plotxys.Add(plot);

                                plot = new plotxy();
                                plot.Show();
                                plot.dt     = dtExt;
                                plot.time   = time;
                                plot.coords = lstaAN;
                                plot.draw2d(axistype.t, axistype.x, numP, 1, true, false, "aAN(t)", "t", "aAN", false, System.Drawing.Color.Red);
                                plot.initControls();
                                plot.coords = lsta;
                                plot.draw2d(axistype.t, axistype.x, numP, 1, true, false, "a(t)", "t", "a", true, System.Drawing.Color.Blue);
                                plot.initControls();
                                plotxys.Add(plot);

                                plot = new plotxy();
                                plot.Show();
                                plot.dt     = dtExt;
                                plot.time   = time;
                                plot.coords = lstFAN;
                                plot.draw2d(axistype.t, axistype.x, numP, 1, true, false, "Fan(t)", "t", "Fan", false, System.Drawing.Color.Red);
                                plot.initControls();
                                plot.coords = lstF;
                                plot.draw2d(axistype.t, axistype.x, numP, 1, true, false, "F(t)", "t", "F", true, System.Drawing.Color.Blue);
                                plot.initControls();
                                plotxys.Add(plot);

                                plot = new plotxy();
                                plot.Show();
                                plot.dt     = dtExt;
                                plot.time   = time;
                                plot.coords = lstVmp;
                                plot.draw2d(axistype.t, axistype.x, numP, 1, true, false, "Fan(t)", "t", "Fan", false, System.Drawing.Color.Red);
                                plot.initControls();
                                plotxys.Add(plot);
                            }
                            //plot.Show();
                            //plot.draw2d(axistype.t, axistype.x, lstFep1, time, numP, 1, false, false, "Fep1(x)", "t", "N");
                            //plotxys.Add(plot);
                        }));
                        ClearEffect(this);
                        //GC.Collect();
                    }
                }
                else
                {
                    MessageBox.Show("В файле нет нагруженных точек");
                }
            });
            thrdraw.Start();
        }
        /// <summary>
        /// Transforms the object-model into a mathematical formulation
        /// </summary>
        /// <returns>The model</returns>
        internal override LinearModel Transform()
        {
            // Init
            LinearModel model = new LinearModel(ChosenSolver, Config.Log);

            // TODO retrieve this stuff in a better way!?
            double excessLengthShare = 0.1;

            // Set big Ms
            double bigMContainerLength = Instance.Containers.Max(c => c.Mesh.Length);
            double bigMContainerWidth  = Instance.Containers.Max(c => c.Mesh.Width);
            double bigMContainerHeight = Instance.Containers.Max(c => c.Mesh.Height);
            double bigM      = Instance.Containers.Max(c => Math.Max(Math.Max(c.Mesh.Length, c.Mesh.Width), c.Mesh.Height));
            double slantBigM =
                Instance.Containers.Max(c => Math.Sqrt(Math.Pow(c.Mesh.Length, 2) + Math.Pow(c.Mesh.Width, 2) + Math.Pow(c.Mesh.Height, 2))) /
                Instance.Containers.Min(c => Math.Sqrt(Math.Pow(c.Mesh.Length, 2) + Math.Pow(c.Mesh.Width, 2) + Math.Pow(c.Mesh.Height, 2)));

            // --> Variables
            _pieceIsInContainer = new VariableCollection <Piece, Container>(model, VariableType.Integer, 0, 1, (Piece piece, Container container) => { return("PieceInContainer" + piece.ToIdentString() + container.ToIdentString()); });
            _containerUsed      = new VariableCollection <Container>(model, VariableType.Integer, 0, 1, (Container container) => { return("ContainerIsUsed" + container.ToIdentString()); });
            _frontLeftBottomX   = new VariableCollection <Piece>(model, VariableType.Continuous, 0, bigMContainerLength, (Piece piece) => { return("FrontLeftBottomPositionX" + piece.ToIdentString()); });
            _frontLeftBottomY   = new VariableCollection <Piece>(model, VariableType.Continuous, 0, bigMContainerWidth, (Piece piece) => { return("FrontLeftBottomPositionY" + piece.ToIdentString()); });
            _frontLeftBottomZ   = new VariableCollection <Piece>(model, VariableType.Continuous, 0, bigMContainerHeight, (Piece piece) => { return("FrontLeftBottomPositionZ" + piece.ToIdentString()); });
            _rearRightTopX      = new VariableCollection <Piece>(model, VariableType.Continuous, 0, bigMContainerLength, (Piece piece) => { return("RearRightTopPositionX" + piece.ToIdentString()); });
            _rearRightTopY      = new VariableCollection <Piece>(model, VariableType.Continuous, 0, bigMContainerWidth, (Piece piece) => { return("RearRightTopPositionY" + piece.ToIdentString()); });
            _rearRightTopZ      = new VariableCollection <Piece>(model, VariableType.Continuous, 0, bigMContainerHeight, (Piece piece) => { return("RearRightTopPositionZ" + piece.ToIdentString()); });
            _left            = new VariableCollection <Piece, Piece>(model, VariableType.Integer, 0, 1, (Piece piece1, Piece piece2) => { return("LeftFrom" + piece1.ToIdentString() + piece2.ToIdentString()); });
            _right           = new VariableCollection <Piece, Piece>(model, VariableType.Integer, 0, 1, (Piece piece1, Piece piece2) => { return("RightFrom" + piece1.ToIdentString() + piece2.ToIdentString()); });
            _behind          = new VariableCollection <Piece, Piece>(model, VariableType.Integer, 0, 1, (Piece piece1, Piece piece2) => { return("BehindFrom" + piece1.ToIdentString() + piece2.ToIdentString()); });
            _front           = new VariableCollection <Piece, Piece>(model, VariableType.Integer, 0, 1, (Piece piece1, Piece piece2) => { return("FrontFrom" + piece1.ToIdentString() + piece2.ToIdentString()); });
            _above           = new VariableCollection <Piece, Piece>(model, VariableType.Integer, 0, 1, (Piece piece1, Piece piece2) => { return("AboveFrom" + piece1.ToIdentString() + piece2.ToIdentString()); });
            _below           = new VariableCollection <Piece, Piece>(model, VariableType.Integer, 0, 1, (Piece piece1, Piece piece2) => { return("BelowFrom" + piece1.ToIdentString() + piece2.ToIdentString()); });
            _rotation        = new VariableCollection <Piece, int, int>(model, VariableType.Integer, 0, 1, (Piece piece, int p, int q) => { return("Rotation" + piece.ToIdentString() + "p" + p + "q" + q); });
            _bothInContainer = new VariableCollection <Container, Piece, Piece>(model, VariableType.Integer, 0, 1, (Container container, Piece piece1, Piece piece2) => { return("SameContainer" + container.ToIdentString() + piece1.ToIdentString() + piece2.ToIdentString()); });
            _locatedOn       = new VariableCollection <Piece, Piece>(model, VariableType.Integer, 0, 1, (Piece piece1, Piece piece2) => { return("LocatedOn" + piece1.ToIdentString() + piece2.ToIdentString()); });
            _locatedOnGround = new VariableCollection <Piece>(model, VariableType.Integer, 0, 1, (Piece piece) => { return("LocatedOnGround" + piece.ToIdentString()); });

            // Keep model up-to-date
            model.Update();

            // --> Objective
            switch (Config.Goal)
            {
            case OptimizationGoal.MinContainer:
            {
                // Minimize container count
                model.SetObjective(
                    LinearExpression.Sum(Instance.Containers.Select(container => _containerUsed[container])),
                    OptimizationSense.Minimize);
            }
            break;

            case OptimizationGoal.MaxUtilization:
            {
                // Maximize utilization
                model.SetObjective(
                    LinearExpression.Sum(Instance.Pieces.Select(p => (p.Volume)
                                                                * LinearExpression.Sum(Instance.Containers.Select(c => _pieceIsInContainer[p, c])))),
                    OptimizationSense.Maximize);
            }
            break;

            default:
                break;
            }


            // --> Constraints
            // Only assign to container if the container is in use
            foreach (var container in Instance.Containers)
            {
                foreach (var piece in Instance.Pieces)
                {
                    model.AddConstr(
                        _pieceIsInContainer[piece, container] <= _containerUsed[container],
                        "OnlyAssignIfContainerIsUsed" + container.ToIdentString() + piece.ToIdentString());
                }
            }
            // Ensure that piece is only added to one container
            foreach (var piece in Instance.Pieces)
            {
                model.AddConstr(
                    (Config.Goal == OptimizationGoal.MaxUtilization) ?
                    LinearExpression.Sum(Instance.Containers.Select(c => _pieceIsInContainer[piece, c])) <= 1 :
                    LinearExpression.Sum(Instance.Containers.Select(c => _pieceIsInContainer[piece, c])) == 1,
                    "AssignToSingleContainer" + piece.ToIdentString());
            }
            // Ensure that the gross weight is not exceeded // TODO enable again!?
            //foreach (var container in _instance.Containers)
            //{
            //    model.AddConstraint(
            //        Expression.Sum(_instance.Pieces.Select(p => _pieceIsInContainer[p, container] * p.Weight)) <= containerGrossWeight,
            //        "GrossWeightCapacityLimitation" + container.ToIdentString());
            //}
            // Ensure that the pieces stay in the container
            foreach (var piece in Instance.Pieces)
            {
                foreach (var container in Instance.Containers)
                {
                    // Consider X-value
                    model.AddConstr(
                        _rearRightTopX[piece] <= bigMContainerLength - ((bigMContainerLength - container.Mesh.Length) * _pieceIsInContainer[piece, container]),
                        "StayInsideX" + piece.ToIdentString() + container.ToIdentString());
                    // Consider Y-value
                    model.AddConstr(
                        _rearRightTopY[piece] <= bigMContainerWidth - ((bigMContainerWidth - container.Mesh.Width) * _pieceIsInContainer[piece, container]),
                        "StayInsideY" + piece.ToIdentString() + container.ToIdentString());
                    // Consider Z-value
                    model.AddConstr(
                        _rearRightTopZ[piece] <= bigMContainerHeight - ((bigMContainerHeight - container.Mesh.Height) * _pieceIsInContainer[piece, container]),
                        "StayInsideZ" + piece.ToIdentString() + container.ToIdentString());
                }
            }
            // Ensure that pieces do not protrude slants
            foreach (var container in Instance.Containers)
            {
                foreach (var slant in container.Slants)
                {
                    foreach (var piece in Instance.Pieces)
                    {
                        // Use vertex depending on the normal vector of the slant
                        model.AddConstr(
                            ((slant.NormalVector.X >= 0 ? _rearRightTopX[piece] : _frontLeftBottomX[piece]) - slant.Position.X) * slant.NormalVector.X +
                            ((slant.NormalVector.Y >= 0 ? _rearRightTopY[piece] : _frontLeftBottomY[piece]) - slant.Position.Y) * slant.NormalVector.Y +
                            ((slant.NormalVector.Z >= 0 ? _rearRightTopZ[piece] : _frontLeftBottomZ[piece]) - slant.Position.Z) * slant.NormalVector.Z <=
                            0 + (1 - _pieceIsInContainer[piece, container]) * slantBigM,
                            "StayInSlants" + slant.ToIdentString() + piece.ToIdentString() + container.ToIdentString()
                            );
                    }
                }
            }
            // Ensure that the boxes can rotate by 90 degrees
            foreach (var piece in Instance.Pieces)
            {
                // Set x-value
                model.AddConstr(
                    _rearRightTopX[piece] - _frontLeftBottomX[piece] ==
                    _rotation[piece, 1, 1] * piece.Original.BoundingBox.Length +
                    _rotation[piece, 1, 2] * piece.Original.BoundingBox.Width +
                    _rotation[piece, 1, 3] * piece.Original.BoundingBox.Height,
                    "RotationXValue" + piece.ToIdentString());
                // Set y-value
                model.AddConstr(
                    _rearRightTopY[piece] - _frontLeftBottomY[piece] ==
                    _rotation[piece, 2, 1] * piece.Original.BoundingBox.Length +
                    _rotation[piece, 2, 2] * piece.Original.BoundingBox.Width +
                    _rotation[piece, 2, 3] * piece.Original.BoundingBox.Height,
                    "RotationYValue" + piece.ToIdentString());
                // Set z-value
                model.AddConstr(
                    _rearRightTopZ[piece] - _frontLeftBottomZ[piece] ==
                    _rotation[piece, 3, 1] * piece.Original.BoundingBox.Length +
                    _rotation[piece, 3, 2] * piece.Original.BoundingBox.Width +
                    _rotation[piece, 3, 3] * piece.Original.BoundingBox.Height,
                    "RotationZValue" + piece.ToIdentString());
            }
            foreach (var piece in Instance.Pieces)
            {
                foreach (var q in _rotationIndexes)
                {
                    model.AddConstr(
                        LinearExpression.Sum(_rotationIndexes.Select(p => _rotation[piece, p, q])) == 1,
                        "RotationHelper1" + piece.ToIdentString() + "q" + q);
                }
                foreach (var p in _rotationIndexes)
                {
                    model.AddConstr(
                        LinearExpression.Sum(_rotationIndexes.Select(q => _rotation[piece, p, q])) == 1,
                        "RotationHelper2" + piece.ToIdentString() + "p" + p);
                }
            }
            // Link FLB corner point with RRT corner point for virtual pieces
            foreach (var container in Instance.Containers)
            {
                foreach (var virtualPiece in container.VirtualPieces)
                {
                    model.AddConstr(
                        _rearRightTopX[virtualPiece] - _frontLeftBottomX[virtualPiece] == virtualPiece[virtualPiece.FixedOrientation].BoundingBox.Length,
                        "LinkFLBRRTX" + container.ToIdentString() + virtualPiece.ToIdentString());
                    model.AddConstr(
                        _rearRightTopY[virtualPiece] - _frontLeftBottomY[virtualPiece] == virtualPiece[virtualPiece.FixedOrientation].BoundingBox.Width,
                        "LinkFLBRRTY" + container.ToIdentString() + virtualPiece.ToIdentString());
                    model.AddConstr(
                        _rearRightTopZ[virtualPiece] - _frontLeftBottomZ[virtualPiece] == virtualPiece[virtualPiece.FixedOrientation].BoundingBox.Height,
                        "LinkFLBRRTZ" + container.ToIdentString() + virtualPiece.ToIdentString());
                }
            }
            // Link the variables
            foreach (var container in Instance.Containers)
            {
                // Remember seen pieces
                HashSet <Piece> seenPieces = new HashSet <Piece>();

                // Iterate pieces
                foreach (var piece in Instance.PiecesWithVirtuals)
                {
                    // Remember piece
                    seenPieces.Add(piece);

                    // Iterate pieces (inner)
                    foreach (var secondPiece in Instance.PiecesWithVirtuals.Except(seenPieces))
                    {
                        model.AddConstr(
                            _frontLeftBottomX[piece]
                            - _rearRightTopX[secondPiece]
                            + ((1 - _left[secondPiece, piece]) * bigM)
                            + ((2 - (_pieceIsInContainer[piece, container] + _pieceIsInContainer[secondPiece, container])) * bigM)
                            >= 0,
                            "Link1" + container.ToIdentString() + piece.ToIdentString() + secondPiece.ToIdentString());
                        model.AddConstr(
                            _frontLeftBottomX[secondPiece]
                            - _rearRightTopX[piece]
                            + ((1 - _right[secondPiece, piece]) * bigM)
                            + ((2 - (_pieceIsInContainer[piece, container] + _pieceIsInContainer[secondPiece, container])) * bigM)
                            >= 0,
                            "Link2" + container.ToIdentString() + piece.ToIdentString() + secondPiece.ToIdentString());
                        model.AddConstr(
                            _frontLeftBottomY[piece]
                            - _rearRightTopY[secondPiece]
                            + ((1 - _behind[secondPiece, piece]) * bigM)
                            + ((2 - (_pieceIsInContainer[piece, container] + _pieceIsInContainer[secondPiece, container])) * bigM)
                            >= 0,
                            "Link3" + container.ToIdentString() + piece.ToIdentString() + secondPiece.ToIdentString());
                        model.AddConstr(
                            _frontLeftBottomY[secondPiece]
                            - _rearRightTopY[piece]
                            + ((1 - _front[secondPiece, piece]) * bigM)
                            + ((2 - (_pieceIsInContainer[piece, container] + _pieceIsInContainer[secondPiece, container])) * bigM)
                            >= 0,
                            "Link4" + container.ToIdentString() + piece.ToIdentString() + secondPiece.ToIdentString());
                        model.AddConstr(
                            _frontLeftBottomZ[piece]
                            - _rearRightTopZ[secondPiece]
                            + ((1 - _above[secondPiece, piece]) * bigM)
                            + ((2 - (_pieceIsInContainer[piece, container] + _pieceIsInContainer[secondPiece, container])) * bigM)
                            >= 0,
                            "Link5" + container.ToIdentString() + piece.ToIdentString() + secondPiece.ToIdentString());
                        model.AddConstr(
                            _frontLeftBottomZ[secondPiece]
                            - _rearRightTopZ[piece]
                            + ((1 - _below[secondPiece, piece]) * bigM)
                            + ((2 - (_pieceIsInContainer[piece, container] + _pieceIsInContainer[secondPiece, container])) * bigM)
                            >= 0,
                            "Link6" + container.ToIdentString() + piece.ToIdentString() + secondPiece.ToIdentString());
                    }
                }
            }
            // Ensure non-overlapping
            foreach (var piece in Instance.PiecesWithVirtuals)
            {
                foreach (var secondPiece in Instance.PiecesWithVirtuals)
                {
                    model.AddConstr(
                        _left[secondPiece, piece] +
                        _right[secondPiece, piece] +
                        _behind[secondPiece, piece] +
                        _front[secondPiece, piece] +
                        _above[secondPiece, piece] +
                        _below[secondPiece, piece] >= 1,
                        "EnsureNonOverlapping" + piece.ToIdentString() + secondPiece.ToIdentString());
                }
            }
            // Redundant volume limitation constraints
            foreach (var container in Instance.Containers)
            {
                model.AddConstr(
                    LinearExpression.Sum(Instance.PiecesWithVirtuals.Select(piece =>
                                                                            _pieceIsInContainer[piece, container] * piece.Original.BoundingBox.Volume))
                    <= (container.Mesh.Length * container.Mesh.Width * container.Mesh.Height),
                    "RedundantVolumeLimitation" + container.ToIdentString());
            }
            // Fix virtual pieces to the predefined positions and orientations
            foreach (var container in Instance.Containers)
            {
                foreach (var virtualPiece in container.VirtualPieces)
                {
                    model.AddConstr(
                        _pieceIsInContainer[virtualPiece, container] == 1,
                        "VirtualPieceFixContainer" + container.ToIdentString() + virtualPiece.ToIdentString());
                    model.AddConstr(
                        _frontLeftBottomX[virtualPiece] == virtualPiece.FixedPosition.X,
                        "VirtualPieceFixPositionX" + container.ToIdentString() + virtualPiece.ToIdentString());
                    model.AddConstr(
                        _frontLeftBottomY[virtualPiece] == virtualPiece.FixedPosition.Y,
                        "VirtualPieceFixPositionY" + container.ToIdentString() + virtualPiece.ToIdentString());
                    model.AddConstr(
                        _frontLeftBottomZ[virtualPiece] == virtualPiece.FixedPosition.Z,
                        "VirtualPieceFixPositionZ" + container.ToIdentString() + virtualPiece.ToIdentString());
                }
            }
            // Ensure gravity only if desired
            if (Config.HandleGravity)
            {
                // Gravity
                Piece[] supporteeArray = Instance.Pieces.ToArray();
                Piece[] supporterArray = Instance.PiecesWithVirtuals.ToArray();
                _pieceTuples = new List <Tuple <Piece, Piece> >();
                for (int i = 0; i < supporteeArray.Length; i++)
                {
                    for (int j = 0; j < supporterArray.Length; j++)
                    {
                        if (supporteeArray[i] != supporterArray[j])
                        {
                            _pieceTuples.Add(new Tuple <Piece, Piece>(supporteeArray[i], supporterArray[j]));
                        }
                    }
                }
                foreach (var tuple in _pieceTuples)
                {
                    // Z-distance has to equal 0 if located on the specified piece
                    model.AddConstr(
                        _frontLeftBottomZ[tuple.Item1] <=
                        _rearRightTopZ[tuple.Item2] +
                        (1 - _locatedOn[tuple.Item1, tuple.Item2]) * bigM,
                        "EnsureGravityZ1-" + tuple.Item1.ToIdentString() + tuple.Item2.ToIdentString());
                    model.AddConstr(
                        _frontLeftBottomZ[tuple.Item1] +
                        (1 - _locatedOn[tuple.Item1, tuple.Item2]) * bigM >=
                        _rearRightTopZ[tuple.Item2],
                        "EnsureGravityZ2-" + tuple.Item1.ToIdentString() + tuple.Item2.ToIdentString());
                    // Located on another piece regarding X and Y - respectively stability
                    model.AddConstr(
                        _rearRightTopY[tuple.Item1]
                        <= _rearRightTopY[tuple.Item2]
                        + (excessLengthShare * (_rearRightTopY[tuple.Item1] - _frontLeftBottomY[tuple.Item1]))
                        + (bigM * (1 - _locatedOn[tuple.Item1, tuple.Item2])),
                        "EnsureStabilityY1-" + tuple.Item1.ToIdentString() + tuple.Item2.ToIdentString());
                    model.AddConstr(
                        _rearRightTopX[tuple.Item1]
                        <= _rearRightTopX[tuple.Item2]
                        + (excessLengthShare * (_rearRightTopX[tuple.Item1] - _frontLeftBottomX[tuple.Item1]))
                        + (bigM * (1 - _locatedOn[tuple.Item1, tuple.Item2])),
                        "EnsureStabilityX1-" + tuple.Item1.ToIdentString() + tuple.Item2.ToIdentString());
                    model.AddConstr(
                        _frontLeftBottomY[tuple.Item1]
                        >= _frontLeftBottomY[tuple.Item2]
                        - (excessLengthShare * (_rearRightTopY[tuple.Item1] - _frontLeftBottomY[tuple.Item1]))
                        - (bigM * (1 - _locatedOn[tuple.Item1, tuple.Item2])),
                        "EnsureStabilityY2-" + tuple.Item1.ToIdentString() + tuple.Item2.ToIdentString());
                    model.AddConstr(
                        _frontLeftBottomX[tuple.Item1]
                        >= _frontLeftBottomX[tuple.Item2]
                        - (excessLengthShare * (_rearRightTopX[tuple.Item1] - _frontLeftBottomX[tuple.Item1]))
                        - (bigM * (1 - _locatedOn[tuple.Item1, tuple.Item2])),
                        "EnsureStabilityX2-" + tuple.Item1.ToIdentString() + tuple.Item2.ToIdentString());
                    // Track whether items are put into the same container
                    foreach (var container in Instance.Containers)
                    {
                        model.AddConstr(
                            _pieceIsInContainer[tuple.Item1, container] + _pieceIsInContainer[tuple.Item2, container] >=
                            2 * _bothInContainer[container, tuple.Item1, tuple.Item2],
                            "BothInSameContainer" + container.ToIdentString() + tuple.Item1.ToIdentString() + tuple.Item2.ToIdentString());
                    }
                    // Ensure the same container when located on another piece
                    model.AddConstr(
                        LinearExpression.Sum(Instance.Containers.Select(container =>
                                                                        _bothInContainer[container, tuple.Item1, tuple.Item2])) >=
                        _locatedOn[tuple.Item1, tuple.Item2],
                        "SameContainerWhenLocatedOn" + tuple.Item1.ToIdentString() + tuple.Item2.ToIdentString());
                }
                // Located on ground if no piece is below the specified one
                foreach (var piece in Instance.Pieces)
                {
                    model.AddConstr(
                        _frontLeftBottomZ[piece] <= (1 - _locatedOnGround[piece]) * bigM,
                        "LocatedOnGround" + piece.ToIdentString());
                }
                // Locate pieces on other pieces or the ground
                foreach (var piece in Instance.Pieces)
                {
                    model.AddConstr(
                        LinearExpression.Sum(_pieceTuples
                                             .Where(t => t.Item1 == piece)
                                             .Select(tuple => _locatedOn[tuple.Item1, tuple.Item2])) +
                        _locatedOnGround[piece]
                        == 1,
                        "LocatedOnAnotherPiece-" + piece.ToIdentString());
                }
            }
            // Ensure material compatibility only if desired
            if (Config.HandleCompatibility)
            {
                HashSet <VariablePiece> seenPieces = new HashSet <VariablePiece>();

                foreach (var piece1 in Instance.Pieces.OrderBy(p => p.ID))
                {
                    seenPieces.Add(piece1);

                    foreach (var piece2 in Instance.Pieces.OrderBy(p => p.ID).Except(seenPieces).Where(p => p.Material.IncompatibleMaterials.Contains(piece1.Material.MaterialClass)))
                    {
                        foreach (var container in Instance.Containers)
                        {
                            model.AddConstr(
                                _pieceIsInContainer[piece1, container] + _pieceIsInContainer[piece2, container]
                                <= 1,
                                "MaterialCompatibility" + container.ToIdentString() + piece1.ToIdentString() + piece2.ToIdentString());
                        }
                    }
                }
            }
            // Ensure that items which are not marked as stackable won't get stacked on
            if (Config.HandleStackability)
            {
                foreach (var piece1 in Instance.Pieces.Where(p => !p.Stackable))
                {
                    foreach (var piece2 in Instance.Pieces.Where(p => p != piece1))
                    {
                        model.AddConstr(
                            _locatedOn[piece2, piece1]
                            == 0,
                            "Stackability" + piece1.ToIdentString() + piece2.ToIdentString());
                    }
                }
            }
            // Ensure that no forbidden orientations get used
            if (Config.HandleForbiddenOrientations)
            {
                foreach (var piece in Instance.Pieces)
                {
                    foreach (var forbiddenOrientation in piece.ForbiddenOrientations)
                    {
                        switch (forbiddenOrientation)
                        {
                        case 0:
                            model.AddConstr(
                                _rotation[piece, 1, 1] + _rotation[piece, 2, 2] + _rotation[piece, 3, 3] <= 2,
                                "ForbiddenOrientation" + piece.ToIdentString() + "O" + forbiddenOrientation.ToString());
                            break;

                        case 2:
                            model.AddConstr(
                                _rotation[piece, 1, 1] + _rotation[piece, 2, 3] + _rotation[piece, 3, 2] <= 2,
                                "ForbiddenOrientation" + piece.ToIdentString() + "O" + forbiddenOrientation.ToString());
                            break;

                        case 8:
                            model.AddConstr(
                                _rotation[piece, 1, 2] + _rotation[piece, 2, 1] + _rotation[piece, 3, 3] <= 2,
                                "ForbiddenOrientation" + piece.ToIdentString() + "O" + forbiddenOrientation.ToString());
                            break;

                        case 10:
                            model.AddConstr(
                                _rotation[piece, 1, 3] + _rotation[piece, 2, 1] + _rotation[piece, 3, 2] <= 2,
                                "ForbiddenOrientation" + piece.ToIdentString() + "O" + forbiddenOrientation.ToString());
                            break;

                        case 16:
                            model.AddConstr(
                                _rotation[piece, 1, 2] + _rotation[piece, 2, 3] + _rotation[piece, 3, 1] <= 2,
                                "ForbiddenOrientation" + piece.ToIdentString() + "O" + forbiddenOrientation.ToString());
                            break;

                        case 18:
                            model.AddConstr(
                                _rotation[piece, 1, 3] + _rotation[piece, 2, 2] + _rotation[piece, 3, 1] <= 2,
                                "ForbiddenOrientation" + piece.ToIdentString() + "O" + forbiddenOrientation.ToString());
                            break;

                        default:
                            break;
                        }
                    }
                }
            }
            // Forbid any kind of rotation if rotatability is not desired
            if (!Config.HandleRotatability)
            {
                foreach (var piece in Instance.Pieces)
                {
                    foreach (var orientation in MeshConstants.ORIENTATIONS.Skip(1))
                    {
                        switch (orientation)
                        {
                        case 0:
                            model.AddConstr(
                                _rotation[piece, 1, 1] + _rotation[piece, 2, 2] + _rotation[piece, 3, 3] <= 2,
                                "ForbiddenOrientation" + piece.ToIdentString() + "O" + orientation.ToString());
                            break;

                        case 2:
                            model.AddConstr(
                                _rotation[piece, 1, 1] + _rotation[piece, 2, 3] + _rotation[piece, 3, 2] <= 2,
                                "ForbiddenOrientation" + piece.ToIdentString() + "O" + orientation.ToString());
                            break;

                        case 8:
                            model.AddConstr(
                                _rotation[piece, 1, 2] + _rotation[piece, 2, 1] + _rotation[piece, 3, 3] <= 2,
                                "ForbiddenOrientation" + piece.ToIdentString() + "O" + orientation.ToString());
                            break;

                        case 10:
                            model.AddConstr(
                                _rotation[piece, 1, 3] + _rotation[piece, 2, 1] + _rotation[piece, 3, 2] <= 2,
                                "ForbiddenOrientation" + piece.ToIdentString() + "O" + orientation.ToString());
                            break;

                        case 16:
                            model.AddConstr(
                                _rotation[piece, 1, 2] + _rotation[piece, 2, 3] + _rotation[piece, 3, 1] <= 2,
                                "ForbiddenOrientation" + piece.ToIdentString() + "O" + orientation.ToString());
                            break;

                        case 18:
                            model.AddConstr(
                                _rotation[piece, 1, 3] + _rotation[piece, 2, 2] + _rotation[piece, 3, 1] <= 2,
                                "ForbiddenOrientation" + piece.ToIdentString() + "O" + orientation.ToString());
                            break;

                        default:
                            break;
                        }
                    }
                }
            }

            // Keep model up-to-date
            model.Update();

            // Output some model statistics
            Config.Log("Model statistics:" + Environment.NewLine);
            Config.Log("PieceIsInContainer: " + _pieceIsInContainer.Count + Environment.NewLine);
            Config.Log("ContainerUsed: " + _containerUsed.Count + Environment.NewLine);
            Config.Log("FrontLeftBottomX: " + _frontLeftBottomX.Count + Environment.NewLine);
            Config.Log("FrontLeftBottomY: " + _frontLeftBottomY.Count + Environment.NewLine);
            Config.Log("FrontLeftBottomZ: " + _frontLeftBottomZ.Count + Environment.NewLine);
            Config.Log("RearRightTopX: " + _rearRightTopX.Count + Environment.NewLine);
            Config.Log("RearRightTopY: " + _rearRightTopY.Count + Environment.NewLine);
            Config.Log("RearRightTopZ: " + _rearRightTopZ.Count + Environment.NewLine);
            Config.Log("Left: " + _left.Count + Environment.NewLine);
            Config.Log("Right: " + _right.Count + Environment.NewLine);
            Config.Log("Behind: " + _behind.Count + Environment.NewLine);
            Config.Log("Front: " + _front.Count + Environment.NewLine);
            Config.Log("Above: " + _above.Count + Environment.NewLine);
            Config.Log("Below: " + _below.Count + Environment.NewLine);
            Config.Log("Rotation: " + _rotation.Count + Environment.NewLine);
            Config.Log("BothInContainer: " + _bothInContainer.Count + Environment.NewLine);
            Config.Log("LocatedOn: " + _locatedOn.Count + Environment.NewLine);
            Config.Log("LocatedOnGround: " + _locatedOnGround.Count + Environment.NewLine);

            // Return
            return(model);
        }
Beispiel #16
0
    //Parse string into a linear model.
    public static LinearModel Parse(string model)
    {
        LinearModel Model = new LinearModel();

        string[] cleanedInput = CleanInput(model);

        var declarativeLine = cleanedInput[0];

        if (declarativeLine.StartsWith("MAXZ="))
        {
            Model.Objective = Objective.MAX;
        }
        else if (declarativeLine.StartsWith("MINZ="))
        {
            Model.Objective = Objective.MIN;
        }
        else
        {
            throw new InvalidInputException("Invalid or undeclared objective.", 0, cleanedInput);
        }

        var decMatches = VarRegex.Matches(declarativeLine);

        Dictionary <string, Variable> declaredVariables = new Dictionary <string, Variable>();

        foreach (Match match in decMatches)
        {
            try
            {
                var         name       = match.Groups[2].Value;
                var         valueMatch = match.Groups[1].Value;
                BigRational value;
                if (valueMatch == "-")
                {
                    value = -1;
                }
                else
                {
                    var hasValue = decimal.TryParse(valueMatch, out var decimalValue);
                    if (!hasValue)
                    {
                        value = 1;
                    }
                    else
                    {
                        value = decimalValue;
                    }
                }

                Variable var = Variable.Input(name);
                declaredVariables[name] = var;
                ValueVariable valVar = var.As(value);
                Model.Variables.Add(var);
                Model.ObjectiveFunction.Add(valVar);
            }
            catch (Exception e)
            {
                throw new InvalidInputException("Invalid variable declaration.", 0, cleanedInput, e);
            }
        }


        for (int i = 1; i < cleanedInput.Length; i++)
        {
            var constraintLine = cleanedInput[i];

            var variables = new List <ValueVariable>();
            var vars      = VarRegex.Matches(constraintLine);

            foreach (Match match in vars)
            {
                try
                {
                    var         name       = match.Groups[2].Value;
                    var         valueMatch = match.Groups[1].Value;
                    BigRational value;
                    if (valueMatch == "-")
                    {
                        value = -1;
                    }
                    else
                    {
                        var hasValue = decimal.TryParse(valueMatch, out var decimalValue);
                        if (!hasValue)
                        {
                            value = 1;
                        }
                        else
                        {
                            value = decimalValue;
                        }
                    }

                    if (declaredVariables.TryGetValue(name, out var variable))
                    {
                        variables.Add(variable.As(value));
                    }
                    else
                    {
                        throw new InvalidInputException($"Undeclared variable {name}", i, cleanedInput);
                    }
                }
                catch (Exception e)
                {
                    throw new InvalidInputException($"Invalid variable declaration.", i, cleanedInput, e);
                }
            }

            Constraint ct;
            try
            {
                var constraint           = ConstraintRegex.Match(constraintLine);
                var constraintSign       = constraint.Groups[1].Value;
                var constraintValueMatch = constraint.Groups[2].Value;
                var constraintValue      = decimal.Parse(constraintValueMatch);

                switch (constraintSign)
                {
                case ">=":
                    ct = Constraint.GreaterThanOrEqualTo($"CT{i}", constraintValue, variables);
                    break;

                case "<=":
                    ct = Constraint.LessThanOrEqualTo($"CT{i}", constraintValue, variables);
                    break;

                case "=":
                case "==":
                    ct = Constraint.EqualTo($"CT{i}", constraintValue, variables);
                    break;

                default:
                    throw new InvalidInputException("Invalid constraint value", i, cleanedInput);
                }
            }
            catch (Exception e)
            {
                throw new InvalidInputException("Invalid constraint declaration", i, cleanedInput, e);
            }
            Model.Constraints.Add(ct);
        }

        return(Model);
    }
Beispiel #17
0
        public IList <LinearFitResult> PerformLinearFit(QrFactorizationCache cache)
        {
            var linearModel = LinearModel.CreateModel(cache, DenseMatrix.OfColumnArrays(_matrixColumns), DenseMatrix.OfColumnArrays(_contrastValues), 1E-7);

            return(linearModel.Fit(DataSet.Abundances.ToArray()));
        }
Beispiel #18
0
        private static List <double[]> SolveWithLinearRegression(DataSet ds, DataSet dt, LinearModel model)
        {
            LLSGradientDescent gd = new LLSGradientDescent();

            //Calling the Train method of the trainer with the desired parameters
            //n, ds, learningRate: .3, numberOfEpochs: 200, shuffle: false, debug: n.Debug, nestrov:false, momentum:0.9, resilient: false, resilientUpdateAccelerationRate: 0.3,
            //resilientUpdateSlowDownRate: 0.1, regularization: AA1_MLP.Enums.Regularizations.L2, regularizationRate: 0.001, validationSet: dt, batchSize: 7


            LinearLeastSquaresParams passedParams = new LinearLeastSquaresParams {
                model = model
            };

            passedParams.trainingSet        = ds;
            passedParams.learningRate       = 1;
            passedParams.numOfIterations    = 3000;
            passedParams.shuffle            = false;
            passedParams.debug              = false;
            passedParams.regularizationRate = 0.01;
            passedParams.regularizationType = Regularizations.None;
            passedParams.validationSet      = dt;
            passedParams.degree             = 30;


            var learningCurve = gd.Train(passedParams);

            return(learningCurve);
        }
    //Build first SolverIteration from LinearModel
    public static SolverIteration BuildFirstIteration(LinearModel model)
    {
        var variables   = model.Variables.ToList();
        var constraints = model.Constraints.Select(c => c.Copy()).ToList();
        var objectives  = model.ObjectiveFunction
                          .Select(vv => vv.Coefficient).ToList();

        if (model.Objective == Objective.MIN)
        {
            objectives = objectives.Select(o => o * -1).ToList();
        }

        var inputGrid = new List <List <BigRational> >();

        int slackCount      = 0;
        int artificialCount = 0;

        foreach (var constraint in constraints)
        {
            if (constraint.ConstraintValue < 0)
            {
                switch (constraint.ConstraintType)
                {
                case ConstraintType.LessThanOrEqualTo:
                    constraint.ConstraintType = ConstraintType.GreaterThanOrEqualTo;
                    break;

                case ConstraintType.GreaterThanOrEqualTo:
                    constraint.ConstraintType = ConstraintType.LessThanOrEqualTo;
                    break;

                case ConstraintType.EqualTo:
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
                for (int i = 0; i < constraint.Variables.Count; i++)
                {
                    constraint.Variables[i].Coefficient *= -1;
                }

                constraint.ConstraintValue *= -1;
            }

            switch (constraint.ConstraintType)
            {
            case ConstraintType.LessThanOrEqualTo:
            {
                var slack = new Variable {
                    Name = $"S{++slackCount}", Type = VariableType.Slack
                };
                variables.Add(slack);
                objectives.Add(0);
                constraint.Variables.Add(new ValueVariable {
                        Variable = slack, Coefficient = 1
                    });
                break;
            }

            case ConstraintType.GreaterThanOrEqualTo:
            {
                var slack = new Variable {
                    Name = $"S{++slackCount}", Type = VariableType.Slack
                };
                var artificial = new Variable {
                    Name = $"A{++artificialCount}", Type = VariableType.Artificial
                };
                variables.Add(slack);
                objectives.Add(BigRational.Zero);
                variables.Add(artificial);
                objectives.Add(BigRational.Zero);
                constraint.Variables.Add(new ValueVariable {
                        Variable = slack, Coefficient = -1
                    });
                constraint.Variables.Add(new ValueVariable {
                        Variable = artificial, Coefficient = 1
                    });
                break;
            }

            case ConstraintType.EqualTo:
            {
                var artificial = new Variable {
                    Name = $"A{++artificialCount}", Type = VariableType.Artificial
                };
                variables.Add(artificial);
                objectives.Add(0);
                constraint.Variables.Add(new ValueVariable {
                        Variable = artificial, Coefficient = 1
                    });
                break;
            }

            default:
                throw new ArgumentOutOfRangeException();
            }
        }

        variables.Sort((v1, v2) => v1.Type - v2.Type);

        foreach (var constraint in constraints)
        {
            foreach (var missingVariable in variables.Except(constraint.Variables.Select(vv => vv.Variable)))
            {
                constraint.Variables.Add(missingVariable.As(0));
            }
        }

        foreach (var constraint in constraints)
        {
            constraint.Variables.Sort((vv1, vv2) =>
                                      variables.IndexOf(vv1.Variable) - variables.IndexOf(vv2.Variable));
        }

        inputGrid = constraints
                    .Select(c => c.Variables
                            .Select(v => v.Coefficient).ToList())
                    .ToList();

        var firstIteration = new SolverIteration
        {
            Variables          = variables.ToArray(),
            Z                  = BigRational.Zero,
            ObjectiveVariables = objectives.ToArray(),
            DecisionVariables  = objectives.Select(o => o * -1).ToArray(),
            BaseVariables      = constraints.Select(c => c.ConstraintValue).ToArray(),
            Bases              = variables.Skip(variables.Count - constraints.Count).ToArray(),
            InputGrid          = inputGrid.Select(r => r.ToArray()).ToArray()
        };

        return(firstIteration);
    }