প্রদত্ত পরিমাণ বা গড় রয়েছে এমন একটি পরিসরে N এলোমেলো পূর্ণসংখ্যা উত্পন্ন করার কোনও কার্যকর উপায় আছে কি?


11

N এর পূর্ণসংখ্যার এমন একটি এলোমেলো সংমিশ্রণ তৈরি করার কোনও কার্যকর উপায় আছে যে way

  • প্রতিটি পূর্ণসংখ্যা ব্যবধানে থাকে [ min, max],
  • পূর্ণসংখ্যার একটি যোগফল থাকে sum,
  • পূর্ণসংখ্যাগুলি যে কোনও ক্রমে (উদাঃ, এলোমেলো ক্রম) হাজির হতে পারে এবং
  • সংমিশ্রণটি অন্যান্য সংযোজনগুলির সাথে মেলে এমন সমস্ত সংমিশ্রণের মধ্যে থেকে এলোমেলোভাবে নির্বাচন করা হয়?

এলোমেলো সংমিশ্রণের জন্য কি একই ধরণের অ্যালগরিদম আছে যেখানে পূর্ণসংখ্যাগুলি তাদের মান অনুসারে বাছাই করা ক্রমে হাজির হয় (কোনও ক্রমের পরিবর্তে)?

(ক গড় সঙ্গে একটি যথাযথ সমন্বয় নির্বাচন অফ mean, একটি বিশেষ যদি হয় তাহলে sum = N * mean। এই সমস্যার একটি অভিন্ন র্যান্ডম পার্টিশন উৎপাদিত সমতূল্য sum[n যে অংশ ব্যবধান প্রতিটি মধ্যে min, max] এবং কোনো আদেশ অথবা অনুসারে সাজানো ক্রমে প্রদর্শিত হয় তাদের মান হিসাবে, কেস হতে পারে।)

আমি সচেতন যে এলোমেলো ক্রমে উপস্থিত সংমিশ্রণের জন্য এই সমস্যাটি নিম্নলিখিত উপায়ে সমাধান করা যেতে পারে (এডিআইটি [এপ্রিল ২]]: অ্যালগোরিদম সংশোধিত)):

  1. যদি N * max < sumবা N * min > sum, কোন সমাধান নেই।

  2. যদি N * max == sum, একটি মাত্র সমাধান থাকে, যেখানে সমস্ত Nসংখ্যা সমান max। যদি N * min == sum, একটি মাত্র সমাধান থাকে, যেখানে সমস্ত Nসংখ্যা সমান min

  3. যোগফলের সাথে এন এলোমেলো অ-নেতিবাচক পূর্ণসংখ্যার উত্পাদন করতে স্মিথ এবং ট্রাম্বলে ("ইউনিট সিমপ্লেক্স থেকে স্যাম্পলিং", 2004) প্রদত্ত অ্যালগরিদম ব্যবহার করুনsum - N * min

  4. minএইভাবে উত্পন্ন প্রতিটি সংখ্যায় যুক্ত করুন ।

  5. যদি কোনও সংখ্যা এর চেয়ে বেশি হয় max, তবে পদক্ষেপ 3 এ যান।

তবে এই অ্যালগরিদমটি যদি maxখুব কম হয় তবে ধীর হয় sum। উদাহরণস্বরূপ, আমার পরীক্ষাগুলি অনুসারে (উপরে জড়িত বিশেষ মামলার বাস্তবায়ন সহ mean), অ্যালগরিদম গড়পড়তাভাবে প্রত্যাখ্যান করে—

  • প্রায় 1.6 নমুনা যদি N = 7, min = 3, max = 10, sum = 42, তবে
  • প্রায় 30.6 নমুনা যদি N = 20, min = 3, max = 10, sum = 120

উপরের প্রয়োজনীয়তাগুলি পূরণ করার সময়ও বৃহত্তর এনগুলির পক্ষে দক্ষ হওয়ার জন্য এই অ্যালগরিদমটি সংশোধন করার কোনও উপায় আছে?

সম্পাদনা করুন:

মন্তব্যে প্রস্তাবিত বিকল্প হিসাবে, বৈধ এলোমেলো সংমিশ্রণ উত্পাদন করার একটি কার্যকর উপায় (এটি সর্বশেষ প্রয়োজন ব্যতীত সমস্ত কিছুতেই সন্তুষ্ট হয়):

  1. হিসাব X, বৈধ সমাহারের সংখ্যা সম্ভব প্রদত্ত sum, minএবং max
  2. চয়ন করুন Y, এর মধ্যে একটি অভিন্ন র্যান্ডম পূর্ণসংখ্যা [0, X)
  3. ("আনআরঙ্ক") Yএকটি বৈধ সংমিশ্রণে রূপান্তর করুন ।

তবে, বৈধ সংমিশ্রণের সংখ্যা (বা ক্রমগতি) গণনা করার কোনও সূত্র আছে এবং কোনও পূর্ণসংখ্যাকে বৈধ সংমিশ্রণে রূপান্তর করার কোনও উপায় আছে কি? [সম্পাদনা (এপ্রিল 28): সংমিশ্রণের পরিবর্তে আদেশের জন্য একই]।

সম্পাদনা (27 এপ্রিল):

