/// <summary>
        /// Finds (dimension + 1) initial points.
        /// </summary>
        /// <param name="extremes"></param>
        /// <returns></returns>
        private List <int> FindInitialPoints()
        {
            var bigNumber = maxima.Sum() * NumOfDimensions * NumberOfVertices;
            // the first two points are taken from the dimension that had the fewest extremes
            // well, in most cases there will only be 2 in all dimensions: one min and one max
            // but a lot of engineering part shapes are nice and square and can have hundreds of
            // parallel vertices at the extremes
            var vertex1 = boundingBoxPoints[indexOfDimensionWithLeastExtremes].First(); // these are min and max vertices along
            var vertex2 = boundingBoxPoints[indexOfDimensionWithLeastExtremes].Last();  // the dimension that had the fewest points

            boundingBoxPoints[indexOfDimensionWithLeastExtremes].RemoveAt(0);
            boundingBoxPoints[indexOfDimensionWithLeastExtremes].RemoveAt(boundingBoxPoints[indexOfDimensionWithLeastExtremes].Count - 1);
            var initialPoints = new List <int> {
                vertex1, vertex2
            };

            VertexVisited[vertex1] = VertexVisited[vertex2] = true;
            CurrentVertex          = vertex1; UpdateCenter();
            CurrentVertex          = vertex2; UpdateCenter();
            var edgeVectors = new double[NumOfDimensions][];

            edgeVectors[0] = MathHelper.VectorBetweenVertices(vertex2, vertex1);
            // now the remaining vertices are just combined in one big list
            var extremes = boundingBoxPoints.SelectMany(x => x).ToList();
            // otherwise find the remaining points by maximizing the initial simplex volume
            var index = 1;

            while (index < NumOfDimensions && extremes.Any())
            {
                var bestVertex     = -1;
                var bestEdgeVector = new double[] { };
                var maxVolume      = 0.0;
                for (var i = extremes.Count - 1; i >= 0; i--)
                {
                    // count backwards in order to remove potential duplicates
                    var vIndex = extremes[i];
                    if (initialPoints.Contains(vIndex))
                    {
                        extremes.RemoveAt(i);
                    }
                    else
                    {
                        edgeVectors[index] = MathHelper.VectorBetweenVertices(vIndex, vertex1);
                        var volume = MathHelper.GetSimplexVolume(edgeVectors, index, bigNumber);
                        if (maxVolume < volume)
                        {
                            maxVolume      = volume;
                            bestVertex     = vIndex;
                            bestEdgeVector = edgeVectors[index];
                        }
                    }
                }
                extremes.Remove(bestVertex);
                if (bestVertex == -1)
                {
                    break;
                }
                initialPoints.Add(bestVertex);
                edgeVectors[index++] = bestEdgeVector;
                CurrentVertex        = bestVertex; UpdateCenter();
            }
            // hmm, there are not enough points on the bounding box to make a simplex. It is rare but entirely possibly.
            // As an extreme, the bounding box can be made in n dimensions from only 2 unique points. When we can't find
            // enough unique points, we start again with ALL the vertices. The following is a near replica of the code
            // above, but instead of extremes, we consider "allVertices".
            if (initialPoints.Count <= NumOfDimensions)
            {
                var allVertices = Enumerable.Range(0, NumberOfVertices).ToList();
                while (index < NumOfDimensions && allVertices.Any())
                {
                    var bestVertex     = -1;
                    var bestEdgeVector = new double[] { };
                    var maxVolume      = 0.0;
                    for (var i = allVertices.Count - 1; i >= 0; i--)
                    {
                        // count backwards in order to remove potential duplicates
                        var vIndex = allVertices[i];
                        if (initialPoints.Contains(vIndex))
                        {
                            allVertices.RemoveAt(i);
                        }
                        else
                        {
                            edgeVectors[index] = MathHelper.VectorBetweenVertices(vIndex, vertex1);
                            var volume = MathHelper.GetSimplexVolume(edgeVectors, index, bigNumber);
                            if (maxVolume < volume)
                            {
                                maxVolume      = volume;
                                bestVertex     = vIndex;
                                bestEdgeVector = edgeVectors[index];
                            }
                        }
                    }
                    allVertices.Remove(bestVertex);
                    if (bestVertex == -1)
                    {
                        break;
                    }
                    initialPoints.Add(bestVertex);
                    edgeVectors[index++] = bestEdgeVector;
                    CurrentVertex        = bestVertex; UpdateCenter();
                }
            }
            if (initialPoints.Count <= NumOfDimensions)
            {
                throw new ArgumentException("The input data is degenerate. It appears to exist in " + NumOfDimensions +
                                            " dimensions, but it is a " + (NumOfDimensions - 1) + " dimensional set (i.e. the point of collinear,"
                                            + " coplanar, or co-hyperplanar.)");
            }
            return(initialPoints);
        }
