এক্স সম্পত্তি ছাড়াই সর্বোচ্চ স্কোরিং ম্যাট্রিক্স সন্ধান করুন


14

এই চ্যালেঞ্জটি আংশিকভাবে একটি অ্যালগরিদম চ্যালেঞ্জ, আংশিকভাবে একটি অপ্টিমাইজেশন চ্যালেঞ্জ এবং আংশিকভাবে কেবল একটি দ্রুততম কোড চ্যালেঞ্জ।

একটি চক্রীয় ম্যাট্রিক্স সম্পূর্ণরূপে তার প্রথম সারি দ্বারা নির্দিষ্ট করা হয়েছে r। অবশিষ্ট সারিগুলি rসারির সূচকের সমান অফসেট সহ সারিটির প্রতিটি চক্রীয় ক্রমশক্তি । আমরা চক্রীয় ম্যাট্রিকগুলিকে অনুমতি দেব যা বর্গক্ষেত্রের নয় যাতে তারা কেবল তাদের শেষ সারিগুলির কিছু অনুপস্থিত। তবে আমরা সবসময় ধরে নিই যে সারিগুলির সংখ্যা কলামের সংখ্যার চেয়ে বেশি নয়। উদাহরণস্বরূপ, নিম্নলিখিত 3 বাই 5 সাইক্লিক ম্যাট্রিক্সটি বিবেচনা করুন।

10111
11011
11101

আমরা বলি যে একটি ম্যাট্রিক্সের সম্পত্তি এক্স রয়েছে যদি এতে অ-অভিন্ন পরিচয় সূচকযুক্ত কলামগুলির দুটি খালি খালি সেট থাকে যা একই (ভেক্টর) যোগফল। দুটি কলামের ভেক্টর যোগফল দুটি কলামের কেবলমাত্র উপাদান-ভিত্তিক সংমিশ্রণ। এটি xউপাদানগুলির সমন্বয়ে দুটি কলামের যোগফল এবং এর মধ্যে প্রতিটি উপাদান রয়েছে এমন আরও একটি কলাম x

উপরের ম্যাট্রিক্সটি তুচ্ছভাবে X এবং এর প্রথম এবং শেষের কলামগুলি একই হিসাবে সম্পত্তি থাকে। পরিচয় ম্যাট্রিক্সে কখনই এক্স সম্পত্তি থাকে না।

যদি আমরা কেবল উপরের ম্যাট্রিক্সের শেষ কলামটি সরিয়ে ফেলি তবে আমরা এমন একটি উদাহরণ পাই যাতে প্রপার্টি এক্স নেই এবং 4/3 এর স্কোর দেয়।

1011
1101
1110

কাজটি

কাজটি হ'ল সর্বোচ্চ স্কোরিং সাইক্লিক ম্যাট্রিক্স সন্ধানের জন্য কোড লেখা যাঁর এন্ট্রিগুলি সমস্ত 0 বা 1 এবং যার সম্পত্তি এক্স নেই find

স্কোর

আপনার স্কোরটি আপনার সেরা স্কোরিং ম্যাট্রিক্সের সারিগুলির সংখ্যা দ্বারা বিভক্ত সংখ্যা কলামগুলি হবে।

টাইব্রেকার

দুটি উত্তরের যদি একই স্কোর থাকে তবে একটি জমা দেয় প্রথমে।

(অত্যন্ত) অসম্ভব ইভেন্টে যে কেউ সীমাহীন স্কোর পাওয়ার জন্য কোনও পদ্ধতি আবিষ্কার করে, এই জাতীয় সমাধানের প্রথম বৈধ প্রমাণ গ্রহণ করা হবে। এর চেয়েও বেশি সম্ভাবনাময় ইভেন্টে আপনি একটি সীমাবদ্ধ ম্যাট্রিক্সের অনুকূলতার প্রমাণ খুঁজে পেতে পারেন অবশ্যই আমি জয়ের পুরস্কারও দেব।

ইঙ্গিত

12/8 এর স্কোর পাওয়া খুব কঠিন নয়।

ভাষা ও গ্রন্থাগার

আপনি যে কোনও ভাষা নিখরচায় উপলব্ধ সংকলক / দোভাষী / ইত্যাদি ব্যবহার করতে পারেন। লিনাক্স এবং যে কোনও লাইব্রেরির জন্য লিনাক্সের জন্য নিখরচায় উপলব্ধ।