ডিভ্রয়ের অ-ইউনিফর্ম র‌্যান্ডম ভেরিয়েট জেনারেশন (1986) পড়ার পরে , আমি নিশ্চিত করতে পারি যে এটি একটি এলোমেলো পার্টিশন তৈরির সমস্যা is এছাড়াও, পৃষ্ঠা 661 এ ব্যায়াম 2 (বিশেষত E ই) এই প্রশ্নের সাথে সম্পর্কিত।

সম্পাদনা (এপ্রিল 28):

এটি যে অ্যালগরিদমটি দিয়েছিল তা অভিন্ন যেখানে জড়িত পূর্ণসংখ্যাগুলি এলোমেলো ক্রমে দেওয়া হয় , তাদের মান অনুসারে বাছাই করা আদেশের বিপরীতে । যেহেতু উভয় সমস্যাই সাধারণ আগ্রহের, তাই আমি উভয় সমস্যার একটি প্রমিত উত্তর পেতে এই প্রশ্নটি সংশোধন করেছি।

নিম্নলিখিত রুবি কোডটি অভিন্নতার সম্ভাব্য সমাধানগুলি যাচাই করতে ব্যবহার করা যেতে পারে (যেখানে algorithm(...)প্রার্থী অ্যালগরিদম রয়েছে):

combos={}
permus={}
mn=0
mx=6
sum=12
for x in mn..mx
  for y in mn..mx
    for z in mn..mx
      if x+y+z==sum
        permus[[x,y,z]]=0
      end
      if x+y+z==sum and x<=y and y<=z
        combos[[x,y,z]]=0
      end
    end
  end
end

3000.times {|x|
 f=algorithm(3,sum,mn,mx)
 combos[f.sort]+=1
 permus[f]+=1
}
p combos
p permus

সম্পাদনা (২৯ এপ্রিল): বর্তমান বাস্তবায়নের রুবি কোড পুনরায় যুক্ত করা হয়েছে।

নিম্নলিখিত কোড উদাহরণটি রুবিতে দেওয়া হয়েছে, তবে আমার প্রশ্নটি প্রোগ্রামিং ভাষার থেকে পৃথক:

def posintwithsum(n, total)
    raise if n <= 0 or total <=0
    ls = [0]
    ret = []
    while ls.length < n
      c = 1+rand(total-1)
      found = false
      for j in 1...ls.length
        if ls[j] == c
          found = true
          break
        end
      end
      if found == false;ls.push(c);end
    end
    ls.sort!
    ls.push(total)
    for i in 1...ls.length
       ret.push(ls[i] - ls[i - 1])
    end
    return ret
end

def integersWithSum(n, total)
 raise if n <= 0 or total <=0
 ret = posintwithsum(n, total + n)
 for i in 0...ret.length
    ret[i] = ret[i] - 1
 end
 return ret
end

# Generate 100 valid samples
mn=3
mx=10
sum=42
n=7
100.times {
 while true
    pp=integersWithSum(n,sum-n*mn).map{|x| x+mn }
    if !pp.find{|x| x>mx }
      p pp; break # Output the sample and break
    end
 end
}


আপনি আপনার তৃতীয় প্রয়োজনীয়তা স্পষ্ট করতে পারেন? আপনার সমস্ত সম্ভাব্য সংমিশ্রণের মধ্যে (ভুল গড়যুক্তগুলি সহ) বা সমস্ত বৈধ সংমিশ্রণের (যেমন সঠিক গড় সহ) এর মধ্যে আপনার কি অভিন্নতা দরকার ?
ব্যবহারকারী58697

সমস্ত বৈধ সংমিশ্রণ, যা, সমস্ত সংমিশ্রণ যা অন্যান্য প্রয়োজনীয়তা পূরণ করে।
পিটার ও।

[মিনিট, সর্বোচ্চ] -তে N পূর্ণসংখ্যার মধ্যে সীমাবদ্ধ রাশিগুলির পার্টিশনগুলি গণনা এবং আনঙ্কঙ্ক করার কোনও উপায় থাকলে, এলোমেলোভাবে এবং আনরঙ্কিং এ part পার্টিশনগুলির মধ্যে একটি নির্বাচন করে একটি অভিন্ন বন্টন উপস্থাপন করতে পারে এবং এটি কি আপনার বর্তমান পদ্ধতির চেয়ে আরও কার্যকর হবে? যোগফল এবং এন কত বড় হতে পারে?
ברקן

"যোগফলের অবিচ্ছেদ্য অংশ" বলতে কী বোঝায় তা আমি জানি না এবং এমন প্রমাণের সাথে আমি অবগত নই যে এটি করার ফলে এই প্রশ্নের অর্থের মধ্যে একটি অভিন্ন বিতরণ ঘটে। এই প্রশ্নের জন্য, উভয়ই sumএবং Nকার্যকরভাবে সীমাহীন (কারণের মধ্যে)। আমি একটি আধ্যাত্মিক উত্তর চাইছি কারণ অন্তর্নিহিত সমস্যাটি স্ট্যাক ওভারফ্লোতে জিজ্ঞাসা করা অনেকগুলি প্রশ্নাবলীতে পপ আপ হয়েছে যার মধ্যে এটি এবং এই একটিও রয়েছে । @ גלעדברקן
পিটার ও।