Пример #2
0
        private List <int> FindInitialPoints()
        {
            double bigNumber = maxima.Sum() * (double)NumOfDimensions * (double)NumberOfVertices;
            int    num       = boundingBoxPoints[indexOfDimensionWithLeastExtremes].First();
            int    num2      = boundingBoxPoints[indexOfDimensionWithLeastExtremes].Last();

            boundingBoxPoints[indexOfDimensionWithLeastExtremes].RemoveAt(0);
            boundingBoxPoints[indexOfDimensionWithLeastExtremes].RemoveAt(boundingBoxPoints[indexOfDimensionWithLeastExtremes].Count - 1);
            List <int> list = new List <int>();

            list.Add(num);
            list.Add(num2);
            List <int> list2 = list;

            VertexVisited[num] = (VertexVisited[num2] = true);
            CurrentVertex      = num;
            UpdateCenter();
            CurrentVertex = num2;
            UpdateCenter();
            double[][] array = new double[NumOfDimensions][];
            array[0] = mathHelper.VectorBetweenVertices(num2, num);
            List <int> list3 = boundingBoxPoints.SelectMany((List <int> x) => x).ToList();
            int        num3  = 1;

            while (num3 < NumOfDimensions)
            {
                if (!list3.Any())
                {
                    break;
                }
                int      num4   = -1;
                double[] array2 = new double[0];
                double   num5   = 0.0;
                for (int num6 = list3.Count - 1; num6 >= 0; num6--)
                {
                    int num7 = list3[num6];
                    if (list2.Contains(num7))
                    {
                        list3.RemoveAt(num6);
                    }
                    else
                    {
                        array[num3] = mathHelper.VectorBetweenVertices(num7, num);
                        double simplexVolume = mathHelper.GetSimplexVolume(array, num3, bigNumber);
                        if (num5 < simplexVolume)
                        {
                            num5   = simplexVolume;
                            num4   = num7;
                            array2 = array[num3];
                        }
                    }
                }
                list3.Remove(num4);
                if (num4 == -1)
                {
                    break;
                }
                list2.Add(num4);
                array[num3++] = array2;
                CurrentVertex = num4;
                UpdateCenter();
            }
            if (list2.Count <= NumOfDimensions)
            {
                List <int> list4 = Enumerable.Range(0, NumberOfVertices).ToList();
                while (num3 < NumOfDimensions)
                {
                    if (!list4.Any())
                    {
                        break;
                    }
                    int      num9   = -1;
                    double[] array3 = new double[0];
                    double   num10  = 0.0;
                    for (int num11 = list4.Count - 1; num11 >= 0; num11--)
                    {
                        int num12 = list4[num11];
                        if (list2.Contains(num12))
                        {
                            list4.RemoveAt(num11);
                        }
                        else
                        {
                            array[num3] = mathHelper.VectorBetweenVertices(num12, num);
                            double simplexVolume2 = mathHelper.GetSimplexVolume(array, num3, bigNumber);
                            if (num10 < simplexVolume2)
                            {
                                num10  = simplexVolume2;
                                num9   = num12;
                                array3 = array[num3];
                            }
                        }
                    }
                    list4.Remove(num9);
                    if (num9 == -1)
                    {
                        break;
                    }
                    list2.Add(num9);
                    array[num3++] = array3;
                    CurrentVertex = num9;
                    UpdateCenter();
                }
            }
            if (list2.Count <= NumOfDimensions && IsLifted)
            {
                List <int> list5 = Enumerable.Range(0, NumberOfVertices).ToList();
                while (num3 < NumOfDimensions)
                {
                    if (!list5.Any())
                    {
                        break;
                    }
                    int      num14  = -1;
                    double[] array4 = new double[0];
                    double   num15  = 0.0;
                    for (int num16 = list5.Count - 1; num16 >= 0; num16--)
                    {
                        int num17 = list5[num16];
                        if (list2.Contains(num17))
                        {
                            list5.RemoveAt(num16);
                        }
                        else
                        {
                            mathHelper.RandomOffsetToLift(num17);
                            array[num3] = mathHelper.VectorBetweenVertices(num17, num);
                            double simplexVolume3 = mathHelper.GetSimplexVolume(array, num3, bigNumber);
                            if (num15 < simplexVolume3)
                            {
                                num15  = simplexVolume3;
                                num14  = num17;
                                array4 = array[num3];
                            }
                        }
                    }
                    list5.Remove(num14);
                    if (num14 == -1)
                    {
                        break;
                    }
                    list2.Add(num14);
                    array[num3++] = array4;
                    CurrentVertex = num14;
                    UpdateCenter();
                }
            }
            if (list2.Count <= NumOfDimensions && IsLifted)
            {
                throw new ArgumentException("The input data is degenerate. It appears to exist in " + NumOfDimensions + " dimensions, but it is a " + (NumOfDimensions - 1) + " dimensional set (i.e. the point of collinear, coplanar, or co-hyperplanar.)");
            }
            return(list2);
        }