コード例 #1
0
ファイル: Ndsort.cs プロジェクト: KernelA/nds
        /// <summary>
        /// <paramref name="Indices"/> splits into three lists.
        /// </summary>
        /// <param name="SeqUniqObjs"> The sequence of the unique objectives. </param>
        /// <param name="Indices"> The indices of the <paramref name="SeqUniqObjs"/>. </param>
        /// <param name="SplitValue"> A value for the splitting. </param>
        /// <param name="IndexOfValue"> The index of the value in the objectives, for the split. </param>
        /// <param name="LessSplitValue">
        /// The indices, where the <paramref name="IndexOfValue"/> th value of the objectives is less
        /// than <paramref name="SplitValue"/>.
        /// </param>
        /// <param name="EqualSplitValue">
        /// The indices, where the <paramref name="IndexOfValue"/> th value of the objectives are
        /// equal to <paramref name="SplitValue"/>.
        /// </param>
        /// <param name="GreaterSplitValue">
        /// The indices, where the <paramref name="IndexOfValue"/> th value of the objectives is
        /// greater than <paramref name="SplitValue"/>.
        /// </param>
        private void SplitBy(IReadOnlyList <TObj>[] SeqUniqObjs, LinkedList <int> Indices, TObj SplitValue, int IndexOfValue,
                             out LinkedList <int> LessSplitValue, out LinkedList <int> EqualSplitValue, out LinkedList <int> GreaterSplitValue)
        {
            LessSplitValue = new LinkedList <int>();

            EqualSplitValue = new LinkedList <int>();

            GreaterSplitValue = new LinkedList <int>();


            ResComp resComp;

            foreach (int index in Indices)
            {
                resComp = ConverterResCmp.ConvertToResCmp(_objCmp(SeqUniqObjs[index][IndexOfValue], SplitValue));

                if (resComp == ResComp.LE)
                {
                    LessSplitValue.AddLast(index);
                }
                else if (resComp == ResComp.EQ)
                {
                    EqualSplitValue.AddLast(index);
                }
                else
                {
                    GreaterSplitValue.AddLast(index);
                }
            }
        }
コード例 #2
0
ファイル: Ndsort.cs プロジェクト: KernelA/nds
            /// <summary>
            /// <para>
            /// Compare <paramref name="LeftSeq"/> and <paramref name="RightSeq"/> in the
            /// lexicographical order.
            /// </para>
            /// <para>
            /// <paramref name="LeftSeq"/> is lexicographically less than
            /// <paramref name="RightSeq"/>, if and only if <paramref name="LeftSeq"/>[i] &lt;
            /// <paramref name="RightSeq"/>[i], for first i in {0,1,...,len(
            /// <paramref name="LeftSeq"/>)-1}, where <paramref name="LeftSeq"/>[i] != <paramref name="RightSeq"/>[i].
            /// </para>
            /// <para>
            /// <paramref name="LeftSeq"/> is equal to <paramref name="RightSeq"/>, if and only if
            /// <paramref name="LeftSeq"/>[i] == <paramref name="RightSeq"/>[i], for all i in
            /// {0,1,...,len( <paramref name="LeftSeq"/>)-1}.
            /// </para>
            /// <para>
            /// In other cases, <paramref name="LeftSeq"/> is lexicographically greater than <paramref name="RightSeq"/>.
            /// </para>
            /// </summary>
            /// <remarks>
            /// <para>
            /// <paramref name="LeftSeq"/> and <paramref name="RightSeq"/> must have the same lengths.
            /// </para>
            /// </remarks>
            /// <param name="LeftSeq"></param>
            /// <param name="RightSeq"></param>
            /// <returns>
            /// -1, if <paramref name="LeftSeq"/> is lexicographically less than <paramref name="RightSeq"/>.
            /// 0, if <paramref name="LeftSeq"/> is equal to <paramref name="RightSeq"/>,. 1, otherwise.
            /// </returns>
            /// <exception cref="ArgumentNullException">
            /// If <paramref name="LeftSeq"/> or <paramref name="RightSeq"/> is null.
            /// </exception>
            /// <exception cref="ArgumentException">
            /// <para>
            /// If <paramref name="LeftSeq"/> and <paramref name="RightSeq"/> have no the same length.
            /// </para>
            /// <para> If <paramref name="LeftSeq"/> and <paramref name="RightSeq"/> are empty. </para>
            /// </exception>
            public int Compare(IReadOnlyList <T> LeftSeq, IReadOnlyList <T> RightSeq)
            {
                if (LeftSeq == null)
                {
                    throw new ArgumentNullException(nameof(LeftSeq));
                }

                if (RightSeq == null)
                {
                    throw new ArgumentNullException(nameof(RightSeq));
                }

                if (LeftSeq.Count != RightSeq.Count)
                {
                    throw new ArgumentException($"{nameof(LeftSeq)} and {nameof(RightSeq)} must have the same length.");
                }
                else if (LeftSeq.Count == 0)
                {
                    throw new ArgumentException($"{nameof(LeftSeq)} and {nameof(RightSeq)} are empty.");
                }

                int res = 0;

                ResComp resComp;

                for (int i = 0; i < LeftSeq.Count; i++)
                {
                    resComp = ConverterResCmp.ConvertToResCmp(_cmp(LeftSeq[i], RightSeq[i]));

                    if (resComp == ResComp.LE)
                    {
                        res = -1;
                        break;
                    }
                    else if (resComp == ResComp.GR)
                    {
                        res = 1;
                        break;
                    }
                }

                return(res);
            }