যদি আমরা তাদের প্রত্যেকটির একটি অর্ডারেমেন্টে প্রতিটি সম্ভাব্য সংমিশ্রণকে "র‌্যাঙ্ক" (বা সূচক) দিয়ে থাকি, "আনরঙ্কিং," এর সংমিশ্রণটি তৈরি করা হয়, এর র‌্যাঙ্ক (এবং অবশ্যই এন, মিনিট এবং সর্বোচ্চ) দেওয়া হয় given সমস্ত সম্ভাব্য সংমিশ্রণের মধ্যে এই জাতীয় পছন্দ কেন অভিন্ন বন্টনের সাথে মানাবে না?
5

উত্তর:


3

জাভাতে আমার সমাধানটি এখানে। এটি সম্পূর্ণরূপে কার্যক্ষম এবং এতে দুটি জেনারেটর রয়েছে: PermutationPartitionGeneratorঅরসেটেড পার্টিশনের CombinationPartitionGeneratorজন্য এবং সাজানো পার্টিশনের জন্য। আপনার জেনারেটর SmithTromblePartitionGeneratorতুলনা করার জন্য ক্লাসে প্রয়োগও করেছে। শ্রেণিটি SequentialEnumeratorঅনুমিত ক্রমে সমস্ত সম্ভাব্য পার্টিশন (প্যারামিটারের উপর নির্ভর করে সাজানো বা সাজানো) গণনা করে। আমি এই সমস্ত জেনারেটরের জন্য পুঙ্খানুপুঙ্খ পরীক্ষা (আপনার পরীক্ষার কেস সহ) যুক্ত করেছি। বাস্তবায়ন বেশিরভাগ অংশের জন্য স্ব-ব্যাখ্যাযোগ্য। আপনার যদি কোনও প্রশ্ন থাকে তবে আমি কয়েক দিনের মধ্যে তাদের উত্তর দেব।

import java.util.Random;
import java.util.function.Supplier;

public abstract class PartitionGenerator implements Supplier<int[]>{
    public static final Random rand = new Random();
    protected final int numberCount;
    protected final int min;
    protected final int range;
    protected final int sum; // shifted sum
    protected final boolean sorted;

    protected PartitionGenerator(int numberCount, int min, int max, int sum, boolean sorted) {
        if (numberCount <= 0)
            throw new IllegalArgumentException("Number count should be positive");
        this.numberCount = numberCount;
        this.min = min;
        range = max - min;
        if (range < 0)
            throw new IllegalArgumentException("min > max");
        sum -= numberCount * min;
        if (sum < 0)
            throw new IllegalArgumentException("Sum is too small");
        if (numberCount * range < sum)
            throw new IllegalArgumentException("Sum is too large");
        this.sum = sum;
        this.sorted = sorted;
    }

    // Whether this generator returns sorted arrays (i.e. combinations)
    public final boolean isSorted() {
        return sorted;
    }

    public interface GeneratorFactory {
        PartitionGenerator create(int numberCount, int min, int max, int sum);
    }
}

import java.math.BigInteger;

// Permutations with repetition (i.e. unsorted vectors) with given sum
public class PermutationPartitionGenerator extends PartitionGenerator {
    private final double[][] distributionTable;

    public PermutationPartitionGenerator(int numberCount, int min, int max, int sum) {
        super(numberCount, min, max, sum, false);
        distributionTable = calculateSolutionCountTable();
    }

    private double[][] calculateSolutionCountTable() {
        double[][] table = new double[numberCount + 1][sum + 1];
        BigInteger[] a = new BigInteger[sum + 1];
        BigInteger[] b = new BigInteger[sum + 1];
        for (int i = 1; i <= sum; i++)
            a[i] = BigInteger.ZERO;
        a[0] = BigInteger.ONE;
        table[0][0] = 1.0;
        for (int n = 1; n <= numberCount; n++) {
            double[] t = table[n];
            for (int s = 0; s <= sum; s++) {
                BigInteger z = BigInteger.ZERO;
                for (int i = Math.max(0, s - range); i <= s; i++)
                    z = z.add(a[i]);
                b[s] = z;
                t[s] = z.doubleValue();
            }
            // swap a and b
            BigInteger[] c = b;
            b = a;
            a = c;
        }
        return table;
    }

    @Override
    public int[] get() {
        int[] p = new int[numberCount];
        int s = sum; // current sum
        for (int i = numberCount - 1; i >= 0; i--) {
            double t = rand.nextDouble() * distributionTable[i + 1][s];
            double[] tableRow = distributionTable[i];
            int oldSum = s;
            // lowerBound is introduced only for safety, it shouldn't be crossed 
            int lowerBound = s - range;
            if (lowerBound < 0)
                lowerBound = 0;
            s++;
            do
                t -= tableRow[--s];
            // s can be equal to lowerBound here with t > 0 only due to imprecise subtraction
            while (t > 0 && s > lowerBound);
            p[i] = min + (oldSum - s);
        }
        assert s == 0;
        return p;
    }

    public static final GeneratorFactory factory = (numberCount, min, max,sum) ->
        new PermutationPartitionGenerator(numberCount, min, max, sum);
}

import java.math.BigInteger;

// Combinations with repetition (i.e. sorted vectors) with given sum 
public class CombinationPartitionGenerator extends PartitionGenerator {
    private final double[][][] distributionTable;