নেতৃস্থানীয় এন্ট্রি

  • পিটার টেলর (জাভা) দ্বারা 36/19
  • সাবপটিমাস প্রাইম (সি #) দ্বারা 32/17
  • 21/12 জাস্টহেল্ফ দ্বারা (পাইথন 2)

আহ, সম্পত্তি এক্স কলামগুলিতে রয়েছে, সারি নয়।
অপ্টিমাইজার

যেমনটি লেখা হয়েছে, 1 বাই 2 ম্যাট্রিক্সের 01 বৈশিষ্ট্য এক্স রয়েছে কারণ প্রথম কলামের সেটটিতে খালি সেটটির মতো একই ভেক্টর যোগফল রয়েছে। সম্ভবত আপনি কলামের অদম্য সেট বোঝাতে চেয়েছিলেন? আমি মনে করি এটি পরিষ্কার না করে যদিও এটি পরিবর্তন করা উচিত।
xnor

2
বিধিগুলির সহজতম পঠনটিতে এখনও 01সম্পত্তি X: রয়েছে (1) = (0) + (1)। আপনি যদি এটি বাদ দিতে চান তবে আপনার উচিত উচিত যে কলামের দুটি সেট অবশ্যই আলাদা হবে।
পিটার টেলর

1
এই প্রশ্নটি এই সমস্যাটির উপর অনেকটা অন্তর্দৃষ্টি দেবে (সম্পত্তিটি এক্স, যা এনপি-হার্ড, এটি দুর্ভাগ্যক্রমে চেক করা কতটা শক্ত) তার উপর ম্যাথওভারফ্লো.net
প্রশ্নগুলি /

3
বর্তমানে আমরা 2^mসম্পত্তিটি এক্স পরীক্ষা করার জন্য সমস্ত কলামের সংমিশ্রণকে জোর করে চাপিয়ে দিচ্ছি If আমরা যদি কোনওভাবে "মাঝখানে দেখা" স্কিমটি তৈরি করতে পারি ("সাবসেটের যোগফল দেখুন") সমস্যাটি সম্ভবত এটি হ্রাস করতে পারে m * 2^(m/2)...
কেনেটিএম

উত্তর:


11

16/9 20/11 22/12 28/15 30/16 32/17 34/18 36/19 (জাভা)

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

  • এটি স্পষ্ট যে আমরা কেবলমাত্র সার্কুল্যান্ট ম্যাট্রিক্স বিবেচনা করতে পারি যেখানে প্রথম সারিতে লিন্ডন শব্দটি রয়েছে : শব্দটি যদি অ-মৌলিক হয় তবে এর অবশ্যই সম্পত্তি X থাকতে হবে এবং অন্যথায় আমরা স্কোর বা সম্পত্তি এক্সকে প্রভাবিত না করে ঘোরতে পারি।
  • পর্যবেক্ষণ করা সংক্ষিপ্ত বিজয়ীদের তাত্পর্যের ভিত্তিতে, আমি এখন লিন্ডন শব্দের মধ্য দিয়ে 50% ঘনত্বের (অর্থাত্ একই সংখ্যার 0এবং একই 1) কাজ শুরু করে পুনরুক্ত করছি ; আমি স্থায়ী ঘনত্ব নেকলেস এবং লিন্ডন শব্দগুলির জন্য ধূসর কোডে বর্ণিত অ্যালগরিদমকে ধ্রুবক মোড়িত সময়ে সাওদা এবং উইলিয়ামস, তাত্ত্বিক কম্পিউটার বিজ্ঞান 502 (2013): 46-54 ব্যবহার করি।
  • একটি অভিজ্ঞতাগত পর্যবেক্ষণ হ'ল মানগুলি জোড়ায় ঘটে: প্রতিটি সর্বোত্তম লিন্ডন শব্দ যা আমি স্কোর পেয়েছি তার বিপরীত হিসাবে একই। সুতরাং আমি এই জাতীয় প্রতিটি জোড়ার অর্ধেক বিবেচনা করে দুটি গতি সম্পন্ন করার একটি ফ্যাক্টর পেতে পারি।
  • আমার আসল কোডটি BigIntegerসঠিক পরীক্ষা দেওয়ার জন্য কাজ করেছিল । একটি বড় প্রাইম মডিউল পরিচালনা করে এবং সবকিছুকে আদিমতায় রেখে, আমি মিথ্যা নেতিবাচক ঝুঁকিতে একটি উল্লেখযোগ্য গতির উন্নতি পেয়েছি। আমি যে প্রাইমটি বেছে নিয়েছি তা হ'ল 2 57 এর চেয়ে কম ছোট , কারণ এটি আমার ধারণাটি ভেক্টর উপস্থাপনের ভিত্তিকে উপচে পড়া ছাড়াই গুণ করে।
  • আমি সাবোপটিমাস প্রাইম এর তাত্পর্যপূর্ণ চুরি করেছি যে আকারের ক্রমবর্ধমান সাবটেক্টগুলি বিবেচনা করে দ্রুত প্রত্যাখ্যান করা সম্ভব। সংঘাতের সাবসেটগুলির জন্য পরীক্ষার জন্য মধ্যবর্তী পদ্ধতির মধ্যবর্তী পদ্ধতির সাথে আমি এখন এই ধারণাটি একীভূত করেছি। ( পূর্ণসংক্রান্ত সাবসেট সমস্যা থেকে পদ্ধতির সাথে খাপ খাইয়ে দেওয়ার পরামর্শ দেওয়ার জন্য কেনিটিএমকে কৃতিত্ব ; আমি মনে করি যে xnor এবং আমি একসাথে এটি করার উপায়টি দেখেছি)। প্রতিটি কলামে 0 বা 1 বার অন্তর্ভুক্ত থাকতে পারে এবং একই সমষ্টি হতে পারে এমন দুটি সাবসেটের সন্ধানের পরিবর্তে আমরা এমন একটি উপসেট খুঁজছি যা প্রতিটি কলাম -1, 0, বা 1 বার এবং শূন্যের যোগ করতে পারে। এটি স্মৃতিশক্তির প্রয়োজনীয়তা উল্লেখযোগ্যভাবে হ্রাস করে।
  • মেমোরির প্রয়োজনীয়তাগুলিতে দু'টি সঞ্চয় করার অতিরিক্ত কারণ রয়েছে যা পর্যবেক্ষণ করে যে প্রতিটি উপাদানটির {-1,0,1}^mতত্পরতা রয়েছে তবে {-1,0,1}^mএটি কেবল দুটির মধ্যে একটি সংরক্ষণের প্রয়োজন।
  • আমি কাস্টম হ্যাশম্যাপ বাস্তবায়ন ব্যবহার করে মেমরির প্রয়োজনীয়তা এবং কার্য সম্পাদনও উন্নত করি। ৩//১৯ পরীক্ষার জন্য 3 ms 18 টি পরিমাণ জমা করতে হবে এবং 3 ^ 18 ল্যাংগুলি কোনও ওভারহেড ছাড়াই প্রায় 3 জিবি - আমি এটিকে 6 গিগাবাইট দিয়েছি কারণ 4 জিবি যথেষ্ট ছিল না; 8 গিগাবাইট র‌্যামের মধ্যে আর কোনও পরীক্ষা (যথা পরীক্ষা 38/20) করার জন্য দীর্ঘস্থায়ী না হয়ে ইনটগুলি সংরক্ষণ করার জন্য আরও অনুকূলকরণের প্রয়োজন হবে। কোন 20 টি বিট বলতে হবে যা সাবসেটটি যোগফল তৈরি করে যা 12 বিট প্লাস বালতি থেকে অন্তর্নিহিত বিট ছেড়ে দেয়; আমি আশঙ্কা করি যে কোনও হিট পাওয়ার জন্য অনেকগুলি মিথ্যা সংঘর্ষ হবে।
  • যেহেতু প্রমাণের ওজন আমাদের পরামর্শ দেওয়া উচিত 2n/(n+1), তাই আমি কেবল এটি পরীক্ষা করে জিনিসগুলিকে দ্রুত করছি।
  • কিছু অপ্রয়োজনীয় কিন্তু আশ্বাসজনক পরিসংখ্যান আউটপুট রয়েছে।
import java.util.*;

// Aiming to find a solution for (2n, n+1).
public class PPCG41021_QRTernary_FixedDensity {
    private static final int N = 36;
    private static int density;
    private static long start;
    private static long nextProgressReport;

    public static void main(String[] args) {
        start = System.nanoTime();
        nextProgressReport = start + 5 * 60 * 1000000000L;

        // 0, -1, 1, -2, 2, ...
        for (int i = 0; i < N - 1; i++) {
            int off = i >> 1;
            if ((i & 1) == 1) off = ~off;
            density = (N >> 1) + off;

            // Iterate over Lyndon words of length N and given density.
            for (int j = 0; j < N; j++) a[j] = j < N - density ? '0' : '1';
            c = 1;
            Bs[1] = N - density;
            Bt[1] = density;
            gen(N - density, density, 1);
            System.out.println("----");
        }

        System.out.println("Finished in " + (System.nanoTime() - start)/1000000 + " ms");
    }

    private static int c;
    private static int[] Bs = new int[N + 1], Bt = new int[N + 1];
    private static char[] a = new char[N];
    private static void gen(int s, int t, int r) {
        if (s > 0 && t > 0) {
            int j = oracle(s, t, r);
            for (int i = t - 1; i >= j; i--) {
                updateBlock(s, t, i);
                char tmp = a[s - 1]; a[s - 1] = a[s+t-i - 1]; a[s+t-i - 1] = tmp;
                gen(s-1, t-i, testSuffix(r) ? c-1 : r);
                tmp = a[s - 1]; a[s - 1] = a[s+t-i - 1]; a[s+t-i - 1] = tmp;
                restoreBlock(s, t, i);
            }
        }
        visit();
    }

    private static int oracle(int s, int t, int r) {
        int j = pseudoOracle(s, t, r);
        updateBlock(s, t, j);
        int p = testNecklace(testSuffix(r) ? c - 1 : r);
        restoreBlock(s, t, j);
        return p == N ? j : j + 1;
    }

    private static int pseudoOracle(int s, int t, int r) {
        if (s == 1) return t;
        if (c == 1) return s == 2 ? N / 2 : 1;
        if (s - 1 > Bs[r] + 1) return 0;
        if (s - 1 == Bs[r] + 1) return cmpPair(s-1, t, Bs[c-1]+1, Bt[c-1]) <= 0 ? 0 : 1;
        if (s - 1 == Bs[r]) {
            if (s == 2) return Math.max(t - Bt[r], (t+1) >> 1);
            return Math.max(t - Bt[r], (cmpPair(s-1, t, Bs[c-1] + 1, Bt[c-1]) <= 0) ? 0 : 1); 
        }
        if (s == Bs[r]) return t;
        throw new UnsupportedOperationException("Hit the case not covered by the paper or its accompanying code");
    }

    private static int testNecklace(int r) {
        if (density == 0 || density == N) return 1;
        int p = 0;
        for (int i = 0; i < c; i++) {
            if (r - i <= 0) r += c;
            if (cmpBlocks(c-i, r-i) < 0) return 0;
            if (cmpBlocks(c-i, r-1) > 0) return N;
            if (r < c) p += Bs[r-i] + Bt[r-i];
        }
        return p;
    }

    private static int cmpPair(int a1, int a2, int b1, int b2) {
        if (a1 < b1) return -1;
        if (a1 > b1) return 1;
        if (a2 < b2) return -1;
        if (a2 > b2) return 1;
        return 0;
    }

    private static int cmpBlocks(int i, int j) {
        return cmpPair(Bs[i], Bt[i], Bs[j], Bt[j]);
    }

    private static boolean testSuffix(int r) {
        for (int i = 0; i < r; i++) {
            if (c - 1 - i == r) return true;
            if (cmpBlocks(c-1-i, r-i) < 0) return false;
            if (cmpBlocks(c-1-i, r-1) > 0) return true;
        }
        return false;
    }

    private static void updateBlock(int s, int t, int i) {
        if (i == 0 && c > 1) {
            Bs[c-1]++;
            Bs[c] = s - 1;
        }
        else {
            Bs[c] = 1;
            Bt[c] = i;
            Bs[c+1] = s-1;
            Bt[c+1] = t-i;
            c++;
        }
    }

    private static void restoreBlock(int s, int t, int i) {
        if (i == 0 && (c > 0 || (Bs[1] != 1 || Bt[1] != 0))) {
            Bs[c-1]--;
            Bs[c] = s;
        }
        else {
            Bs[c-1] = s;
            Bt[c-1] = t;
            c--;
        }
    }

    private static long[] stats = new long[N/2+1];
    private static long visited = 0;
    private static void visit() {
        String word = new String(a);

        visited++;
        if (precedesReversal(word) && testTernary(word)) System.out.println(word + " after " + (System.nanoTime() - start)/1000000 + " ms");
        if (System.nanoTime() > nextProgressReport) {
            System.out.println("Progress: visited " + visited + "; stats " + Arrays.toString(stats) + " after " + (System.nanoTime() - start)/1000000 + " ms");
             nextProgressReport += 5 * 60 * 1000000000L;
        }
    }

    private static boolean precedesReversal(String w) {
        int n = w.length();
        StringBuilder rev = new StringBuilder(w);
        rev.reverse();
        rev.append(rev, 0, n);
        for (int i = 0; i < n; i++) {
            if (rev.substring(i, i + n).compareTo(w) < 0) return false;
        }
        return true;
    }

    private static boolean testTernary(String word) {
        int n = word.length();
        String rep = word + word;

        int base = 1;
        for (char ch : word.toCharArray()) base += ch & 1;

        // Operating base b for b up to 32 implies that we can multiply by b modulo p<2^57 without overflowing a long.
        // We're storing 3^(n/2) ~= 2^(0.8*n) sums, so while n < 35.6 we don't get *too* bad a probability of false reject.
        // (In fact the birthday paradox assumes independence, and our values aren't independent, so we're better off than that).
        long p = (1L << 57) - 13;
        long[] basis = new long[n];
        basis[0] = 1;
        for (int i = 1; i < basis.length; i++) basis[i] = (basis[i-1] * base) % p;

        int rows = n / 2 + 1;
        long[] colVals = new long[n];
        for (int col = 0; col < n; col++) {
            for (int row = 0; row < rows; row++) {
                colVals[col] = (colVals[col] + basis[row] * (rep.charAt(row + col) & 1)) % p;
            }
        }

        MapInt57Int27 map = new MapInt57Int27();
        // Special-case the initial insertion.
        int[] oldLens = new int[map.entries.length];
        int[] oldSupercounts = new int[1 << 10];
        {
            // count = 1
            for (int k = 0; k < n/2; k++) {
                int val = 1 << (25 - k);
                if (!map.put(colVals[k], val)) { stats[1]++; return false; }
                if (!map.put(colVals[k + n/2], val + (1 << 26))) { stats[1]++; return false; }
            }
        }
        final long keyMask = (1L << 37) - 1;
        for (int count = 2; count <= n/2; count++) {
            int[] lens = map.counts.clone();
            int[] supercounts = map.supercounts.clone();
            for (int sup = 0; sup < 1 << 10; sup++) {
                int unaccountedFor = supercounts[sup] - oldSupercounts[sup];
                for (int supi = 0; supi < 1 << 10 && unaccountedFor > 0; supi++) {
                    int i = (sup << 10) + supi;
                    int stop = lens[i];
                    unaccountedFor -= stop - oldLens[i];
                    for (int j = oldLens[i]; j < stop; j++) {
                        long existingKV = map.entries[i][j];
                        long existingKey = ((existingKV & keyMask) << 20) + i;
                        int existingVal = (int)(existingKV >>> 37);

                        // For each possible prepend...
                        int half = (existingVal >> 26) * n/2;
                        // We have 27 bits of key, of which the top marks the half, so 26 bits. That means there are 6 bits at the top which we need to not count.
                        int k = Integer.numberOfLeadingZeros(existingVal << 6) - 1;
                        while (k >= 0) {
                            int newVal = existingVal | (1 << (25 - k));
                            long pos = (existingKey + colVals[k + half]) % p;
                            if (pos << 1 > p) pos = p - pos;
                            if (pos == 0 || !map.put(pos, newVal)) { stats[count]++; return false; }
                            long neg = (p - existingKey + colVals[k + half]) % p;
                            if (neg << 1 > p) neg = p - neg;
                            if (neg == 0 || !map.put(neg, newVal)) { stats[count]++; return false; }
                            k--;
                        }
                    }
                }
            }
            oldLens = lens;
            oldSupercounts = supercounts;
        }

        stats[n/2]++;
        return true;
    }

    static class MapInt57Int27 {
        private long[][] entries;
        private int[] counts;
        private int[] supercounts;

        public MapInt57Int27() {
            entries = new long[1 << 20][];
            counts = new int[1 << 20];
            supercounts = new int[1 << 10];
        }

        public boolean put(long key, int val) {
            int bucket = (int)(key & (entries.length - 1));
            long insert = (key >>> 20) | (((long)val) << 37);
            final long mask = (1L << 37) - 1;

            long[] chain = entries[bucket];
            if (chain == null) {
                chain = new long[16];
                entries[bucket] = chain;
                chain[0] = insert;
                counts[bucket]++;
                supercounts[bucket >> 10]++;
                return true;
            }

            int stop = counts[bucket];
            for (int i = 0; i < stop; i++) {
                if ((chain[i] & mask) == (insert & mask)) {
                    return false;
                }
            }

            if (stop == chain.length) {
                long[] newChain = new long[chain.length < 512 ? chain.length << 1 : chain.length + 512];
                System.arraycopy(chain, 0, newChain, 0, chain.length);
                entries[bucket] = newChain;
                chain = newChain;
            }
            chain[stop] = insert;
            counts[bucket]++;
            supercounts[bucket >> 10]++;
            return true;
        }
    }
}

প্রথম পাওয়া গেছে

000001001010110001000101001111111111

এবং 15 ঘন্টার মধ্যে এটিই হিট।

ছোট বিজয়ীরা:

4/3:    0111                       (plus 8 different 8/6)
9/6:    001001011                  (and 5 others)
11/7:   00010100111                (and 3 others)
13/8:   0001001101011              (and 5 others)
15/9:   000010110110111            (and 21 others)
16/9:   0000101110111011           (and 1 other)
20/11:  00000101111011110111       (and others)
22/12:  0000001100110011101011     (and others)
24/13:  000000101011101011101011   (and others)
26/14:  00000001101110010011010111 (and others)
28/15:  0000000010000111100111010111 (and others)
30/16:  000000001011001110011010101111 (and probably others)
32/17:  00001100010010100100101011111111 (and others)
34/18:  0000101000100101000110010111111111 (and others)

এটি একটি ভাল উন্নতি। মনে হচ্ছে লিন্ডন শব্দ ব্যবহার করার অর্থ আপনার কেবল প্রথম সারির জন্য 2 ^ n এর পরিবর্তে প্রায় 2 ^ n / n বাইনারি স্ট্রিংগুলি পরীক্ষা করতে হবে check

আপনি যখন বিগইন্টিজারের প্রতিটি অঙ্ককে ম্যাট্রিক্স সেল হিসাবে ব্যবহার করছেন, তখন এন> 10 থাকলে কি ভুল উত্তর হবে না?
কেনেটিএম

@ কেনেনিটিএম, নোট করুন যে দ্বিতীয় প্যারামিটারটি মূলত। একটি ছোট ত্রুটি রয়েছে: আমার nপরিবর্তে আমার ব্যবহার করা উচিত rows, যদিও এটি ব্যর্থ-নিরাপদ এই অর্থে যে এটি অবৈধগুলি গ্রহণ করার পরিবর্তে বৈধ সমাধানগুলি বাতিল করবে। এটি ফলাফলগুলিকেও প্রভাবিত করে না।
পিটার টেলর

1
আমি মনে করি আমরা ব্যবহারিকভাবে এই স্কোরের মধ্যেই সীমাবদ্ধ, যেহেতু সম্পত্তি এক্স চেক করা খুব সময়সাপেক্ষ, যদি না আমরা অন্য সমমানের শর্তটি খুঁজে পাই যা দ্রুত মূল্যায়ন করা যায়। এজন্য আমি এতটাই আগ্রহী ছিলাম যে "নন-প্রাইম" দ্বারা সম্পত্তি X = D বোঝায়
justhalf

1
@ সুপোটিমাসপ্রাইম, আমি এটি people.math.sfu.ca/~kya17/teaching/math343/16-343.pdfপেয়েছি এবং একটি বাগ স্থির করেছি। মজার বিষয় হল আমি এখন লিন্ডন শব্দের মাধ্যমে পুনরাবৃত্তি করতে যাচ্ছি তা সম্পর্কিত অ্যালগরিদমের একটি শ্রেণি যা কে-অফ-এন সাবসেটগুলিও করে, তাই আমি কিছু সংশোধনকারী এবং ভাগ করতে সক্ষম হতে পারি।
পিটার টেলর

9

পাইথন 2 - 21/12

এটি প্রমাণ করার প্রক্রিয়াতে যে কোনও একটি 2-(3/n)সর্বদা বিদ্যমান existsn

এই প্রশ্নের দ্বারা অনুপ্রাণিত হয়ে , আমি সম্ভাব্য ম্যাট্রিকগুলিকে জোর করে জোর করতে ডি ব্রুইজন সিকোয়েন্স ব্যবহার করেছি used এবং ব্রুটফোর্সিংয়ের পরে n=6,7,8,9,10, আমি একটি প্যাটার্ন পেয়েছি যে সর্বাধিক সমাধানটি সর্বদা আকারে থাকে (n, 2n-3)

সুতরাং আমি ম্যাট্রিক্সের ঠিক সেই আকারটিই ব্রুটোফোর্স করার জন্য আরেকটি পদ্ধতি তৈরি করেছি এবং জিনিসগুলিকে গতি বাড়ানোর জন্য মাল্টিপ্রসেসিং ব্যবহার করেছি, কারণ এই কাজটি অত্যন্ত বিতরণযোগ্য ut 16-কোর উবুন্টুতে, এটি n=12প্রায় 4 মিনিটের মধ্যে সমাধান খুঁজে পেতে পারে :

চেষ্টা করে (0, 254)
চেষ্টা করছে (254, 509)
চেষ্টা করে (509, 764)
চেষ্টা করা হচ্ছে (764, 1018)
চেষ্টা করা (1018, 1273)
চেষ্টা করে (1273, 1528)
চেষ্টা করছেন (1528, 1782)
চেষ্টা করা (1782, 2037)
চেষ্টা করে (2037, 2292)
চেষ্টা করা (2292, 2546)
চেষ্টা করছেন (2546, 2801)
চেষ্টা করছেন (2801, 3056)
চেষ্টা করা হচ্ছে (3056, 3310)
চেষ্টা করে (3820, 4075)
চেষ্টা করে (3565, 3820)
চেষ্টা করে (3310, 3565)
(1625, 1646)
[[0 0 0 1 0 0 1 0 1 1 1 0 0 0 1 0 0 1 1 0]
 [0 0 1 0 0 1 0 1 1 1 0 0 0 1 0 0 1 1 0 0]
 [0 1 0 0 1 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 0]
 [১ 0 0 1 0 1 1 1 1 0 0 1 0 0 1 1 0 0 0 0]
 [0 0 1 0 1 1 1 1 0 0 1 0 0 1 1 0 0 0 0 1]
 [0 1 0 1 1 1 1 0 0 0 1 0 0 1 1 0 0 0 0 1 0]
 [১ 0 1 1 1 1 0 0 0 1 0 0 1 1 0 0 0 0 1 0 0]
 [0 1 1 1 1 0 0 0 1 0 0 1 1 0 0 0 0 1 0 0 1]
 [1 1 1 1 0 0 0 1 0 0 1 1 0 0 0 1 1 0 0 1 0]
 [1 1 1 0 0 0 1 0 0 1 1 0 0 0 1 1 0 0 1 0 1]
 [1 1 0 0 0 1 0 0 1 1 0 0 0 1 1 0 0 1 0 1 1]
 [১ 0 0 0 1 0 0 1 1 0 0 0 1 0 0 1 0 1 1 1]]
(12, 21)
স্কোর: 1.7500

বাস্তব 4m9.121s
ব্যবহারকারী 42m47.472s
ss 0m5.780s

গণনার বেশিরভাগ অংশ এক্স এক্স চেক করতে যায়, যার জন্য সমস্ত সাবসেট পরীক্ষা করা প্রয়োজন (সেখানে 2^(2n-3)সাবসেট রয়েছে)

মনে রাখবেন যে আমি প্রথম সারিতে বাম দিকে ঘোরান, প্রশ্নের মতো ডানদিকে নয়। তবে এগুলি সমান কারণ আপনি কেবল পুরো ম্যাট্রিক্সকে বিপরীত করতে পারেন। =)

