प्रत्येक आकार Toeplitz मैट्रिक्स के लिए अधिकतम निर्धारक का पता लगाएं


14

एक निश्चित एन के लिए, एन टोप्लेट्ज़ मेट्रिसेस द्वारा एन प्रविष्टियों पर विचार करें, जो या तो 0 या 1 हैं। इसका उद्देश्य ऐसे सभी टोलपिट्ज़ मैट्रिसेस पर अधिकतम निर्धारक खोजना है।

कार्य

n1 से ऊपर की ओर से प्रत्येक के लिए , एन टोप्लेट्ज़ मैट्रिसेस द्वारा एन के द्वारा अधिकतम निर्धारक का उत्पादन किया जाता है, जो कि या तो 0 या 1. हैं, nजिसमें एक आउटपुट होना चाहिए जिसमें अधिकतम निर्धारक भी होना चाहिए और एक उदाहरण मैट्रिक्स भी होता है जो उस तक पहुंचता है।

स्कोर

आपका स्कोर nमेरे कंप्यूटर पर 2 मिनट में आपका सबसे बड़ा कोड हो जाता है। थोड़ा स्पष्ट करने के लिए, आपका कोड कुल 2 मिनट तक चल सकता है, यह 2 मिनट प्रति नहीं है n

टाई ब्रेकर

यदि दो प्रविष्टियों को समान nस्कोर मिलता है, तो जीतने वाली प्रविष्टि वह होगी जो nमेरी मशीन पर सबसे कम समय में मिलती है । यदि इस कसौटी पर भी दो सर्वश्रेष्ठ प्रविष्टियाँ समान हैं तो विजेता सबसे पहले प्रस्तुत किया गया उत्तर होगा।

भाषा और पुस्तकालय

आप किसी भी स्वतंत्र रूप से उपलब्ध भाषा और अपनी पसंद की लाइब्रेरी का उपयोग कर सकते हैं। मुझे आपके कोड को चलाने में सक्षम होना चाहिए ताकि कृपया अपने कोड को लिनक्स में चलाने / संकलित करने के लिए पूर्ण विवरण शामिल करें यदि संभव हो तो।

मेरी मशीन मेरी मशीन पर टाइमिंग चलाई जाएगी। यह एक मानक ubuntu एक AMD FX-8350 आठ-कोर प्रोसेसर पर स्थापित है। इसका मतलब यह भी है कि मुझे आपका कोड चलाने में सक्षम होना चाहिए।

छोटे जवाब

N = 1..10 के लिए आउटपुट 1,1,2,3,5,9,32,56,125,315 होना चाहिए

यह अनुक्रम OEIS में नहीं है और इसलिए विजेता प्रविष्टि को भी वहाँ एक नई प्रविष्टि का प्रस्ताव मिलता है।

अब तक प्रवेश करता है

  • n=10 n=11पायथन में Vioz द्वारा
  • n=9टाइलो द्वारा C में
  • n=12लीजेंड्रे द्वारा जे
  • n=10Tensibai द्वारा आर में
  • n=14C ++ में SteelRaven द्वारा
  • n=14C ++ में RetoKoradi द्वारा

@AlexA। आप सही हैं और मैंने माफी मांगी है। सौभाग्य से दोनों समस्याएं बहुत समान हैं इसलिए उसे आसानी से अपने कोड को संशोधित करने में सक्षम होना चाहिए।

@Vioz द्वारा समाधान 1, 1, 2, 3, 5, 9, 32 के साथ शुरू होने वाले अनुक्रम के साथ आता है। इसलिए n = 5 के लिए मूल्य आपके द्वारा सूचीबद्ध सूची से अलग है। चूंकि अन्य सभी मूल्य मेल खाते हैं, ऐसा लगता है कि समाधान शायद सही है, और यह प्रश्न में केवल एक टाइपो है?
रेटो कोराडी

@RetoKoradi धन्यवाद फिक्स्ड।

यहाँ 10 संभावित बाइनरी टोप्लेट्ज़ मैट्रिसेस हैं जिनके लिए अधिकतम नियतांक हैं n = 1..10: ghostbin.com/paste/axkpa
Tyilo

2
अवलोकन के रूप में जो दूसरों की मदद कर सकता है, लेकिन मैं 14. परे सत्यापित नहीं कर सकता। यह शीर्ष पंक्ति के संबंधित साधन प्रतीत होते हैं और टोप्लेट्ज़ मैट्रिक्स का पहला कॉलम हमेशा अधिकतम निर्धारक के लिए 0.4 <= m <= 0.6 है।
मिकट

जवाबों:


3

सी ++ के साथ pthreads