    public CombinationPartitionGenerator(int numberCount, int min, int max, int sum) {
        super(numberCount, min, max, sum, true);
        distributionTable = calculateSolutionCountTable();
    }

    private double[][][] calculateSolutionCountTable() {
        double[][][] table = new double[numberCount + 1][range + 1][sum + 1];
        BigInteger[][] a = new BigInteger[range + 1][sum + 1];
        BigInteger[][] b = new BigInteger[range + 1][sum + 1];
        double[][] t = table[0];
        for (int m = 0; m <= range; m++) {
            a[m][0] = BigInteger.ONE;
            t[m][0] = 1.0;
            for (int s = 1; s <= sum; s++) {
                a[m][s] = BigInteger.ZERO;
                t[m][s] = 0.0;
            }
        }
        for (int n = 1; n <= numberCount; n++) {
            t = table[n];
            for (int m = 0; m <= range; m++)
                for (int s = 0; s <= sum; s++) {
                    BigInteger z;
                    if (m == 0)
                        z = a[0][s];
                    else {
                        z = b[m - 1][s];
                        if (m <= s)
                            z = z.add(a[m][s - m]);
                    }
                    b[m][s] = z;
                    t[m][s] = z.doubleValue();
                }
            // swap a and b
            BigInteger[][] c = b;
            b = a;
            a = c;
        }
        return table;
    }

    @Override
    public int[] get() {
        int[] p = new int[numberCount];
        int m = range; // current max
        int s = sum; // current sum
        for (int i = numberCount - 1; i >= 0; i--) {
            double t = rand.nextDouble() * distributionTable[i + 1][m][s];
            double[][] tableCut = distributionTable[i];
            if (s < m)
                m = s;
            s -= m;
            while (true) {
                t -= tableCut[m][s];
                // m can be 0 here with t > 0 only due to imprecise subtraction
                if (t <= 0 || m == 0)
                    break;
                m--;
                s++;
            }
            p[i] = min + m;
        }
        assert s == 0;
        return p;
    }

    public static final GeneratorFactory factory = (numberCount, min, max, sum) ->
        new CombinationPartitionGenerator(numberCount, min, max, sum);
}

import java.util.*;

public class SmithTromblePartitionGenerator extends PartitionGenerator {
    public SmithTromblePartitionGenerator(int numberCount, int min, int max, int sum) {
        super(numberCount, min, max, sum, false);
    }

    @Override
    public int[] get() {
        List<Integer> ls = new ArrayList<>(numberCount + 1);
        int[] ret = new int[numberCount];
        int increasedSum = sum + numberCount;
        while (true) {
            ls.add(0);
            while (ls.size() < numberCount) {
                int c = 1 + rand.nextInt(increasedSum - 1);
                if (!ls.contains(c))
                    ls.add(c);
            }
            Collections.sort(ls);
            ls.add(increasedSum);
            boolean good = true;
            for (int i = 0; i < numberCount; i++) {
                int x = ls.get(i + 1) - ls.get(i) - 1;
                if (x > range) {
                    good = false;
                    break;
                }
                ret[i] = x;
            }
            if (good) {
                for (int i = 0; i < numberCount; i++)
                    ret[i] += min;
                return ret;
            }
            ls.clear();
        }
    }

    public static final GeneratorFactory factory = (numberCount, min, max, sum) ->
        new SmithTromblePartitionGenerator(numberCount, min, max, sum);
}

import java.util.Arrays;

// Enumerates all partitions with given parameters
public class SequentialEnumerator extends PartitionGenerator {
    private final int max;
    private final int[] p;
    private boolean finished;

    public SequentialEnumerator(int numberCount, int min, int max, int sum, boolean sorted) {
        super(numberCount, min, max, sum, sorted);
        this.max = max;
        p = new int[numberCount];
        startOver();
    }

    private void startOver() {
        finished = false;
        int unshiftedSum = sum + numberCount * min;
        fillMinimal(0, Math.max(min, unshiftedSum - (numberCount - 1) * max), unshiftedSum);
    }

    private void fillMinimal(int beginIndex, int minValue, int fillSum) {
        int fillRange = max - minValue;
        if (fillRange == 0)
            Arrays.fill(p, beginIndex, numberCount, max);
        else {
            int fillCount = numberCount - beginIndex;
            fillSum -= fillCount * minValue;
            int maxCount = fillSum / fillRange;
            int maxStartIndex = numberCount - maxCount;
            Arrays.fill(p, maxStartIndex, numberCount, max);
            fillSum -= maxCount * fillRange;
            Arrays.fill(p, beginIndex, maxStartIndex, minValue);
            if (fillSum != 0)
                p[maxStartIndex - 1] = minValue + fillSum;
        }
    }

    @Override
    public int[] get() { // returns null when there is no more partition, then starts over
        if (finished) {
            startOver();
            return null;
        }
        int[] pCopy = p.clone();
        if (numberCount > 1) {
            int i = numberCount;
            int s = p[--i];
            while (i > 0) {
                int x = p[--i];
                if (x == max) {
                    s += x;
                    continue;
                }
                x++;
                s--;
                int minRest = sorted ? x : min;
                if (s < minRest * (numberCount - i - 1)) {
                    s += x;
                    continue;
                }
                p[i++]++;
                fillMinimal(i, minRest, s);
                return pCopy;
            }
        }
        finished = true;
        return pCopy;
    }