কোড:

import math
import numpy as np
from itertools import combinations
from multiprocessing import Process, Queue, cpu_count

def de_bruijn(k, n):
    """
    De Bruijn sequence for alphabet k
    and subsequences of length n.
    """
    alphabet = list(range(k))
    a = [0] * k * n
    sequence = []
    def db(t, p):
        if t > n:
            if n % p == 0:
                for j in range(1, p + 1):
                    sequence.append(a[j])
        else:
            a[t] = a[t - p]
            db(t + 1, p)
            for j in range(a[t - p] + 1, k):
                a[t] = j
                db(t + 1, t)
    db(1, 1)
    return sequence

def generate_cyclic_matrix(seq, n):
    result = []
    for i in range(n):
        result.append(seq[i:]+seq[:i])
    return np.array(result)

def generate_cyclic_matrix_without_property_x(n=3, n_jobs=-1):
    seq = de_bruijn(2,n)
    seq = seq + seq[:n/2]
    max_idx = len(seq)
    max_score = 1
    max_matrix = np.array([[]])
    max_ij = (0,0)
    workers = []
    queue = Queue()
    if n_jobs < 0:
        n_jobs += cpu_count()+1
    for i in range(n_jobs):
        worker = Process(target=worker_function, args=(seq,i*(2**n-2*n+3)/n_jobs, (i+1)*(2**n-2*n+3)/n_jobs, n, queue))
        workers.append(worker)
        worker.start()
    (result, max_ij) = queue.get()
    for worker in workers:
        worker.terminate()
    return (result, max_ij)