コード例 #3
0
ファイル: Ndsort.cs プロジェクト: KernelA/nds
        /// <summary>
        /// Two-objective sorting. It attributes front's index to the lexicographically ordered
        /// elements in the <paramref name="SeqUniqObjs"/>, with the indices in the
        /// <paramref name="Indices"/>, based on the first two values of the objectives using a
        /// line-sweep algorithm.
        /// </summary>
        /// <param name="SeqUniqObjs"> The sequence of the unique objectives. </param>
        /// <param name="Fronts"> The values of the fronts. </param>
        /// <param name="Indices"> The indices of the <paramref name="SeqUniqObjs"/>. </param>
        private void SweepA(IReadOnlyList <TObj>[] SeqUniqObjs, int[] Fronts, LinkedList <int> Indices)
        {
            HashSet <int> initInd = new HashSet <int>();

            LinkedList <int> indicesWhereSecondValuesLessOrEqual = new LinkedList <int>();

            using (IEnumerator <int> listEnumer = Indices.GetEnumerator())
            {
                listEnumer.MoveNext();

                initInd.Add(listEnumer.Current);

                int index = 0, maxFront = -1;

                ResComp resComp;

                while (listEnumer.MoveNext())
                {
                    index = listEnumer.Current;

                    indicesWhereSecondValuesLessOrEqual.Clear();

                    foreach (int initIndex in initInd)
                    {
                        resComp = ConverterResCmp.ConvertToResCmp(_objCmp(SeqUniqObjs[initIndex][1], SeqUniqObjs[index][1]));

                        if (resComp == ResComp.LE || resComp == ResComp.EQ)
                        {
                            indicesWhereSecondValuesLessOrEqual.AddLast(initIndex);
                        }
                    }

                    if (indicesWhereSecondValuesLessOrEqual.Count != 0)
                    {
                        maxFront      = indicesWhereSecondValuesLessOrEqual.Max(idx => Fronts[idx]);
                        Fronts[index] = Math.Max(Fronts[index], maxFront + 1);
                    }

                    initInd.RemoveWhere(idx => Fronts[idx] == Fronts[index]);
                    initInd.Add(index);
                }
            }
        }