यह मेरी मशीन पर सिर्फ 1 मिनट के भीतर n = 14 हो जाता है। लेकिन चूंकि यह सिर्फ 2-कोर वाला लैपटॉप है, इसलिए मुझे उम्मीद है कि 8-कोर टेस्ट मशीन 2 मिनट के अंदर n = 15 खत्म कर सकती है। मेरी मशीन पर लगभग 4:20 मिनट लगते हैं।

मैं वास्तव में कुछ अधिक कुशल के साथ आने की उम्मीद कर रहा था। वहाँ गया है मिल गया और अधिक कुशलता से एक द्विआधारी मैट्रिक्स की नियत गणना करने के लिए एक तरह से किया जाना है। मैं कुछ प्रकार के गतिशील प्रोग्रामिंग दृष्टिकोण के साथ आना चाहता था जो निर्धारक गणना में +1 और -1 शब्दों को गिनता है। लेकिन यह अभी तक एक साथ नहीं आया है।

चूँकि बाउंटी समाप्त होने वाली है, इसलिए मैंने मानक ब्रूट फ़ोर्स अप्रोच लागू किया:

  • सभी संभव टोलपिट्ज़ मैट्रिस पर लूप करें।
  • प्रत्येक ट्रांसपोज़्ड मैट्रिक्स जोड़ी में दो में से एक को छोड़ दें। चूंकि मैट्रिक्स को बिटमास्क मानों द्वारा वर्णित किया गया है, इसलिए यह उन सभी मूल्यों को छोड़ कर करना आसान है, जहां बिटकॉम्स का उलटा बिटमैप के मुकाबले छोटा होता है।
  • दृढ़ संकल्प की गणना एक पाठ्य पुस्तक एलआर अपघटन के साथ की जाती है। कुछ मामूली प्रदर्शन ट्यूनिंग को छोड़कर, मैंने अपने कॉलेज के संख्यात्मक तरीकों की किताब से एल्गोरिथ्म में मुख्य सुधार किया है कि मैं एक सरल धुरी रणनीति का उपयोग करता हूं।
  • समांतरकरण pthreads के साथ किया जाता है। बस प्रत्येक थ्रेड द्वारा संसाधित मूल्यों के लिए नियमित रिक्ति का उपयोग करने से बहुत बुरा भार संतुलन होता है, इसलिए मैंने कुछ स्विज़लिंग की शुरुआत की।

मैंने मैक ओएस पर इसका परीक्षण किया, लेकिन मैंने पहले भी उबंटू पर इसी तरह के कोड का उपयोग किया था, इसलिए मुझे उम्मीद है कि यह एक अड़चन के बिना संकलन और चलेगा:

  1. .cppएक्सटेंशन के साथ फ़ाइल में कोड सहेजें , जैसे optim.cpp
  2. के साथ संकलित करें gcc -Ofast optim.cpp -lpthread -lstdc++
  3. के साथ चला time ./a.out 14 8। पहला तर्क अधिकतम है n। 14 को सुनिश्चित करने के लिए 2 मिनट के भीतर खत्म करना चाहिए, लेकिन यह बहुत अच्छा होगा यदि आप 15 के रूप में अच्छी तरह से कोशिश कर सकते हैं। दूसरा तर्क थ्रेड्स की संख्या है। मशीन के कोर की संख्या के समान मूल्य का उपयोग करना आम तौर पर एक अच्छी शुरुआत है, लेकिन कुछ बदलावों की कोशिश करने से समय में सुधार हो सकता है।

मुझे बताएं कि क्या आपको कोड बनाने या चलाने में कोई समस्या है।

#include <stdint.h>
#include <pthread.h>
#include <cstdlib>
#include <iostream>

static int NMax = 14;
static int ThreadCount = 4;

static pthread_mutex_t ThreadMutex;
static pthread_cond_t ThreadCond;
static int BarrierCount = 0;

static float* MaxDetA;
static uint32_t* MaxDescrA;

static inline float absVal(float val)
{
    return val < 0.0f ? -val : val;
}

static uint32_t reverse(int n, uint32_t descr)
{
    uint32_t descrRev = 0;
    for (int iBit = 0; iBit < 2 * n - 1; ++iBit)
    {
        descrRev <<= 1;
        descrRev |= descr & 1;
        descr >>= 1;
    }

    return descrRev;
}

static void buildMat(int n, float mat[], uint32_t descr)
{
    int iDiag;
    for (iDiag = 1 - n; iDiag < 0; ++iDiag)
    {
        float val = static_cast<float>(descr & 1);
        descr >>= 1;
        for (int iRow = 0; iRow < n + iDiag; ++iRow)
        {
            mat[iRow * (n + 1) - iDiag] = val;
        }
    }

    for ( ; iDiag < n; ++iDiag)
    {
        float val = static_cast<float>(descr & 1);
        descr >>= 1;
        for (int iCol = 0; iCol < n - iDiag; ++iCol)
        {
            mat[iCol * (n + 1) + iDiag * n] = val;
        }
    }
}