def worker_function(seq,min_idx,max_idx,n,queue):
    print 'Trying (%d, %d)' % (min_idx, max_idx)
    for i in range(min_idx, max_idx):
        j = i+2*n-3
        result = generate_cyclic_matrix(seq[i:j], n)
        if has_property_x(result):
            continue
        else:
            queue.put( (result, (i,j)) )
            return

def has_property_x(mat):
    vecs = zip(*mat)
    vector_sums = set()
    for i in range(1, len(vecs)+1):
        for combination in combinations(vecs, i):
            vector_sum = tuple(sum(combination, np.array([0]*len(mat))))
            if vector_sum in vector_sums:
                return True
            else:
                vector_sums.add(vector_sum)
    return False

def main():
    import sys
    n = int(sys.argv[1])
    if len(sys.argv) > 2:
        n_jobs = int(sys.argv[2])
    else:
        n_jobs = -1
    (matrix, ij) = generate_cyclic_matrix_without_property_x(n, n_jobs)
    print ij
    print matrix
    print matrix.shape
    print 'Score: %.4f' % (float(matrix.shape[1])/matrix.shape[0])

if __name__ == '__main__':
    main()

পুরানো উত্তর, রেফারেন্সের জন্য

এখনও পর্যন্ত অনুকূল সমাধান ( n=10):