    public static final GeneratorFactory permutationFactory = (numberCount, min, max, sum) ->
        new SequentialEnumerator(numberCount, min, max, sum, false);
    public static final GeneratorFactory combinationFactory = (numberCount, min, max, sum) ->
        new SequentialEnumerator(numberCount, min, max, sum, true);
}

import java.util.*;
import java.util.function.BiConsumer;
import PartitionGenerator.GeneratorFactory;

public class Test {
    private final int numberCount;
    private final int min;
    private final int max;
    private final int sum;
    private final int repeatCount;
    private final BiConsumer<PartitionGenerator, Test> procedure;

    public Test(int numberCount, int min, int max, int sum, int repeatCount,
            BiConsumer<PartitionGenerator, Test> procedure) {
        this.numberCount = numberCount;
        this.min = min;
        this.max = max;
        this.sum = sum;
        this.repeatCount = repeatCount;
        this.procedure = procedure;
    }

    @Override
    public String toString() {
        return String.format("=== %d numbers from [%d, %d] with sum %d, %d iterations ===",
                numberCount, min, max, sum, repeatCount);
    }

    private static class GeneratedVector {
        final int[] v;

        GeneratedVector(int[] vect) {
            v = vect;
        }

        @Override
        public int hashCode() {
            return Arrays.hashCode(v);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            return Arrays.equals(v, ((GeneratedVector)obj).v);
        }

        @Override
        public String toString() {
            return Arrays.toString(v);
        }
    }

    private static final Comparator<Map.Entry<GeneratedVector, Integer>> lexicographical = (e1, e2) -> {
        int[] v1 = e1.getKey().v;
        int[] v2 = e2.getKey().v;
        int len = v1.length;
        int d = len - v2.length;
        if (d != 0)
            return d;
        for (int i = 0; i < len; i++) {
            d = v1[i] - v2[i];
            if (d != 0)
                return d;
        }
        return 0;
    };

    private static final Comparator<Map.Entry<GeneratedVector, Integer>> byCount =
            Comparator.<Map.Entry<GeneratedVector, Integer>>comparingInt(Map.Entry::getValue)
            .thenComparing(lexicographical);

    public static int SHOW_MISSING_LIMIT = 10;

    private static void checkMissingPartitions(Map<GeneratedVector, Integer> map, PartitionGenerator reference) {
        int missingCount = 0;
        while (true) {
            int[] v = reference.get();
            if (v == null)
                break;
            GeneratedVector gv = new GeneratedVector(v);
            if (!map.containsKey(gv)) {
                if (missingCount == 0)
                    System.out.println(" Missing:");
                if (++missingCount > SHOW_MISSING_LIMIT) {
                    System.out.println("  . . .");
                    break;
                }
                System.out.println(gv);
            }
        }
    }

    public static final BiConsumer<PartitionGenerator, Test> distributionTest(boolean sortByCount) {
        return (PartitionGenerator gen, Test test) -> {
            System.out.print("\n" + getName(gen) + "\n\n");
            Map<GeneratedVector, Integer> combos = new HashMap<>();
            // There's no point of checking permus for sorted generators
            // because they are the same as combos for them
            Map<GeneratedVector, Integer> permus = gen.isSorted() ? null : new HashMap<>();
            for (int i = 0; i < test.repeatCount; i++) {
                int[] v = gen.get();
                if (v == null && gen instanceof SequentialEnumerator)
                    break;
                if (permus != null) {
                    permus.merge(new GeneratedVector(v), 1, Integer::sum);
                    v = v.clone();
                    Arrays.sort(v);
                }
                combos.merge(new GeneratedVector(v), 1, Integer::sum);
            }
            Set<Map.Entry<GeneratedVector, Integer>> sortedEntries = new TreeSet<>(
                    sortByCount ? byCount : lexicographical);
            System.out.println("Combos" + (gen.isSorted() ? ":" : " (don't have to be uniform):"));
            sortedEntries.addAll(combos.entrySet());
            for (Map.Entry<GeneratedVector, Integer> e : sortedEntries)
                System.out.println(e);
            checkMissingPartitions(combos, test.getGenerator(SequentialEnumerator.combinationFactory));
            if (permus != null) {
                System.out.println("\nPermus:");
                sortedEntries.clear();
                sortedEntries.addAll(permus.entrySet());
                for (Map.Entry<GeneratedVector, Integer> e : sortedEntries)
                    System.out.println(e);
                checkMissingPartitions(permus, test.getGenerator(SequentialEnumerator.permutationFactory));
            }
        };
    }

    public static final BiConsumer<PartitionGenerator, Test> correctnessTest =
        (PartitionGenerator gen, Test test) -> {
        String genName = getName(gen);
        for (int i = 0; i < test.repeatCount; i++) {
            int[] v = gen.get();
            if (v == null && gen instanceof SequentialEnumerator)
                v = gen.get();
            if (v.length != test.numberCount)
                throw new RuntimeException(genName + ": array of wrong length");
            int s = 0;
            if (gen.isSorted()) {
                if (v[0] < test.min || v[v.length - 1] > test.max)
                    throw new RuntimeException(genName + ": generated number is out of range");
                int prev = test.min;
                for (int x : v) {
                    if (x < prev)
                        throw new RuntimeException(genName + ": unsorted array");
                    s += x;
                    prev = x;
                }
            } else
                for (int x : v) {
                    if (x < test.min || x > test.max)
                        throw new RuntimeException(genName + ": generated number is out of range");
                    s += x;
                }
            if (s != test.sum)
                throw new RuntimeException(genName + ": wrong sum");
        }
        System.out.format("%30s :   correctness test passed%n", genName);
    };