static float determinant(int n, float mat[])
{
    float det = 1.0f;
    for (int k = 0; k < n - 1; ++k)
    {
        float maxVal = 0.0f;
        int pk = 0;
        for (int i = k; i < n; ++i)
        {
            float q = absVal(mat[i * n + k]);
            if (q > maxVal)
            {
                maxVal = q;
                pk = i;
            }
        }

        if (pk != k)
        {
            det = -det;
            for (int j = 0; j < n; ++j)
            {
                float t = mat[k * n + j];
                mat[k * n + j] = mat[pk * n + j];
                mat[pk * n + j] = t;
            }
        }

        float s = mat[k * n + k];
        det *= s;

        s = 1.0f / s;
        for (int i = k + 1; i < n; ++i)
        {
            mat[i * n + k] *= s;
            for (int j = k + 1; j < n; ++j)
            {
                mat[i * n + j] -= mat[i * n + k] * mat[k * n + j];
            }
        }
    }

    det *= mat[n * n - 1];

    return det;
}

static void threadBarrier()
{
    pthread_mutex_lock(&ThreadMutex);

    ++BarrierCount;
    if (BarrierCount <= ThreadCount)
    {
        pthread_cond_wait(&ThreadCond, &ThreadMutex);
    }
    else
    {
        pthread_cond_broadcast(&ThreadCond);
        BarrierCount = 0;
    }

    pthread_mutex_unlock(&ThreadMutex);
}

static void* threadFunc(void* pData)
{
    int* pThreadIdx = static_cast<int*>(pData);
    int threadIdx = *pThreadIdx;

    float* mat = new float[NMax * NMax];

    for (int n = 1; n <= NMax; ++n)
    {
        uint32_t descrRange(1u << (2 * n - 1));
        float maxDet = 0.0f;
        uint32_t maxDescr = 0;

        uint32_t descrInc = threadIdx;
        for (uint32_t descrBase = 0;
             descrBase + descrInc < descrRange;
             descrBase += ThreadCount)
        {
            uint32_t descr = descrBase + descrInc;
            descrInc = (descrInc + 1) % ThreadCount;

            if (reverse(n, descr) > descr)
            {
                continue;
            }

            buildMat(n, mat, descr);
            float det = determinant(n, mat);
            if (det > maxDet)
            {
                maxDet = det;
                maxDescr = descr;
            }
        }

        MaxDetA[threadIdx] = maxDet;
        MaxDescrA[threadIdx] = maxDescr;

        threadBarrier();
        // Let main thread output results.
        threadBarrier();
    }

    delete[] mat;

    return 0;
}

static void printMat(int n, float mat[])
{
    for (int iRow = 0; iRow < n; ++iRow)
    {
        for (int iCol = 0; iCol < n; ++iCol)
        {
            std::cout << " " << mat[iRow * n + iCol];
        }
        std::cout << std::endl;
    }

    std::cout << std::endl;
}

int main(int argc, char* argv[])
{
    if (argc > 1)
    {
        NMax = atoi(argv[1]);
        if (NMax > 16)
        {
            NMax = 16;
        }
    }

    if (argc > 2)
    {
        ThreadCount = atoi(argv[2]);
    }

    MaxDetA = new float[ThreadCount];
    MaxDescrA = new uint32_t[ThreadCount];

    pthread_mutex_init(&ThreadMutex, 0);
    pthread_cond_init(&ThreadCond, 0);

    int* threadIdxA = new int[ThreadCount];
    pthread_t* threadA = new pthread_t[ThreadCount];

    for (int iThread = 0; iThread < ThreadCount; ++iThread)
    {
        threadIdxA[iThread] = iThread;
        pthread_create(threadA + iThread, 0, threadFunc, threadIdxA + iThread);
    }

    float* mat = new float[NMax * NMax];

    for (int n = 1; n <= NMax; ++n)
    {
        threadBarrier();

        float maxDet = 0.0f;
        uint32_t maxDescr = 0;

        for (int iThread = 0; iThread < ThreadCount; ++iThread)
        {
            if (MaxDetA[iThread] > maxDet)
            {
                maxDet = MaxDetA[iThread];
                maxDescr = MaxDescrA[iThread];
            }
        }

        std::cout << "n = " << n << " det = " << maxDet << std::endl;
        buildMat(n, mat, maxDescr);
        printMat(n, mat);

        threadBarrier();
    }

    delete[] mat;

    delete[] MaxDetA;
    delete[] MaxDescrA;

    delete[] threadIdxA;
    delete[] threadA;

    return 0;
}