(855, 872)
[[1 1 0 1 0 1 0 0 1 1 1 0 1 1 1 0]
 [1 0 1 0 1 0 0 1 1 1 1 0 1 1 1 0 1]
 [0 1 0 1 0 0 1 1 1 1 1 1 1 0 1 1]
 [1 0 1 0 0 1 1 1 1 1 1 1 0 1 1 0]
 [0 1 0 0 1 1 1 1 1 1 0 0 1 1 0 1]
 [1 0 0 1 1 1 1 0 1 1 0 0 1 1 0 1 0]
 [0 0 1 1 1 1 0 1 1 1 0 1 1 0 1 0 1]
 [0 1 1 1 1 0 1 1 1 0 1 1 0 1 0 1 0]
 [1 1 1 1 0 1 1 0 0 1 1 0 1 0 0 0]
 [1 1 1 0 1 1 0 0 1 1 0 1 0 0 1]]
(10, 17)
স্কোর: 1.7000

এর জন্য n=7:

(86, 97)
[[0 1 1 1 0 1 0 0 1 1 1]
 [1 1 1 0 1 0 0 1 1 1 0]
 [1 1 0 1 0 0 1 1 1 0 1]
 [1 0 1 0 0 1 1 1 0 1 1]
 [0 1 0 0 1 1 1 0 1 1 1]
 [১ 0 0 1 1 1 0 1 1 1 0]
 [0 0 1 1 1 0 1 1 1 0 1]]
(,, ১১)
স্কোর: 1.5714

ওপি ( n=8) দ্বারা বর্ণিত আকারের সাথে একটি সমাধান :

(227, 239)
[[0 1 0 1 1 1 1 1 1 1 0 0]
 [১ 0 1 1 1 1 1 0 1 1 0 0]
 [0 1 1 1 1 1 0 1 1 0 0 1]
 [1 1 1 1 1 0 1 1 0 0 1 0]
 [1 1 1 1 0 1 1 0 0 1 0 1]
 [1 1 1 0 1 1 0 0 1 0 1 1]
 [1 1 0 1 1 0 0 1 0 1 1 1]
 [1 0 1 1 0 0 1 0 1 1 1 1]]
(8, 12)
স্কোর: 1.5000

তবে আরও ভাল একটি ( n=8):

(95, 108)
[[0 1 1 0 0 1 0 0 0 1 1 0 1]
 [1 1 0 0 1 0 0 0 1 1 0 1 0]
 [1 0 0 1 0 0 0 1 1 0 1 0 1]
 [0 0 1 0 0 0 1 1 0 1 0 1 1]
 [0 1 0 0 0 1 1 0 1 0 1 1 0]
 [১ 0 0 0 1 1 0 1 0 1 1 0 0]
 [0 0 0 1 1 0 1 0 1 1 0 0 1]
 [0 0 1 1 0 1 0 1 1 0 0 1 0]]
(8, 13)
স্কোর: 1.6250

এটি এখানে আরও একটি অনুকূল সমাধানও পেয়েছে n=9:

(103, 118)
[[0 1 0 1 1 1 0 0 0 1 1 0 0 1]
 [1 0 1 1 1 0 0 0 0 1 1 0 0 1 0]
 [0 1 1 1 0 0 0 1 1 0 0 1 0 1]
 [1 1 1 0 0 0 0 1 1 0 0 1 0 1 0]
 [1 1 0 0 0 0 1 1 0 0 1 0 1 0 1]
 [1 0 0 0 0 1 1 0 0 1 0 1 0 1 1]
 [0 0 0 0 1 1 0 0 1 0 1 0 1 1 1]
 [0 0 0 1 1 0 0 1 0 1 0 1 1 1 0]
 [0 0 1 1 0 0 1 0 1 0 1 1 1 0 0]]
(9, 15)
স্কোর: 1.6667

কোডটি নিম্নরূপ। এটি কেবল নিষ্ঠুর শক্তি, তবে কমপক্ষে এটি অপের দাবির চেয়ে ভাল কিছু খুঁজে পেতে পারে =)

import numpy as np
from itertools import combinations