    public static final BiConsumer<PartitionGenerator, Test> performanceTest =
        (PartitionGenerator gen, Test test) -> {
        long time = System.nanoTime();
        for (int i = 0; i < test.repeatCount; i++)
            gen.get();
        time = System.nanoTime() - time;
        System.out.format("%30s : %8.3f s %10.0f ns/test%n", getName(gen), time * 1e-9, time * 1.0 / test.repeatCount);
    };

    public PartitionGenerator getGenerator(GeneratorFactory factory) {
        return factory.create(numberCount, min, max, sum);
    }

    public static String getName(PartitionGenerator gen) {
        String name = gen.getClass().getSimpleName();
        if (gen instanceof SequentialEnumerator)
            return (gen.isSorted() ? "Sorted " : "Unsorted ") + name;
        else
            return name;
    }

    public static GeneratorFactory[] factories = { SmithTromblePartitionGenerator.factory,
            PermutationPartitionGenerator.factory, CombinationPartitionGenerator.factory,
            SequentialEnumerator.permutationFactory, SequentialEnumerator.combinationFactory };

    public static void main(String[] args) {
        Test[] tests = {
                            new Test(3, 0, 3, 5, 3_000, distributionTest(false)),
                            new Test(3, 0, 6, 12, 3_000, distributionTest(true)),
                            new Test(50, -10, 20, 70, 2_000, correctnessTest),
                            new Test(7, 3, 10, 42, 1_000_000, performanceTest),
                            new Test(20, 3, 10, 120, 100_000, performanceTest)
                       };
        for (Test t : tests) {
            System.out.println(t);
            for (GeneratorFactory factory : factories) {
                PartitionGenerator candidate = t.getGenerator(factory);
                t.procedure.accept(candidate, t);
            }
            System.out.println();
        }
    }
}

আপনি আইডিয়নে এটি চেষ্টা করতে পারেন ।


আপনার উত্তরের জন্য ধন্যবাদ; এটি ভালই কাজ করে. আমি এখানে আরেকটি উত্তরে ক্রমশক্তি জেনারেটরের বর্ণনা দিয়েছি; আপনার সহায়তায় আরও একটি প্রশ্নের উত্তর দিয়েছেন ; এবং শীঘ্রই এলোমেলো প্রজন্মের পদ্ধতিতে আমার নিবন্ধের জন্য পাইথন নমুনা কোডটিতে আপনার অ্যালগরিদম অন্তর্ভুক্ত করবে।
পিটার ও

শুধু পরিষ্কার হতে। এই অ্যালগরিদম নমুনার জন্য সমস্ত সম্ভাব্য পার্টিশন / রচনা তৈরির উপর নির্ভর করে ?
জোসেফ উড

@ জোসেফউড নং, এটি তাদের সমস্ত গণনার উপর নির্ভর করে । এটি জেনারেটর সূচনাতে কেবল একবারে করা হয় এবং এটি কার্যকর কারণ এটি গতিশীল প্রোগ্রামিং পদ্ধতির ব্যবহার করে।
জন ম্যাকক্লেইন

কিভাবে গতিশীল প্রোগ্রামিং একটি অভিন্ন র্যান্ডম এলোমেলোভাবে নির্বাচিত এন পূর্ণসংখ্যার মধ্যে 'সমষ্টি' বিভাগের বেছে সংশ্লিষ্ট সমস্যার সমাধান করতে পারে প্রতিস্থাপন সঙ্গে একটি তালিকা দেখুন (থেকে উদাহরণস্বরূপ ) অথবা প্রতিস্থাপন ছাড়া ( উদাহরণস্বরূপ ), বা কিভাবে যে সমস্যা অন্যথায় সমাধান করা যেতে পারে?
পিটার মন্ত্রণালয়

@PeterO। আমার অ্যালগরিদমের মতো একই পদ্ধতির মাধ্যমে আপনার সমস্ত সম্ভাব্য পার্টিশন গণনা করা দরকার তবে এবার আপনাকে যোগফল থেকে কেবলমাত্র অনুমোদিত নম্বরগুলি বিয়োগ করতে হবে । মন্তব্য করতে এটি অনেক দীর্ঘ, আপনি একটি পৃথক প্রশ্ন জিজ্ঞাসা করতে পারেন। আমি সন্দেহ করি যে কেউ একই পদ্ধতির মাধ্যমে চারটি বিভিন্ন সমস্যার সমাধান করতে পারে। মনে করুন যে আপনার কাছে বেছে নিতে আলাদা আলাদা পূর্ণসংখ্যার একটি তালিকা রয়েছে (এটি এই প্রশ্নের মধ্যে কেবল একটি ধারাবাহিক পরিসর)। তারপরে আপনি এই তালিকা থেকে সংখ্যার সমন্বয়ে প্রদত্ত দৈর্ঘ্যের এলোমেলো অ্যারে তৈরি করতে পারবেন যদি অ্যারেগুলি সাজানো / সাজানো না হয় এবং পুনরাবৃত্তিটি মঞ্জুর / অস্বীকার করতে হয়।
জন ম্যাকক্লেইন