केवल पूर्णांक अंकगणितीय का उपयोग करके एक पूर्णांक मैट्रिक्स के निर्धारक की गणना करने का एक दिलचस्प तरीका है: कुछ परिमित क्षेत्र में एलयू अपघटन (मूल रूप से एक बड़ा प्रमुख मॉड)। मुझे नहीं पता कि यह तेजी से होगा।
lirtosiast

@ThomasKwa कि शायद अभी भी O (n ^ 3) होगा? यह बड़े मैट्रिक्स के लिए सहायक हो सकता है जहां फ्लोटिंग पॉइंट सटीकता अन्यथा एक मुद्दा बन जाएगा। मैं वास्तव में साहित्य की तलाश में नहीं था। खैर, मैंने एक त्वरित खोज की, और टोप्लेट्ज़ मैट्रिस के निर्धारकों की गणना के बारे में एक पेपर पाया। लेकिन मेरे लिए बहुत सारे खुले सवाल थे कि मैं कोशिश करने और इसे लागू करने के लिए समय निकालूं।
रेटो कोराडी

1
@ लेम्बिक मैं कोशिश करूंगा और आज बाद में इसे देखूंगा। मैंने कल आपकी अन्य संबंधित चुनौती के लिए बड़े आकारों को संभालने के लिए इसे बदल दिया। N = 30 के लिए अब तक के उच्चतम स्कोर को नहीं हरा सका, मेरी हेरास्टिक्स 5 * 10 ^ 13 से नीचे अटक गई हैं।
रेटो कोराडी

1
@Lembik देखें paste.ubuntu.com/11915546 कोड और के लिए paste.ubuntu.com/11915532 अप एन = 19 के परिणामों के लिए।
रेटो कोरदी

1
@Lembik n = 20 तक परिणाम paste.ubuntu.com/11949738 पर हैं । वे अब सभी बंधे हुए समाधानों को सूचीबद्ध करते हैं, जिसमें विकर्ण के मूल्य को जल्दी से देखने के लिए विशेषताएँ शामिल हैं और क्या वे परिचालित हैं। एम = 18,19,20 के लिए सभी मैक्सिमा सर्कुलर मैट्रिसेस हैं। कृपया उन्हें कहीं भी प्रकाशित करने से पहले निर्धारकों की जाँच करें।
रेटो कोरदी

8

जे

अद्यतन: आधे से अधिक मूल्यों को खोजने के लिए बेहतर कोड। अब n=12120 सेकंड (217s से 60s तक) के भीतर आराम से गणना करता है ।

आपको J के नवीनतम संस्करण की आवश्यकता होगी ।

#!/usr/bin/jconsole

dim =: -:@>:@#
take =: i.@dim
rotstack =: |."0 1~ take
toep =: (dim (|."1 @: {."1) rotstack)"1
det =: -/ . * @: toep
ps =: 3 : ',/(0 1 ,"0 1/ ,.y)'
canonical =: #. >: [: #. |. " 1

lss =: 3 : 0
  shape =. (2^y), y
  shape $ ,>{;/(y,2)$0 1
)

ls =: (canonical@:lss) # lss
ans =: >./ @: det @: ls @: <: @: +:

display =: 3 : 0
echo 'n = ';y;'the answer is';ans y
)
display"0 (1 + i.13)
exit''

इसे चलाएं और दो मिनट ऊपर होने पर मारें। मेरे परिणाम (MBP 2014 - 16GB RAM):

┌────┬─┬─────────────┬─┐
│n = │1│the answer is│1│
└────┴─┴─────────────┴─┘
┌────┬─┬─────────────┬─┐
│n = │2│the answer is│1│
└────┴─┴─────────────┴─┘
┌────┬─┬─────────────┬─┐
│n = │3│the answer is│2│
└────┴─┴─────────────┴─┘
┌────┬─┬─────────────┬─┐
│n = │4│the answer is│3│
└────┴─┴─────────────┴─┘
┌────┬─┬─────────────┬─┐
│n = │5│the answer is│5│
└────┴─┴─────────────┴─┘
┌────┬─┬─────────────┬─┐
│n = │6│the answer is│9│
└────┴─┴─────────────┴─┘
┌────┬─┬─────────────┬──┐
│n = │7│the answer is│32│
└────┴─┴─────────────┴──┘
┌────┬─┬─────────────┬──┐
│n = │8│the answer is│56│
└────┴─┴─────────────┴──┘
┌────┬─┬─────────────┬───┐
│n = │9│the answer is│125│
└────┴─┴─────────────┴───┘
┌────┬──┬─────────────┬───┐
│n = │10│the answer is│315│
└────┴──┴─────────────┴───┘
┌────┬──┬─────────────┬────┐
│n = │11│the answer is│1458│
└────┴──┴─────────────┴────┘
┌────┬──┬─────────────┬────┐
│n = │12│the answer is│2673│
└────┴──┴─────────────┴────┘