def de_bruijn(k, n):
    """
    De Bruijn sequence for alphabet k
    and subsequences of length n.
    """
    alphabet = list(range(k))
    a = [0] * k * n
    sequence = []
    def db(t, p):
        if t > n:
            if n % p == 0:
                for j in range(1, p + 1):
                    sequence.append(a[j])
        else:
            a[t] = a[t - p]
            db(t + 1, p)
            for j in range(a[t - p] + 1, k):
                a[t] = j
                db(t + 1, t)
    db(1, 1)
    return sequence

def generate_cyclic_matrix(seq, n):
    result = []
    for i in range(n):
        result.append(seq[i:]+seq[:i])
    return np.array(result)

def generate_cyclic_matrix_without_property_x(n=3):
    seq = de_bruijn(2,n)
    max_score = 0
    max_matrix = []
    max_ij = (0,0)
    for i in range(2**n+1):
        for j in range(i+n, 2**n+1):
            score = float(j-i)/n
            if score <= max_score:
                continue
            result = generate_cyclic_matrix(seq[i:j], n)
            if has_property_x(result):
                continue
            else:
                if score > max_score:
                    max_score = score
                    max_matrix = result
                    max_ij = (i,j)
    return (max_matrix, max_ij)

def has_property_x(mat):
    vecs = zip(*mat)
    vector_sums = set()
    for i in range(1, len(vecs)):
        for combination in combinations(vecs, i):
            vector_sum = tuple(sum(combination, np.array([0]*len(mat))))
            if vector_sum in vector_sums:
                return True
            else:
                vector_sums.add(vector_sum)
    return False

def main():
    import sys
    n = int(sys.argv[1])
    (matrix, ij) = generate_cyclic_matrix_without_property_x(n)
    print ij
    print matrix
    print matrix.shape
    print 'Score: %.4f' % (float(matrix.shape[1])/matrix.shape[0])

if __name__ == '__main__':
    main()

একটি দুর্দান্ত শুরু :)

2
@ ল্যাম্বিক এখন আমি প্রায় (গণনার সময়সীমাবদ্ধ) যে কাউকে
২.২ এর

সেক্ষেত্রে আপনি কি 19-10-কে পরাজিত করতে পারবেন?

@ ল্যাম্বিক আমি ভাবি না যে আমি পারব। এটির প্রয়োজন n >= 31, যা বোঝায় যে আমাকে 2^(2n-3) = 2^5931-মাত্রিক ভেক্টরের সংমিশ্রণগুলি পরীক্ষা করতে হবে । আমাদের জীবনকাল = ডি শেষ করবেন না
justhalf

2
আপনি কি প্রমাণ করতে পারবেন যে আপনি সর্বদাn*(2n-3)
xnor

7