1

জন ম্যাকক্লেনের পারমুটেশন পার্টিশনজেনেটর থেকে প্রাপ্ত আলগোরিদিম এই পৃষ্ঠার অন্য উত্তরে। এটির দুটি ধাপ রয়েছে, যথা একটি সেটআপ পর্ব এবং একটি নমুনা পর্ব, এবং যোগফলের সাথে n[ min, max] এ এলোমেলো সংখ্যা তৈরি করে sumযেখানে সংখ্যাগুলি এলোমেলো ক্রমে তালিকাভুক্ত করা হয়।

সেটআপ পর্ব: প্রথমে নিম্নলিখিত সূত্রগুলি ( t(y, x)যেখানে y[0, n] এবং x[0, sum - n * min] এ রয়েছে) ব্যবহার করে একটি সমাধান টেবিল তৈরি করা হয় :

  • t (0, j) = 1 যদি জ == 0; 0 অন্যথায়
  • t (i, j) = t (i-1, j) + t (i-1, j-1) + ... + t (i-1, j- (সর্বোচ্চ-মিনিট))

এখানে, টি (y, x) আপেক্ষিক সম্ভাবনা সঞ্চয় করে যে yসংখ্যার যোগফল (উপযুক্ত ব্যাপ্তিতে) সমান হবে x। এই সম্ভাবনাটি একই সাথে সমস্ত টি (y, x) এর সাথে সম্পর্কিত y

নমুনা পর্ব: এখানে আমরা nসংখ্যার একটি নমুনা তৈরি করি । প্রতিটি অবস্থানের জন্য সেট sকরুন sum - n * min, তারপরে iশুরু n - 1করে 0 এ পিছনে কাজ করা:

  • v[0, টি (i + 1, s)) এ এলোমেলো পূর্ণসংখ্যায় সেট করুন।
  • সেট rকরুন min
  • টি (i, গুলি) থেকে বিয়োগ করুন v
  • v0 বা ততোধিক অবধি অবশিষ্ট থেকে, টি (i, s-1) বিয়োগ vকরুন, 1 এ যোগ করুন rএবং 1 থেকে বিয়োগ করুন s
  • iনমুনায় অবস্থানে নম্বর সেট করা আছে r

সম্পাদনা করুন:

এটি প্রদর্শিত হয় যে উপরের অ্যালগরিদমের তুচ্ছ পরিবর্তনের সাথে সাথে প্রতিটি এলোমেলো সংখ্যা তাদের সবার জন্য একই সীমা ব্যবহার না করে পৃথক পরিসর ব্যবহার করা সম্ভব:

অবস্থানগুলিতে প্রতিটি এলোমেলো সংখ্যা। i[0, n) এর সর্বনিম্ন মান মিনিট (i) এবং সর্বাধিক মান সর্বাধিক (i) থাকে।