कुल रन समय = 61.83 s।


सिर्फ मनोरंजन के लिए

┌────┬──┬─────────────┬────┐
│n = │13│the answer is│8118│
└────┴──┴─────────────┴────┘

इसने अपने आप लगभग 210 सेकंड का समय लिया।


1
परीक्षकों को ध्यान दें: n = 12स्मृति की लगभग 18 GiB की आवश्यकता होती है।
डेनिस

यह बहुत अच्छा सुधार है। हालांकि उत्पादन थोड़ा छोटा है। मेरे लिए j64-804 का उपयोग करते हुए यह n = 1 दो बार आउटपुट करता है, इसलिए यह हमेशा के लिए एक के बाद एक बाहर निकलता है।

@Lembik आह यह सही है। मैंने अभी कोड अपडेट किया है; क्या आप फिर से दौड़ने की कोशिश कर सकते हैं? धन्यवाद! (मैंने इसकी गणना करने के लिए इसे सेट किया है n=13। आप 13दूसरी-से-अंतिम पंक्ति में इसे बदल सकते हैं कि आप जो चाहें उसकी गणना करें।)
लीजेंड्रे

मैंने इसे फिर से चलाया और यह अभी भी 12.

@ लेम्बिक हम्म .. क्या आप कह रहे हैं कि यह समय सीमा के भीतर १२ हो जाता है और इसके कुछ समय बाद १३ हो जाता है (जो मैं उम्मीद करता हूं), या यह कि यह १३ तक नहीं मिलता (यानी प्रोग्राम १२ के बाद रुकता है)।
लीजेंड्रे

4

अजगर २

यह एक बहुत ही सीधा समाधान है, और शायद प्रतियोगिता नहीं जीतेगी। लेकिन हे, यह काम करता है!

मैं वास्तव में क्या हो रहा है का एक त्वरित अवलोकन देता हूँ।

  1. मैं पहली बार हर संभव शुरुआती पंक्ति उत्पन्न करता हूं n। उदाहरण के लिए, जब n=2, यह एक सरणी लंबाई 2 n + 1 उत्पन्न करेगा , जहां प्रत्येक पंक्ति लंबाई 2n-1 है। यह इस तरह दिखेगा [[0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]]:।
  2. फिर, उन संभावित शुरुआती पंक्तियों में से प्रत्येक के लिए, मैं इसे nबार-बार घुमाता हूं और nउपयुक्त मैट्रिक्स उत्पन्न करने के लिए पहले आइटम को स्लाइस करता हूं , और scipyअधिकतम मूल्य का ट्रैक रखते हुए, निर्धारक की गणना करने के लिए उपयोग करता हूं । इसके अंत में, मैं केवल n1 से अधिकतम, वेतन वृद्धि का प्रिंट आउट लेता हूं , और 10 मिनट बीतने तक जारी रखता हूं ।

इसे चलाने के लिए, आपको स्कैपी स्थापित करने की आवश्यकता होगी ।

संपादित करें 1: इसके बजाय itertools.product का उपयोग करके प्रारंभिक पंक्तियों को कैसे बनाया गया, धन्यवाद Sp3000!

संपादित करें 2: गति में न्यूनतम सुधार के लिए संभावित शुरुआती पंक्तियों को हटा दिया गया।

संपादित करें 3: scipyकैसे detकाम किया है पर अधिक नियंत्रण रखने के लिए बदल दिया है ।

from scipy import linalg
from collections import deque
from time import time
from itertools import product

c=1
t=time()
while 1:
    m=0
    for d in product(range(2),repeat=2*c-1):
        a=deque(d)
        l=[d[0:c]]
        for x in xrange(c-1):
            a.rotate(1)
            l+=[list(a)[0:c]]
        m=max(m,linalg.det(l,overwrite_a=True,check_finite=False))
    print m,'in',time()-t,'s'
    c+=1

यहाँ मेरे होम मशीन पर कुछ नमूना आउटपुट (i7-4510U, 8GB RAM) है:

1.0 in 0.0460000038147 s
1.0 in 0.0520000457764 s
2.0 in 0.0579998493195 s
3.0 in 0.0659999847412 s
5.0 in 0.0829999446869 s
9.0 in 0.134999990463 s
32.0 in 0.362999916077 s
56.0 in 1.28399991989 s
125.0 in 5.34999990463 s
315.0 in 27.6089999676 s
1458.0 in 117.513000011 s