24/13 26/14 28/15 30/16 32/17 (সি #)

সম্পাদনা: আমার উত্তর থেকে পুরানো তথ্য মুছে ফেলা হয়েছে। আমি বেশিরভাগ পিটার টেলারের মতোই অ্যালগরিদম ব্যবহার করছি ( সম্পাদনা: দেখে মনে হয় তিনি এখন আরও ভাল অ্যালগরিদম ব্যবহার করছেন), যদিও আমি আমার নিজস্ব কিছু অপ্টিমাইজেশান যুক্ত করেছি:

  • আমি একই ভেক্টর রাশির সাথে কলাম সেটগুলি অনুসন্ধানের "মাঝখানে মিলিত হওয়া" কৌশলটি প্রয়োগ করেছি ( এই কেনেনিটির মন্তব্যে প্রস্তাবিত )। এই কৌশলটি মেমরির ব্যবহারকে অনেক উন্নত করেছে, তবে এটি ধীরে ধীরে, তাই আমি HasPropertyXFastফাংশনটি যুক্ত করেছি , এটি "মাঝখানে দেখা" পদ্ধতির ব্যবহারের আগে সমান পরিমাণের সাথে ছোট ছোট সেট রয়েছে কিনা তা দ্রুত পরীক্ষা করে।
  • HasPropertyXFast ফাংশনে কলাম সেটগুলির মাধ্যমে পুনরাবৃত্তি করার সময় , আমি 1 টি কলাম দিয়ে কলাম সেটগুলি পরীক্ষা করা শুরু করি, তারপরে 2, 3 এবং আরও কিছু দিয়ে। কলামের অঙ্কগুলির প্রথম সংঘর্ষের সাথে সাথে ফাংশনটি ফিরে আসে। অনুশীলনে এর অর্থ হ'ল আমাকে সাধারণত কয়েক লক্ষ বা কয়েক হাজার কলাম সেট চেক করতে হবে কয়েক লক্ষের চেয়ে।
  • আমি longপুরো কলামগুলি এবং তাদের ভেক্টরের পরিমাণগুলি সঞ্চয় এবং তুলনা করতে ভেরিয়েবলগুলি ব্যবহার করছি । এই পদ্ধতিটি অ্যারে হিসাবে কলামগুলির তুলনা করার চেয়ে কমপক্ষে তাত্পর্যপূর্ণ ক্রম।
  • আমি long ডেটা টাইপ এবং আমার ব্যবহারের নিদর্শনগুলির জন্য অনুকূলিত হ্যাশसेटটির নিজস্ব বাস্তবায়ন যুক্ত করেছি ।
  • আমি মেমরির বরাদ্দ সংখ্যা কমাতে এবং কর্মক্ষমতা উন্নত করতে আবেদনের পুরো জীবনকালের জন্য একই 3 টি হ্যাশসেট পুনরায় ব্যবহার করছি।
  • মাল্টিথ্রেডিং সমর্থন।

প্রোগ্রাম আউটপুট:

00000000000111011101010010011111
10000000000011101110101001001111
11000000000001110111010100100111
11100000000000111011101010010011
11110000000000011101110101001001
11111000000000001110111010100100
01111100000000000111011101010010
00111110000000000011101110101001
10011111000000000001110111010100
01001111100000000000111011101010
00100111110000000000011101110101
10010011111000000000001110111010
01001001111100000000000111011101
10100100111110000000000011101110
01010010011111000000000001110111
10101001001111100000000000111011
11010100100111110000000000011101
Score: 32/17 = 1,88235294117647
Time elapsed: 02:11:05.9791250

কোড:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

class Program
{
    const int MaxWidth = 32;
    const int MaxHeight = 17;

    static object _lyndonWordLock = new object();

    static void Main(string[] args)
    {
        Stopwatch sw = Stopwatch.StartNew();
        double maxScore = 0;
        const int minHeight = 17; // 1
        for (int height = minHeight; height <= MaxHeight; height++)
        {
            Console.WriteLine("Row count = " + height);
            Console.WriteLine("Time elapsed: " + sw.Elapsed + "\r\n");

            int minWidth = Math.Max(height, (int)(height * maxScore) + 1);
            for (int width = minWidth; width <= MaxWidth; width++)
            {
#if MULTITHREADING
                int[,] matrix = FindMatrixParallel(width, height);
#else
                int[,] matrix = FindMatrix(width, height);
#endif
                if (matrix != null)
                {
                    PrintMatrix(matrix);
                    Console.WriteLine("Time elapsed: " + sw.Elapsed + "\r\n");
                    maxScore = (double)width / height;
                }
                else
                    break;
            }
        }
    }

#if MULTITHREADING
    static int[,] FindMatrixParallel(int width, int height)
    {
        _lyndonWord = 0;
        _stopSearch = false;

        int threadCount = Environment.ProcessorCount;
        Task<int[,]>[] tasks = new Task<int[,]>[threadCount];
        for (int i = 0; i < threadCount; i++)
            tasks[i] = Task<int[,]>.Run(() => FindMatrix(width, height));

        int index = Task.WaitAny(tasks);
        if (tasks[index].Result != null)
            _stopSearch = true;

        Task.WaitAll(tasks);
        foreach (Task<int[,]> task in tasks)
            if (task.Result != null)
                return task.Result;

        return null;
    }

    static volatile bool _stopSearch;
#endif

    static int[,] FindMatrix(int width, int height)
    {
#if MULTITHREADING
        _columnSums = new LongSet();
        _left = new LongSet();
        _right = new LongSet();
#endif

        foreach (long rowTemplate in GetLyndonWords(width))
        {
            int[,] matrix = new int[width, height];
            for (int x = 0; x < width; x++)
            {
                int cellValue = (int)(rowTemplate >> (width - 1 - x)) % 2;
                for (int y = 0; y < height; y++)
                    matrix[(x + y) % width, y] = cellValue;
            }

            if (!HasPropertyX(matrix))
                return matrix;

#if MULTITHREADING
            if (_stopSearch)
                return null;
#endif
        }

        return null;
    }

#if MULTITHREADING
    static long _lyndonWord;
#endif

    static IEnumerable<long> GetLyndonWords(int length)
    {
        long lyndonWord = 0;
        long max = (1L << (length - 1)) - 1;
        while (lyndonWord <= max)
        {
            if ((lyndonWord % 2 != 0) && PrecedesReversal(lyndonWord, length))
                yield return lyndonWord;

#if MULTITHREADING
            lock (_lyndonWordLock)
            {
                if (_lyndonWord <= max)
                    _lyndonWord = NextLyndonWord(_lyndonWord, length);
                else
                    yield break;

                lyndonWord = _lyndonWord;
            }
#else
            lyndonWord = NextLyndonWord(lyndonWord, length);
#endif
        }
    }

    static readonly int[] _lookup =
    {
        32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4, 7, 17,
        0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5, 20, 8, 19, 18
    };

    static int NumberOfTrailingZeros(uint i)
    {
        return _lookup[(i & -i) % 37];
    }

    static long NextLyndonWord(long w, int length)
    {
        if (w == 0)
            return 1;

        int currentLength = length - NumberOfTrailingZeros((uint)w);
        while (currentLength < length)
        {
            w += w >> currentLength;
            currentLength *= 2;
        }

        w++;

        return w;
    }

    private static bool PrecedesReversal(long lyndonWord, int length)
    {
        int shift = length - 1;

        long reverse = 0;
        for (int i = 0; i < length; i++)
        {
            long bit = (lyndonWord >> i) % 2;
            reverse |= bit << (shift - i);
        }

        for (int i = 0; i < length; i++)
        {
            if (reverse < lyndonWord)
                return false;

            long bit = reverse % 2;
            reverse /= 2;
            reverse += bit << shift;
        }

        return true;
    }

#if MULTITHREADING
    [ThreadStatic]
#endif
    static LongSet _left = new LongSet();
#if MULTITHREADING
    [ThreadStatic]
#endif
    static LongSet _right = new LongSet();

    static bool HasPropertyX(int[,] matrix)
    {
        long[] matrixColumns = GetMatrixColumns(matrix);
        if (matrixColumns.Length == 1)
            return false;

        return HasPropertyXFast(matrixColumns) || MeetInTheMiddle(matrixColumns);
    }

    static bool MeetInTheMiddle(long[] matrixColumns)
    {
        long[] leftColumns = matrixColumns.Take(matrixColumns.Length / 2).ToArray();
        long[] rightColumns = matrixColumns.Skip(matrixColumns.Length / 2).ToArray();

        if (PrepareHashSet(leftColumns, _left) || PrepareHashSet(rightColumns, _right))
            return true;

        foreach (long columnSum in _left.GetValues())
            if (_right.Contains(columnSum))
                return true;

        return false;
    }

    static bool PrepareHashSet(long[] columns, LongSet sums)
    {
        int setSize = (int)System.Numerics.BigInteger.Pow(3, columns.Length);
        sums.Reset(setSize, setSize);
        foreach (long column in columns)
        {
            foreach (long sum in sums.GetValues())
                if (!sums.Add(sum + column) || !sums.Add(sum - column))
                    return true;

            if (!sums.Add(column) || !sums.Add(-column))
                return true;
        }

        return false;
    }

#if MULTITHREADING
    [ThreadStatic]
#endif
    static LongSet _columnSums = new LongSet();

    static bool HasPropertyXFast(long[] matrixColumns)
    {
        int width = matrixColumns.Length;

        int maxColumnCount = width / 3;
        _columnSums.Reset(width, SumOfBinomialCoefficients(width, maxColumnCount));

        int resetBit, setBit;
        for (int k = 1; k <= maxColumnCount; k++)
        {
            uint columnMask = (1u << k) - 1;
            long sum = 0;
            for (int i = 0; i < k; i++)
                sum += matrixColumns[i];

            while (true)
            {
                if (!_columnSums.Add(sum))
                    return true;
                if (!NextColumnMask(columnMask, k, width, out resetBit, out setBit))
                    break;
                columnMask ^= (1u << resetBit) ^ (1u << setBit);
                sum = sum - matrixColumns[resetBit] + matrixColumns[setBit];
            }
        }

        return false;
    }

    // stolen from Peter Taylor
    static bool NextColumnMask(uint mask, int k, int n, out int resetBit, out int setBit)
    {
        int gap = NumberOfTrailingZeros(~mask);
        int next = 1 + NumberOfTrailingZeros(mask & (mask + 1));

        if (((k - gap) & 1) == 0)
        {
            if (gap == 0)
            {
                resetBit = next - 1;
                setBit = next - 2;
            }
            else if (gap == 1)
            {
                resetBit = 0;
                setBit = 1;
            }
            else
            {
                resetBit = gap - 2;
                setBit = gap;
            }
        }
        else
        {
            if (next == n)
            {
                resetBit = 0;
                setBit = 0;
                return false;
            }

            if ((mask & (1 << next)) == 0)
            {
                if (gap == 0)
                {
                    resetBit = next - 1;
                    setBit = next;
                }
                else
                {
                    resetBit = gap - 1;
                    setBit = next;
                }
            }
            else
            {
                resetBit = next;
                setBit = gap;
            }
        }

        return true;
    }

    static long[] GetMatrixColumns(int[,] matrix)
    {
        int width = matrix.GetLength(0);
        int height = matrix.GetLength(1);

        long[] result = new long[width];
        for (int x = 0; x < width; x++)
        {
            long column = 0;
            for (int y = 0; y < height; y++)
            {
                column *= 13;
                if (matrix[x, y] == 1)
                    column++;
            }

            result[x] = column;
        }

        return result;
    }

    static int SumOfBinomialCoefficients(int n, int k)
    {
        int result = 0;
        for (int i = 0; i <= k; i++)
            result += BinomialCoefficient(n, i);
        return result;
    }

    static int BinomialCoefficient(int n, int k)
    {
        long result = 1;
        for (int i = n - k + 1; i <= n; i++)
            result *= i;
        for (int i = 2; i <= k; i++)
            result /= i;
        return (int)result;
    }

    static void PrintMatrix(int[,] matrix)
    {
        int width = matrix.GetLength(0);
        int height = matrix.GetLength(1);

        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
                Console.Write(matrix[x, y]);
            Console.WriteLine();
        }

        Console.WriteLine("Score: {0}/{1} = {2}", width, height, (double)width / height);
    }
}


