Beispiel #1
0
        /// <summary>
        /// Chooses an arbitrary ordering of the sequence [0, 1, ... <paramref name="n"/> - 1] using <paramref name="i"/> to choose.
        /// </summary>
        /// <param name="n">The number of elements to permute</param>
        /// <param name="i">The index of the permutation. If this is a nonnegative number less than
        /// Factorial(<paramref name="n"/>) and <paramref name="n"/> &lt;= 12, then the permutations are enumerated. In other words,
        /// each of the possible permutations will correspond to exactly one integer in [0..Factorial(n)). Outside
        /// of that range, the permutation will be chosen using the given integer as a random seed.</param>
        /// <returns>An array of indices between 0 and <paramref name="n"/> in a chosen order.</returns>
        public static int[] ChoosePermutation(int n, int i)
        {
            // for case of small numbers, use enumerated choice
            if (0 <= n && n <= 12 && 0 <= i && i < Combinatorics.Factorial(n))
            {
                return(ChoosePermutation_1(n, i));
            }

            if (n < 0)
            {
                throw new ArgumentException("NModel.Combinatorics.ChoosePermutation: Parameter may not be negative", "n");
            }

            // otherwise use i as a random seed
            int[]     result          = new int[n];
            Set <int> indicesToChoose = Set <int> .EmptySet;

            for (int k = 0; k < n; k += 1)
            {
                indicesToChoose = indicesToChoose.Add(k);
            }

            int choice = TypedHash <int> .ComputeHash(n, i);

            for (int l = 0; l < n; l += 1)
            {
                //^ assume indicesToChoose.Count > 0;
                int currentChoice = indicesToChoose.Choose(Math.Abs(choice) % indicesToChoose.Count);
                result[l]       = currentChoice;
                indicesToChoose = indicesToChoose.Remove(currentChoice);
                choice          = TypedHash <int> .ComputeHash(choice, l);
            }
            return(result);
        }
Beispiel #2
0
        /// <summary>        /// Chooses an arbitrary ordering of the sequence [0, 1, ... <paramref name="n"/> - 1] using <paramref name="i"/> to choose.
        /// </summary>
        /// <param name="n">The number of elements to permute</param>
        /// <param name="i">The index of the permutation. This should be a nonnegative number less than
        /// Factorial(<paramref name="n"/>).</param>
        /// <returns>An array of indices between 0 and <paramref name="n"/> in an arbitrary order.</returns>
        /// <exception cref="ArgumentException">Thrown if <paramref name="n"/>is out of range. The current
        /// implementation allows
        /// permutation of up to 16 elements.</exception>
        /// <exception cref="ArgumentException">Thorwn if <paramref name="i"/>is not a nonnegative integer
        /// less than Factorial(<paramref name="n"/>).</exception>
        static int[] ChoosePermutation_1(int n, int i)
        //^ requires 0 <= n && n <= 12 && 0 <= i && i < Combinatorics.Factorial(n);
        {
            // if (!(0 <= n && n <= 12)) throw new ArgumentException("ChoosePermutation: out of range. Must be between 0 and 16.");
            // if (!(0 <= i && i < Combinatorics.Factorial(n))) throw new ArgumentException("ChoosePermutation: out of range. Must be in [0, Combinatorics.Factorial(16)).");

            int[]     result          = new int[n];
            Set <int> indicesToChoose = Set <int> .EmptySet;

            for (int k = 0; k < n; k += 1)
            {
                indicesToChoose = indicesToChoose.Add(k);
            }

            int choice = i;

            for (int l = n - 1; l >= 0; l -= 1)
            {
                int f = Combinatorics.Factorial(l);
                int currentChoiceIndex = choice / f;
                int currentChoice      = indicesToChoose.Choose(currentChoiceIndex);
                result[l]       = currentChoice;
                indicesToChoose = indicesToChoose.Remove(currentChoice);
                choice          = choice % f;
            }
            return(result);
        }
Beispiel #3
0
        /// <summary>
        /// Chooses an arbitrary reordering of this sequence, using <paramref name="i"/> to provide choice, based
        /// on the ordering given by <see cref="Combinatorics.ChoosePermutation"/>.
        /// </summary>
        /// <param name="i">An arbitrary integer that will be used as a seed to select the permutation.</param>
        /// <returns>A sequence with the same elements as this sequence but in a potentially different order.</returns>
        public Sequence <T> ChoosePermutation(int i)
        {
            Sequence <T> s = this;

            int[]           arr         = Combinatorics.ChoosePermutation(s.Count, i);
            T[]             resultOrder = new T[s.Count];
            IEnumerator <T> se          = s.GetEnumerator();

            foreach (int j in arr)
            {
                //^ assume j <= 0 && j < resultOrder.Length;
                se.MoveNext();
                resultOrder[j] = se.Current;
            }
            return(new Sequence <T>(resultOrder));
        }