যাক adjsum= sum- (মান (i)।

সেটআপ পর্ব: প্রথমে নিম্নলিখিত সূত্রগুলি ( t(y, x)যেখানে y[0, n] এবং x[0, adjsum] এ রয়েছে) ব্যবহার করে একটি সমাধান টেবিল তৈরি করা হয় :

  • t (0, j) = 1 যদি জ == 0; 0 অন্যথায়
  • t (i, j) = t (i-1, j) + t (i-1, j-1) + ... + t (i-1, j- (সর্বোচ্চ (i-1) -মিন (i -1)) )

স্যাম্পলিংয়ের পর্বটি তখন পূর্বের ঠিক ঠিক সমান হয়, ব্যতীত আমরা সেট sকরে adjsum(পরিবর্তে sum - n * min) সেট করি rএবং মিনিট (i) (পরিবর্তে) তে সেট করি min


সম্পাদনা করুন:

জন ম্যাকক্লেনের সংমিশ্রণ পার্টিজিনেটরের জন্য, সেটআপ এবং স্যাম্পলিং পর্যায়গুলি নীচে রয়েছে।

সেটআপ পর্ব: প্রথমে একটি সমাধান টেবিল নিম্নলিখিত সূত্রগুলি ( t(z, y, x)যেখানে z[0, n] এ রয়েছে, y[0, max - min] এবং x[0, sum - n * min] এ রয়েছে) ব্যবহার করে তৈরি করা হয়েছে:

  • টি (0, জে, কে) = 1 যদি কে == 0; 0 অন্যথায়
  • টি (i, 0, কে) = টি (আমি - 1, 0, কে)
  • t (i, j, k) = t (i, j-1, k) + t (i - 1, j, k - j)

নমুনা পর্ব: এখানে আমরা nসংখ্যার একটি নমুনা তৈরি করি । সেট sথেকে sum - n * minএবং mrangeথেকে max - minপ্রতিটি পদের জন্য, তারপর i, দিয়ে শুরু n - 1এবং 0 থেকে পিছনের দিকে কাজ:

  • v[0, টি (i + 1, মরেঞ্জ, গুলি) -এর জন্য এলোমেলো পূর্ণসংখ্যা সেট করুন।
  • mrangeমিনিটে সেট করুন ( mrange, s)
  • mrangeথেকে বিয়োগ s
  • সেট rকরুন min + mrange
  • বিয়োগ T ( i, mrange, s) থেকে v
  • যদিও vদেহাবশেষ 0 বা তার অধিক, 1 যোগ করার জন্য s, বিয়োগ থেকে 1 rথেকে এবং 1 mrangeবিয়োগ T (, তারপর i, mrange, s) থেকে v
  • iনমুনায় অবস্থানে নম্বর সেট করা আছে r

0

আমি এটি পরীক্ষা করিনি, সুতরাং এটি আসলে কোনও উত্তর নয়, চেষ্টা করার মতো এমন কিছু যা কোনও মন্তব্যে ফিট করার জন্য খুব দীর্ঘ। একটি অ্যারে দিয়ে শুরু করুন যা প্রথম দুটি মানদণ্ড পূরণ করে এবং এটি খেলুন যাতে এটি এখনও প্রথম দুটি পূরণ করে তবে এটি অনেক বেশি এলোমেলো।

যদি গড়টি একটি পূর্ণসংখ্যা হয় তবে আপনার প্রাথমিক অ্যারে [4, 4, 4, ... 4] বা হতে পারে [3, 4, 5, 3, 4, 5, ... 5, 8, 0] বা কিছু সহজ। 4.5 এর গড় সময়ের জন্য, [4, 5, 4, 5, ... 4, 5] ব্যবহার করে দেখুন।

পরবর্তী সংখ্যার একটি যুগল বাছাই num1এবং num2অ্যারের মধ্যে। সম্ভবত প্রথম সংখ্যাটি যথাযথভাবে নেওয়া উচিত, যেমন ফিশার-ইয়েটস সাফাল, দ্বিতীয় নম্বরটি এলোমেলোভাবে নেওয়া উচিত। প্রথম সংখ্যাটি ক্রমে নেওয়া নিশ্চিত করে যে প্রতিটি সংখ্যা কমপক্ষে একবারে নির্বাচিত হয়েছে।

এখন গণনা max-num1এবং num2-min। যারা দুটি সংখ্যার থেকে দূরত্বের হয় maxএবং minসীমানা। limitদুটি দূরত্বের মধ্যে আরও ছোট সেট করুন । এটিই সর্বাধিক পরিবর্তন অনুমোদিত যা কোনও এক বা অন্য সংখ্যাকে অনুমোদিত সীমা ছাড়িয়ে রাখবে না। যদি limitশূন্য হয় তবে এই জুটিটি এড়িয়ে যান।

[1, limit] সীমাতে একটি এলোমেলো পূর্ণসংখ্যা চয়ন করুন : কল করুন change। আমি বাছাইযোগ্য পরিসীমা থেকে 0 বাদ দিয়েছি কারণ এর কোনও প্রভাব নেই। পরীক্ষার মাধ্যমে এটি অন্তর্ভুক্ত করে আপনি আরও ভাল এলোমেলোতা অর্জন করতে পারেন; আমি নিশ্চিত নই.

এখন সেট num1 <- num1 + changeএবং num2 <- num2 - change। এটি গড় মানকে প্রভাবিত করবে না এবং অ্যারের সমস্ত উপাদান এখনও প্রয়োজনীয় সীমানার মধ্যে রয়েছে।

আপনাকে কমপক্ষে একবারে পুরো অ্যারেটি চালাতে হবে। পর্যাপ্ত পরিমাণে এলোমেলোভাবে কিছু পাওয়ার জন্য যদি আপনার এটির আগে একবারে চালনার প্রয়োজন হয় তা পরীক্ষা করা উচিত।

ইটিএ: সিউডোকোড অন্তর্ভুক্ত করুন

// Set up the array.
resultAry <- new array size N
for (i <- 0 to N-1)
  // More complex initial setup schemes are possible here.
  resultAry[i] <- mean
rof

// Munge the array entries.
for (ix1 <- 0 to N-1)  // ix1 steps through the array in order.

  // Pick second entry different from first.
  repeat
    ix2 <- random(0, N-1)
  until (ix2 != ix1)

  // Calculate size of allowed change.
  hiLimit <- max - resultAry[ix1]
  loLimit <- resultAry[ix2] - min
  limit <- minimum(hiLimit, loLimit)
  if (limit == 0)
    // No change possible so skip.
    continue loop with next ix1
  fi

  // Change the two entries keeping same mean.
  change <- random(1, limit)  // Or (0, limit) possibly.
  resultAry[ix1] <- resultAry[ix1] + change
  resultAry[ix2] <- resultAry[ix2] - change

rof

// Check array has been sufficiently munged.
if (resultAry not random enough)
  munge the array again
fi

আমি এটি পরীক্ষা করে দেখেছি এবং দুর্ভাগ্যক্রমে, আপনার অ্যালগরিদম সমস্ত সমাধানগুলির অভিন্ন বিতরণ তৈরি করে না, আমি যতই পুনরাবৃত্তি করি না কেন।
পিটার ও।

আচ্ছা ভালো. এটি যেভাবেই চেষ্টা করার মতো ছিল। :(
রোজ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.