धन्यवाद, लेकिन मुझे लगता है कि आपने उस प्रश्न के एक पुराने संस्करण का उत्तर दिया है जिससे मैं डरता हूं। यह अब टोप्लेट्ज़ मैट्रिसेस के बारे में है और समय सीमा 2 मिनट है।

4
मैं इस साइट पर इतने गोल्फ वाले देखता हूं कि मैं अक्सर भूल जाता हूं कि सामान्य उद्देश्यों के लिए यह वास्तव में एक पठनीय भाषा है।
एलेक्स ए।

यह संभवत: काफी बढ़ाया जा सकता है, क्योंकि यह इस तथ्य का लाभ नहीं उठाता है कि यह एक द्विआधारी मैट्रिक्स है।
lirtosiast

@ThomasKwa अगर मैं ईमानदार हूं, मुझे नहीं पता कि इसका लाभ कैसे उठाया जाए: P
Kade

संख्यात्मक दस्तावेज के उद्धरण: "निर्धारक को LAPACK दिनचर्या z / dgetff का उपयोग करके LU कारक के माध्यम से गणना की जाती है।" मैंने dgetrf को देखा, और यह कहता है कि यह दोहरी सटीकता का उपयोग करता है; ओपी के GPU के आधार पर एकल परिशुद्धता तेज हो सकती है।
lirtosiast

4

सी ++

ट्रांसपोटेड मैट्रिसेस के लिए निर्धारक के मूल्यांकन से बचने के लिए समानांतर और सरल अनुकूलन के लिए ओपनएमपी के उपयोग के साथ Bruteforce।

$ lscpu
...
Model name:            Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz
...
$ g++ -O2 toepl.cpp -fopenmp
$ timeout 2m ./a.out 
1 1
2 1
3 2
4 3
5 5
6 9
7 32
8 56
9 125
10 315
11 1458
12 2673
13 8118
14 22386
#include <cmath>

#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

void updateReverses(vector < int > & reverses) {
  int reversesCnt = reverses.size();
  for(int i = 0; i < reversesCnt; ++i){
    reverses[i] <<= 1;
    reverses.push_back(reverses[i] | 1);
  }
}

const double eps = 1e-9;

double determinant(vector < vector < double > > & matrix) {
  int n = matrix.size();
  double det = 1;
  if(n == 1) return matrix[0][0];
  for(int i = 0; i < n; ++i){
    int p = i;
    for(int j = i + 1; j < n; ++j)
      if(fabs(matrix[j][i]) > fabs(matrix[p][i]))
        p = j;
    if(fabs(matrix[p][i]) < eps)
      return 0;
    matrix[i].swap(matrix[p]);
    if(i != p) det *= -1;
    det *= matrix[i][i];
    matrix[i][i] = 1. / matrix[i][i];
    for(int j = i + 1; j < n; ++j)
      matrix[i][j] *= matrix[i][i];
    for(int j = i + 1; j < n; ++j){
      if(fabs(matrix[j][i]) < eps) continue;
      for(int k = i + 1; k < n; ++k)
        matrix[j][k] -= matrix[i][k] * matrix[j][i];
    }
  }
  return det;
}

int main() {
  vector < int > reverses(1, 0);
  reverses.reserve(1 << 30);
  updateReverses(reverses);
  for(int n = 1;; ++n){
    double res = 0;
    int topMask = 1 << (2 * n - 1);
    vector < vector < double > > matrix(n, vector < double > (n));
#pragma omp parallel for reduction(max:res) firstprivate(matrix) schedule(dynamic,1<<10)
    for(int mask = 0; mask < topMask; ++mask){
      if(mask < reverses[mask]) continue;
      for(int i = 0; i < n; ++i)
        for(int j = 0; j < n; ++j)
          matrix[i][j] = (mask >> (i - j + n - 1)) & 1;
      res = max(res, determinant(matrix));
    }
    cout << n << ' ' << res << endl;
    updateReverses(reverses);
    updateReverses(reverses);
  }
}

ऐसा लगता है कि आप जल्द ही अपनी पहली OEIS एंट्री कर रहे हैं जब तक कि कोई व्यक्ति एक चालाक विचार के साथ नहीं आता है :)

2

सी

संकलन:

$ clang -Ofast 52851.c -o 52851

साथ दौड़ो:

$ ./52851

n = 1..10मेरे कंप्यूटर पर ~ 115 सेकंड के लिए अधिकतम निर्धारक आउटपुट कर सकता है ।