コード例 #4
0
ファイル: Ndsort.cs プロジェクト: KernelA/nds
        /// <summary>
        /// Two-objective sorting. It attributes front's index to elements in the
        /// <paramref name="SeqUniqObjs"/>, with the indices in the <paramref name="AssignIndices"/>,
        /// based on the first two values of the objectives, by comparing them to elements in the
        /// <paramref name="SeqUniqObjs"/>, with the indices in the <paramref name="CompIndices"/>,
        /// using a line-sweep algorithm.
        /// </summary>
        /// <param name="SeqUniqObjs"> The sequence of the unique objectives. </param>
        /// <param name="Fronts"> The values of the fronts. </param>
        /// <param name="CompIndices"> The indices for comparing. </param>
        /// <param name="AssignIndices"> The indices for assign front. </param>
        private void SweepB(IReadOnlyList <TObj>[] SeqUniqObjs, int[] Fronts, LinkedList <int> CompIndices, LinkedList <int> AssignIndices)
        {
            HashSet <int> initInd = new HashSet <int>();

            bool isMoveNext = true;

            int compIndex = 0, maxFront = -1;

            TObj[] rightObjs = new TObj[2];
            TObj[] leftObjs  = new TObj[2];

            ResComp resComp;

            LinkedList <int> listIndicesWithLessOrEqValue = new LinkedList <int>();

            using (IEnumerator <int> compListEnum = CompIndices.GetEnumerator())
            {
                isMoveNext = compListEnum.MoveNext();

                foreach (int assignIndex in AssignIndices)
                {
                    if (isMoveNext)
                    {
                        rightObjs[0] = SeqUniqObjs[assignIndex][0];
                        rightObjs[1] = SeqUniqObjs[assignIndex][1];
                    }

                    while (isMoveNext)
                    {
                        compIndex = compListEnum.Current;

                        leftObjs[0] = SeqUniqObjs[compIndex][0];
                        leftObjs[1] = SeqUniqObjs[compIndex][1];

                        resComp = ConverterResCmp.ConvertToResCmp(_lexCmp.Compare(leftObjs, rightObjs));

                        if (resComp == ResComp.LE || resComp == ResComp.EQ)
                        {
                            var indicesWithLessValueAndEqualFront = from index in initInd
                                                                    where Fronts[index] == Fronts[compIndex] && ConverterResCmp.ConvertToResCmp(_objCmp(SeqUniqObjs[index][1], SeqUniqObjs[compIndex][1])) == ResComp.LE
                                                                    select index;

                            if (indicesWithLessValueAndEqualFront.Count() == 0)
                            {
                                initInd.RemoveWhere(idx => Fronts[idx] == Fronts[compIndex]);
                                initInd.Add(compIndex);
                            }

                            isMoveNext = compListEnum.MoveNext();
                        }
                        else
                        {
                            break;
                        }
                    }

                    listIndicesWithLessOrEqValue.Clear();

                    var indicesWithLessOrEqValue = (from index in initInd
                                                    let locResComp = ConverterResCmp.ConvertToResCmp(_objCmp(SeqUniqObjs[index][1], SeqUniqObjs[assignIndex][1]))
                                                                     where locResComp == ResComp.EQ || locResComp == ResComp.LE
                                                                     select index);

                    foreach (int index in indicesWithLessOrEqValue)
                    {
                        listIndicesWithLessOrEqValue.AddLast(index);
                    }

                    if (listIndicesWithLessOrEqValue.Count != 0)
                    {
                        maxFront            = listIndicesWithLessOrEqValue.Max(idx => Fronts[idx]);
                        Fronts[assignIndex] = Math.Max(Fronts[assignIndex], maxFront + 1);
                    }
                }
            }
        }