class LongSet
{
    private static readonly int[] primes =
    {
        17, 37, 67, 89, 113, 149, 191, 239, 307, 389, 487, 613, 769, 967, 1213, 1523, 1907,
        2389, 2999, 3761, 4703, 5879, 7349, 9187, 11489, 14369, 17971, 22469, 28087, 35111,
        43889, 54869, 68597, 85751, 107197, 133999, 167521, 209431, 261791, 327247, 409063,
        511333, 639167, 798961, 998717, 1248407, 1560511, 1950643, 2438309, 3047909,
        809891, 4762367, 5952959, 7441219, 9301529, 11626913, 14533661, 18167089, 22708867,
        28386089, 35482627, 44353297, 55441637, 69302071, 86627603, 108284507, 135355669,
        169194593, 211493263, 264366593, 330458263, 413072843, 516341057, 645426329,
        806782913, 1008478649, 1260598321
    };

    private int[] _buckets;
    private int[] _nextItemIndexes;
    private long[] _items;
    private int _count;
    private int _minCapacity;
    private int _maxCapacity;
    private int _currentCapacity;

    public LongSet()
    {
        Initialize(0, 0);
    }

    private int GetPrime(int capacity)
    {
        foreach (int prime in primes)
            if (prime >= capacity)
                return prime;

        return int.MaxValue;
    }

    public void Reset(int minCapacity, int maxCapacity)
    {
        if (maxCapacity > _maxCapacity)
            Initialize(minCapacity, maxCapacity);
        else
            ClearBuckets();
    }

    private void Initialize(int minCapacity, int maxCapacity)
    {
        _minCapacity = GetPrime(minCapacity);
        _maxCapacity = GetPrime(maxCapacity);
        _currentCapacity = _minCapacity;

        _buckets = new int[_maxCapacity];
        _nextItemIndexes = new int[_maxCapacity];
        _items = new long[_maxCapacity];
        _count = 0;
    }

    private void ClearBuckets()
    {
        Array.Clear(_buckets, 0, _currentCapacity);
        _count = 0;
        _currentCapacity = _minCapacity;
    }

    public bool Add(long value)
    {
        int bucket = (int)((ulong)value % (ulong)_currentCapacity);
        for (int i = _buckets[bucket] - 1; i >= 0; i = _nextItemIndexes[i])
            if (_items[i] == value)
                return false;

        if (_count == _currentCapacity)
        {
            Grow();
            bucket = (int)((ulong)value % (ulong)_currentCapacity);
        }

        int index = _count;
        _items[index] = value;
        _nextItemIndexes[index] = _buckets[bucket] - 1;
        _buckets[bucket] = index + 1;
        _count++;

        return true;
    }

    private void Grow()
    {
        Array.Clear(_buckets, 0, _currentCapacity);

        const int growthFactor = 8;
        int newCapacity = GetPrime(_currentCapacity * growthFactor);
        if (newCapacity > _maxCapacity)
            newCapacity = _maxCapacity;
        _currentCapacity = newCapacity;

        for (int i = 0; i < _count; i++)
        {
            int bucket = (int)((ulong)_items[i] % (ulong)newCapacity);
            _nextItemIndexes[i] = _buckets[bucket] - 1;
            _buckets[bucket] = i + 1;
        }
    }

    public bool Contains(long value)
    {
        int bucket = (int)((ulong)value % (ulong)_buckets.Length);
        for (int i = _buckets[bucket] - 1; i >= 0; i = _nextItemIndexes[i])
            if (_items[i] == value)
                return true;

        return false;
    }

    public IReadOnlyList<long> GetValues()
    {
        return new ArraySegment<long>(_items, 0, _count);
    }
}

কনফিগারেশন ফাইল:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <gcAllowVeryLargeObjects enabled="true" />
  </runtime>
</configuration>

কিছু ক্ষেত্রে আপনি অনুকূলিত না হয়ে নিরাশ করেছেন বলে মনে হচ্ছে। কেবলমাত্র যা একটি অপ্টিমাইজেশনের মতো দেখায় তা হ'ল বিটগুলি সংঘর্ষের অনুমতি ulongএবং ব্যবহারের পরিবর্তে শিফ্টের মোড়কে দেওয়া BigInteger
পিটার টেলর

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

যদিও পারফরম্যান্সের পরিবর্তনগুলি প্রায়শই অবাক করে দেয়, নীতিগতভাবে প্রাথমিকভাবে গর্ভপাতটি 2 এর ফ্যাক্টরের চেয়ে বেশি দেওয়া উচিত নয় এবং GetSumOfColumnsএকটি অতিরিক্ত লুপ যুক্ত করে যা আমি 2 এর 2 ফ্যাক্টরের চেয়ে বেশি দামের প্রত্যাশা করতাম: মুখোশ বাছাই করা আকর্ষণীয় মনে হয়: সম্ভবত আপনি পারতেন এ সম্পর্কে কিছুটা কথা বলার জন্য উত্তরটি সম্পাদনা করবেন? (এবং কোনও পর্যায়ে আমি প্রাথমিক গর্ভপাত বন্ধ করার বিকল্প উপায় নিয়ে পরীক্ষা করবো: যে কারণে আমি এটি করতে পারি না তা হ্যাশসেট সহবর্তী পুনরাবৃত্তি এবং পরিবর্তনকে সমর্থন করে না, তবে আমার পুনরাবৃত্তির প্রয়োজন এড়াতে আমার ধারণা রয়েছে) ।
পিটার টেলর

2
@ আসফাল্ফ, একটি নির্দিষ্ট আকারের সাবসেটগুলি পুনরাবৃত্তি করার জন্য গ্রে-এস্কো পদ্ধতির ব্যবহার করা আসলেই সার্থক। এটি আমাকে 9 মিনিটের নীচে 26/14 এবং 2 ঘন্টার মধ্যে 34 টির সন্ধান করতে দেয়, আমি যে মুহূর্তে বাতিল হয়ে যাই। আমি উপযুক্ত সময়ে 28/15 পেতে পারি কিনা তা পরীক্ষা করে দেখছি।
পিটার টেলর

1
@ ল্যাম্বিক, আমি .5৫.৫ ঘন্টার মধ্যে ২৯/১৫ অবসন্নভাবে অনুসন্ধান করেছি। 31/16 প্রায় 3 বার সময় লাগে - এক সপ্তাহেরও বেশি। আমি 29/15 পরীক্ষাটি চালানো শুরু করার পর থেকে আমরা দুজনেই কিছুটা আশাবাদ করেছি, তাই সম্ভবত এটি এখন এক সপ্তাহের মধ্যে নেমে আসবে। আমার কোড বা সাবপটিমাসপ্রাইম কোডটি সংকলন করা থেকে বিরত হওয়ার কিছু নেই এবং যদি আপনার এমন কোনও কম্পিউটার থাকে যা আপনি এত দিন চালিয়ে যেতে পারেন।
পিটার টেলর
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.