कार्यक्रम सिर्फ आकार के हर संभव बाइनरी टोप्लेट्ज़ मैट्रिक्स के निर्धारक को प्राप्त कर रहा है n, हालांकि आकार 5x5या छोटे के प्रत्येक निर्धारक को संस्मरण का उपयोग करके कैश किया जाएगा।

पहले तो मैंने गलत तरीके से यह मान लिया था कि टोप्लेट्ज़ मैट्रिक्स का हर सबमेट्रिक्स भी एक टोप्लेट्ज़ मैट्रिक्स होगा, इसलिए मुझे केवल प्रत्येक 2^(2n-1)के 2^(n^2)लिए मूल्यों को याद करने की आवश्यकता थी n। मैंने अपनी गलती का एहसास करने से पहले कार्यक्रम बनाया, इसलिए यह सबमिशन उस कार्यक्रम का सिर्फ एक हल है।


#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <limits.h>
#include <string.h>

#define ELEMENTS(x) (sizeof(x) / sizeof(*x))

int *dets[6];

void print_matrix(int n, int c) {
    for(int row = 0; row < n; row++) {
        for(int col = 0; col < n; col++) {
            int j = n - 1 - row + col;
            int val = !!(c & (1 << j));
            printf("%d ", val);
        }
        puts("");
    }
}

int det(int n, uint8_t *m) {
    if(n == 1) {
        return m[0];
    }

    int i = 0;

    if(n < ELEMENTS(dets)) {
        for(int j = 0; j < n * n; j++) {
            i *= 2;
            i += m[j];
        }

        int v = dets[n][i];
        if(v != INT_MIN) {
            return v;
        }
    }

    int v = 0;

    uint8_t *sub = malloc((n - 1) * (n - 1));

    for(int removed = 0; removed < n; removed++) {
        if(m[removed]) {
            uint8_t *p = sub;
            for(int row = 1; row < n; row++) {
                for(int col = 0; col < n; col++) {
                    if(col == removed) {
                        continue;
                    }

                    *p = m[col + row * n];

                    p++;
                }
            }

            v += (removed % 2 == 0? 1: -1) * det(n - 1, sub);
        }
    }

    free(sub);

    if(n < ELEMENTS(dets)) {
        dets[n][i] = v;
    }
    return v;
}

int main(void) {
    for(int i = 2; i < ELEMENTS(dets); i++) {
        int combinations = 1 << (i * i);
        dets[i] = malloc(combinations * sizeof(**dets));
        for(int j = 0; j < combinations; j++) {
            dets[i][j] = INT_MIN;
        }
    }

    puts("1: 1");

    for(int n = 2; n < 65; n++) {
        int vars = 2 * n - 1;
        size_t combinations = 1 << vars;

        int best = -1;
        int max = -1;

        uint8_t *sub = malloc((n - 1) * (n - 1));

        for(int c = 0; c < combinations; c++) {
            int d = 0;
            for(int i = 0; i < n; i++) {
                if(c & (1 << (n - 1 + i))) {
                    uint8_t *p = sub;
                    for(int row = 1; row < n; row++) {
                        for(int col = 0; col < n; col++) {
                            if(col == i) {
                                continue;
                            }

                            int j = n - 1 - row + col;
                            *p = !!(c & (1 << j));

                            p++;
                        }
                    }
                    d += (i % 2 == 0? 1: -1) * det(n - 1, sub);
                }
            }

            if(d > max) {
                max = d;
                best = c;
            }
        }

        free(sub);

        printf("%d: %d\n", n, max);
        //print_matrix(n, best);
    }

    return 0;
}

ऐसा लगता है कि आप नाबालिगों द्वारा विस्तार का उपयोग करके निर्धारक की गणना कर रहे हैं; इसमें O(n!)जटिलता है, इसलिए आप एक अलग एल्गोरिथ्म का उपयोग करके बेहतर हो सकते हैं।
lirtosiast

@ThomasKwa मुझे नहीं पता था कि तेज एल्गोरिदम थे, इसलिए हाँ यह समाधान बहुत बुरा है।
टायरो

आप मैट्रिक्स के निर्धारक को खोजने के लिए LU Decomposition का उपयोग करना चाहते हैं । यह O(n^3)मेरा मानना ​​है, हालांकि कुछ दिलचस्प एल्गोरिदम के साथ तेजी से बनाया जा सकता है। मेरा मानना ​​है कि आमतौर पर यहां बनाए गए अधिकांश बांध निर्धारकों का प्रदर्शन करने के लिए विघटन के एक संस्करण का उपयोग करते हैं।
ब्रेनसैट

@BrainSteel, हाँ, मैंने इसे देखा, लेकिन O(n^2)अगर मैं अपना उत्तर अपडेट कर रहा हूं तो मैं एक एल्गोरिथ्म के लिए भी जा सकता हूं।
टायरो