コード例 #5
0
ファイル: Ndsort.cs プロジェクト: KernelA/nds
        /// <summary>
        /// Recursive procedure. It attributes a front's index to all elements in the
        /// <paramref name="SeqUniqObjs"/>, with the indices in the <paramref name="AssignIndices"/>,
        /// for the first for the first <paramref name="CountOfObjs"/> values of the objectives, by
        /// comparing them to elements in the <paramref name="SeqUniqObjs"/>, with the indices in the <paramref name="CompIndices"/>.
        /// </summary>
        /// <param name="SeqUniqObjs"> The sequence of the unique objectives. </param>
        /// <param name="Fronts"> The values of the fronts. </param>
        /// <param name="CompIndices"> The indices for comparing. </param>
        /// <param name="AssignIndices"> The indices for assign front. </param>
        /// <param name="CountOfObjs">
        /// The number of the values from the objectives, for the sorting.
        /// </param>
        private void NdHelperB(IReadOnlyList <TObj>[] SeqUniqObjs, int[] Fronts, LinkedList <int> CompIndices, LinkedList <int> AssignIndices, int CountOfObjs)
        {
            if (CompIndices.Count == 0 || AssignIndices.Count == 0)
            {
                return;
            }
            else if (CompIndices.Count == 1 || AssignIndices.Count == 1)
            {
                foreach (int assignIndex in AssignIndices)
                {
                    var hv = SeqUniqObjs[assignIndex].Take(CountOfObjs);

                    foreach (int compIndex in CompIndices)
                    {
                        var lv = SeqUniqObjs[compIndex].Take(CountOfObjs);

                        if (Stools.IsDominate(lv, hv, _objCmp) || lv.CmpSeqEqual(hv, _objCmp))
                        {
                            Fronts[assignIndex] = Math.Max(Fronts[assignIndex], Fronts[compIndex] + 1);
                        }
                    }
                }
            }
            else if (CountOfObjs == 2)
            {
                SweepB(SeqUniqObjs, Fronts, CompIndices, AssignIndices);
            }
            else
            {
                var uniqValuesObjFromCompIndices = (from index in CompIndices
                                                    select SeqUniqObjs[index][CountOfObjs - 1]).Distinct();
                var uniqValuesObjFromAssignIndices = (from index in AssignIndices
                                                      select SeqUniqObjs[index][CountOfObjs - 1]).Distinct();

                TObj minUniqValueObjFromCompIndices, maxUniqValueObjFromCompIndices;
                TObj minUniqValueObjFromAssignIndices, maxUniqValueObjFromAssignIndices;

                uniqValuesObjFromAssignIndices.MinMax(out minUniqValueObjFromAssignIndices, out maxUniqValueObjFromAssignIndices, _objCmp);
                uniqValuesObjFromCompIndices.MinMax(out minUniqValueObjFromCompIndices, out maxUniqValueObjFromCompIndices, _objCmp);

                ResComp resComp;

                resComp = ConverterResCmp.ConvertToResCmp(_objCmp(maxUniqValueObjFromCompIndices, minUniqValueObjFromAssignIndices));

                if (resComp == ResComp.LE || resComp == ResComp.EQ)
                {
                    NdHelperB(SeqUniqObjs, Fronts, CompIndices, AssignIndices, CountOfObjs - 1);
                }
                else
                {
                    resComp = ConverterResCmp.ConvertToResCmp(_objCmp(minUniqValueObjFromCompIndices, maxUniqValueObjFromAssignIndices));

                    if (resComp == ResComp.LE || resComp == ResComp.EQ)
                    {
                        TObj median = Stools.FindLowMedian(uniqValuesObjFromAssignIndices.Union(uniqValuesObjFromCompIndices).ToArray(), _objCmp);

                        LinkedList <int> lessMedian1, equalMedian1, greaterMedian1, lessMedian2, equalMedian2, greaterMedian2;

                        SplitBy(SeqUniqObjs, CompIndices, median, CountOfObjs - 1, out lessMedian1, out equalMedian1, out greaterMedian1);
                        SplitBy(SeqUniqObjs, AssignIndices, median, CountOfObjs - 1, out lessMedian2, out equalMedian2, out greaterMedian2);

                        LinkedList <int> lessAndEqualMedian1 = MergeLists(lessMedian1, equalMedian1);

                        NdHelperB(SeqUniqObjs, Fronts, lessMedian1, lessMedian2, CountOfObjs);
                        NdHelperB(SeqUniqObjs, Fronts, lessMedian1, equalMedian2, CountOfObjs - 1);
                        NdHelperB(SeqUniqObjs, Fronts, equalMedian1, equalMedian2, CountOfObjs - 1);
                        NdHelperB(SeqUniqObjs, Fronts, lessAndEqualMedian1, greaterMedian2, CountOfObjs - 1);
                        NdHelperB(SeqUniqObjs, Fronts, greaterMedian1, greaterMedian2, CountOfObjs);
                    }
                }
            }
        }