एक आकस्मिक विकिपीडिया खोज के अनुसार, एक टोप्लेट्ज़ मैट्रिक्स का निर्धारक निर्धारित किया जा सकता है O(n^2)। लेकिन मुझे लगता है कि समस्या की अड़चनें मेट्रिसेस द्वारा O(4^n)कई 0-1 के बीच खोज की जा रही हैं । nn
लीजेंड्रे

2

आर

आपको R और संकुल सूचीबद्ध करने होंगे install.packages("package_name")

इस संस्करण के साथ मेरी मशीन पर 2 मिनट से कम नहीं हुआ (मुझे एक समानांतर संशोधन के साथ प्रयास करना है)

library(pracma)
library(stringr)
library(R.utils)
library(microbenchmark)

f <- function(n) {
  #If n is 1, return 1 to avoid code complexity on this special case
  if(n==1) { return(1) }
  # Generate matrices and get their determinants
  dets <- sapply(strsplit(intToBin( 0:(2^n - 1)), ""), function(x) {
              sapply( strsplit( intToBin( 0:(2^(n-1) - 1) ), ""), 
                    function(y) { 
                      det(Toeplitz(x,c(x[1],y))) 
                    })

              })
  #Get the maximum determinant and return it
  res <- max(abs(dets))
  return(res)
}

कॉल और आउटपुट:

> sapply(1:10,f)
 [1]   1   1   2   3   5   9  32  56 125 315

मेरी मशीन पर बेंचमार्क:

> microbenchmark(sapply(1:10,f),times=1L)
Unit: seconds
            expr      min       lq     mean   median       uq      max neval
 sapply(1:10, f) 66.35315 66.35315 66.35315 66.35315 66.35315 66.35315     1

जानकारी के लिए, 1:11 रेंज के लिए, 285 सेकंड लगते हैं।


1

PARI / जीपी, एन = 11

यह क्रूर बल है लेकिन इसका फायदा उठा रहा है det(A^T) = det(A)। मैं केवल यह प्रदर्शित करने के लिए पोस्ट कर रहा हूं कि ट्रांसपोज़ को छोड़ना कितना आसान है। सबसे छोटी बिट b1शीर्ष बाएं सेल रखती है, और बाकी बिट्स शीर्ष पंक्ति के बाकी हिस्से को रखती हैं। b2बायाँ स्तंभ शेष है। हम बस लागू करते हैं b2 <= (b1>>1)

{ for(n=1,11,
    res=0;
    for(b1=0,2^n-1,
      for(b2=0,b1>>1,
        res=max(res,matdet(matrix(n,n,i,j,bittest(if(i>j,b2>>(i-j-1),b1>>(j-i)),0))));
      )
    );
    print(n" "res);
  )
}

O(n^2)समय में Toeplitz निर्धारकों की गणना के बारे में : अपने सीमित शोध में, मैंने एक आवश्यकता में भाग लिया है कि सभी प्रमुख प्रधान नाबालिगों को काम करने के लिए एल्गोरिदम के लिए नॉनज़रो होना चाहिए, जो इस कार्य के लिए एक बड़ी बाधा है। यदि आप मुझे इस बारे में अधिक जानते हैं तो मुझे संकेत देने के लिए स्वतंत्र महसूस करें।


क्या आपने यह पेपर देखा? scienpress.com/upload/JAMB/Vol%201_1_4.pdf । यह मेरे लिए स्पष्ट नहीं था कि जटिलता क्या है। वहाँ n = 5 उदाहरण के लिए काफी शब्द थे।
रेटो कोराडी

@RetoKoradi हां मैंने देखा है। ऐसा लगता है कि जटिलता बहुपद नहीं है, यह देखते हुए कि उदाहरण e_{k+1}के लिए घटकों की संख्या 4 गुना है e_k। पेपर में कई चूक हैं। एक उल्टे मैट्रिक्स में एक एलयू अपघटन होता है यदि सभी प्रमुख प्रमुख नाबालिग गैर-शून्य होते हैं। (हर को नोटिस करें, उदाहरण के लिए a_0- स्पष्ट रूप से उन्हें नॉनज़रो होने की गारंटी दी गई है।) अद्वितीयता एल जा रहा है इकाई त्रिकोणीय। लेखक ने संख्यात्मक स्थिरता का भी उल्लेख नहीं किया है। यदि लिंक अनुपलब्ध हो जाता है, तो हुसैन-चू ली (2011) द्वारा पेपर "टोलपिट्ज मैट्रिसेस के निर्धारकों की गणना पर" है।
मिच श्वार्ट्ज
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.