প্রতিটি আকারের টোপলিটজ ম্যাট্রিক্সের সর্বাধিক নির্ধারক সন্ধান করুন


14

একটি স্থির এন এর জন্য এন বাই এন টোপলিটজ ম্যাট্রিকেসের সাথে 0 বা 1 এর সাথে এনট্রি বিবেচনা করুন To

কার্য

প্রত্যেকের জন্য n1 ঊর্ধ্বমুখী থেকে আউটপুট এন Toeplitz সকল এন উপর সর্বাধিক নির্ধারক এন্ট্রি যা হয় হয় 0 বা 1. এক আউটপুট প্রতি থাকা উচিত সঙ্গে ম্যাট্রিক্স nসর্বোচ্চ নির্ধারক এবং একটি উদাহরণ ম্যাট্রিক্স যে পৌছানোর এটা থাকা উচিত।

স্কোর

আপনার স্কোরটি nআমার কম্পিউটারে 2 মিনিটের মধ্যে আপনার কোডটি সবচেয়ে বড়। কিছুটা স্পষ্ট করার জন্য, আপনার কোডটি মোট 2 মিনিটের জন্য চলতে পারে, এটি প্রতি 2 মিনিট নয় n

টাইব্রেকার

যদি দুটি এন্ট্রি একই nস্কোর পায় তবে বিজয়ী এন্ট্রিটি nআমার মেশিনের সবচেয়ে কম সময়ে সবচেয়ে বেশি হবে । যদি দুটি সেরা এন্ট্রিও এই মানদণ্ডে সমান হয় তবে বিজয়ীর উত্তর আগে জমা দেওয়া হবে।

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

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

আমার মেশিনের সময়গুলি আমার মেশিনে চালিত হবে। এটি একটি এএমডি এফএক্স-8350 এইট-কোর প্রসেসরে একটি স্ট্যান্ডার্ড উবুন্টু ইনস্টল। এর অর্থ হল আপনার কোডটি চালাতে আমার সক্ষম হওয়া দরকার।

ছোট উত্তর

এন = 1..10 এর জন্য আউটপুটগুলি 1,1,2,3,5,9,32,56,125,315 হওয়া উচিত

এই ক্রমটি ওআইআইএসে নেই এবং তাই বিজয়ী এন্ট্রিও সেখানে একটি নতুন প্রবেশের প্রস্তাব দিতে পারে।

এখনও পর্যন্ত এন্ট্রি

  • n=10 n=11পাইথনে ভিওজ দ্বারা
  • n=9মধ্যে Tyilo দ্বারা সি
  • n=12জে লেজেন্ড্রে লিখেছেন
  • n=10আর তেঁশিবাই লিখেছেন
  • n=14C ++ এ স্টিলরভেন দ্বারা
  • n=14সি ++ এ রেটোকোরাদি লিখেছেন

@AlexA। আপনি ঠিক বলেছেন এবং আমি ক্ষমা চেয়েছি। ভাগ্যক্রমে দুটি সমস্যা খুব একই রকম তাই তার নিজের কোডটি সহজেই সংশোধন করতে সক্ষম হওয়া উচিত।

@ ভিওজের সমাধানটি একটি ক্রম নিয়ে আসে যা 1, 1, 2, 3, 5, 9, 32 দিয়ে শুরু হয় So সুতরাং এন = 5 এর মান আপনি তালিকাভুক্ত থেকে পৃথক। যেহেতু অন্যান্য সমস্ত মান মিলেছে, দেখে মনে হচ্ছে সমাধানটি সম্ভবত সঠিক, এবং এটি প্রশ্নের মধ্যে কেবল একটি টাইপ?
রেটো কোরাাদি

@ রিটোকোরাদি আপনাকে ধন্যবাদ সংশোধন করা হয়েছে।

এখানে সর্বাধিক নির্ধারক সহ সম্ভাব্য 10 টি বাইনারি টোপলিটজ ম্যাট্রিকেস রয়েছে n = 1..10: ঘোস্টবিন.com
পাস্ত

2
এমন একটি পর্যবেক্ষণ হিসাবে যা অন্যকে সহায়তা করতে পারে তবে আমি ১৪-এর চেয়ে বেশি যাচাই করতে পারি না row এটি শীর্ষ সারিটির যথাযথ উপায় এবং টোপলিটজ ম্যাট্রিক্সের প্রথম কলামটি সর্বদা সর্বোচ্চ নির্ধারকের জন্য 0.4 <= মি <= 0.6 হয়।
মিকিটি

উত্তর:


3

সি ++ পাইথ্রেড সহ

আমার মেশিনে 1 মিনিটের নিচে এটি n = 14 এ যায়। তবে যেহেতু এটি কেবলমাত্র একটি 2-কোর ল্যাপটপ, আমি আশা করি 8-কোর টেস্ট মেশিনটি 2 মিনিটের মধ্যে n = 15 শেষ করতে পারে। এটি আমার মেশিনে প্রায় 4:20 মিনিট সময় নেয়।

আমি সত্যিই আরও দক্ষ কিছু নিয়ে আসার আশা করছিলাম। সেখানে আছে পেয়েছিলাম আরো দক্ষতার সঙ্গে একটি বাইনারি ম্যাট্রিক্স নির্ধারিত নিরূপণ করা একটি উপায় হতে হবে। আমি এমন কিছু গতিশীল প্রোগ্রামিং পদ্ধতির সাথে আসতে চেয়েছিলাম যা নির্ধারক গণনায় +1 এবং -1 পদগুলিকে গণনা করে। তবে এটি এখনও পর্যন্ত একসাথে আসে নি।

যেহেতু অনুগ্রহের মেয়াদ শেষ হতে চলেছে, তাই আমি স্ট্যান্ডার্ড ব্রুট ফোর্স পদ্ধতির প্রয়োগ করেছি:

  • সমস্ত সম্ভাব্য টোপলিটজ ম্যাট্রিক্সের উপর লুপ করুন।
  • প্রতি পরিবহিত ম্যাট্রিক্স জুটিতে দু'এর একটিতে যান ip যেহেতু ম্যাট্রিক্স বিটমাস্ক মান দ্বারা বর্ণিত, তাই বিটমাস্কের বিপরীত বিটমাস্কের চেয়ে ছোট যেখানে সমস্ত মানগুলি এড়িয়ে যাওয়া সহজ।
  • নির্ধারণটি একটি পাঠ্য বইয়ের সাথে গণনা করা হয় LR পচন। কিছু অল্প পারফরম্যান্স টিউনিং বাদে, আমার কলেজের সংখ্যা সংক্রান্ত পদ্ধতি বই থেকে অ্যালগরিদমে আমি যে প্রধান উন্নতি করেছি তা হ'ল আমি একটি সহজ পাইভট কৌশল ব্যবহার করি।
  • সমান্তরালকরণ 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;
}

কেবলমাত্র পূর্ণসংখ্যার গাণিতিক ব্যবহার করে পূর্ণসংখ্যার ম্যাট্রিক্সের নির্ধারক গণনা করার একটি আকর্ষণীয় উপায় রয়েছে: কিছু সীমাবদ্ধ ক্ষেত্রের মধ্যে LU পচন (মূলত একটি বড় প্রাইমকে মোড)। আমি জানি না এটি আরও দ্রুত হবে কিনা।
lirtosiast

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

1
@ ল্যাম্বিক আমি চেষ্টা করব এবং আজকের পরে এটি একবার দেখব। গতকাল আপনার অন্যান্য সম্পর্কিত চ্যালেঞ্জের জন্য বৃহত্তর আকারগুলি হ্যান্ডেল করতে আমি এটি পরিবর্তন করেছি। এখন পর্যন্ত n = 30 এর জন্য সর্বোচ্চ স্কোরকে পরাভূত করতে পারেনি, আমার হিউরিস্টিকস 5 * 10 ^ 13 এর নিচে আটকে আছে।
রেটো কোরাাদি

1
@ ল্যাম্বিক কোডের জন্য পেস্ট.বুন্টু. com/ 11915546 এবং এন = 19-এর ফলাফলের জন্য পেস্ট.বুন্টু. com/ 11915532 দেখুন ।
রেটো কোরাডি

1
@ ল্যাম্বিক এন -২০ পর্যন্ত ফলাফল পেস্ট.বুন্টু . com/11949738রয়েছে । তারা এখন ত্রিভুজটির মান এবং সেগুলি বিজ্ঞপ্তি কিনা তাড়াতাড়ি দেখার জন্য গুণাবলী সহ সমস্ত বদ্ধ সমাধানের তালিকা করে। এম = 18,19,20 এর ম্যাক্সিমার সমস্তগুলি সার্কুল্যান্ট ম্যাট্রিক্স। নির্ধারকরা কোথাও প্রকাশের আগে দয়া করে সেগুলি দুটিবার পরীক্ষা করে দেখুন।
রেটো কোরাাদি

8

জে

আপডেট: অর্ধেকের বেশি মান সন্ধানের জন্য উন্নত কোড। এখন n=12120 সেকেন্ডের মধ্যে আরামে গণনা করুন (217s থেকে 60 এর দশকে)।

আপনার জে ইনস্টলের সর্বশেষতম সংস্করণ প্রয়োজন need

#!/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''

এটি চালান এবং দুই মিনিট সময় শেষ হলে হত্যা করুন। আমার ফলাফল (এমবিপি ২০১৪ - ১GB গিগাবাইট র‌্যাম):

┌────┬─┬─────────────┬─┐
│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.83s।


শুধুই মজার জন্য

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

এটি নিজের থেকে প্রায় 210 সেকেন্ড সময় নিয়েছিল।


1
পরীক্ষকদের জন্য নোট: n = 12প্রায় 18 গিগাবাইট মেমরির প্রয়োজন।
ডেনিস

এটি একটি খুব সুন্দর উন্নতি। আউটপুট তবে কিছুটা বগি। আমার জন্য j64-804 ব্যবহার করার জন্য এটি n = 1 কে দুইবার আউটপুট করে তাই এটি আরও একবারের জন্য বাইরে চলে যায়।

@ ললেবিক আহ ঠিক আছে আমি সবেমাত্র কোড আপডেট করেছি; আপনি আবার দৌড়াতে চেষ্টা করতে পারেন? ধন্যবাদ! (আমি এটি গণনা করতে সেট করেছিn=13 আপনি পরিবর্তন করতে পারেন। 13এটি আপ গণনা তোমরা যা ইচ্ছা আছে দ্বিতীয় টু গত লাইনে।)
লেজেন্ড্রে

আমি এটি আবার

@ লিম্বিক হুম .. আপনি কি বলছেন যে এটি সময়সীমার মধ্যে 12 হয়ে যায় এবং এর পরে কিছুটা সময় 13 হয়ে যায় (যা আমি প্রত্যাশা করি), বা এটি কখনই 13-এ আসে না (অর্থাৎ 12 এর পরে প্রোগ্রামটি থামবে)?
লেজেন্ড্রে

4

পাইথন 2

এটি একটি খুব সরল সমাধান, এবং সম্ভবত প্রতিযোগিতাটি জিতবে না। কিন্তু ওহে, এটা কাজ করে!

আমি ঠিক কী ঘটছে তার একটি তাত্ক্ষণিক পর্যালোচনা দেব।

  1. আমি প্রথম জন্য প্রতি সম্ভব শুরুর সারি উৎপন্ন n। উদাহরণস্বরূপ, কখন n=2, এটি একটি অ্যারের দৈর্ঘ্য 2 এন + 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, 8 জিবি র‌্যাম):

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

@ থমাসকওয়া আমি যদি সত্যবাদী হয়ে থাকি তবে কীভাবে সেটার সুবিধা নেব সে সম্পর্কে আমার কোনও ধারণা নেই: পি
কেড

ন্যালি ডকুমেন্টেশন থেকে উদ্ধৃতি: "LAPACK রুটিন z / dgetrf ব্যবহার করে LU ফ্যাক্টেরাইজেশনের মাধ্যমে নির্ধারকটি গণনা করা হয়।" আমি dgetrf তাকালাম, এবং এটিতে এটি ডাবল নির্ভুলতা ব্যবহার করে; ওপির জিপিইউর উপর নির্ভর করে একক নির্ভুলতা দ্রুততর হতে পারে।
লিটারোসিয়াসট

4

সি ++

ট্রান্সপোজড ম্যাট্রিক্সের জন্য নির্ধারকের মূল্যায়ন এড়াতে সমান্তরালকরণ এবং সাধারণ অপ্টিমাইজেশনের জন্য ওপেনএমপি ব্যবহারের সাথে ব্রুটফোর্স।

$ 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);
  }
}

দেখে মনে হচ্ছে আপনি খুব শীঘ্রই আপনার প্রথম ওএআইএস এন্ট্রি করে

2

সি

এর সাথে সংকলন:

$ clang -Ofast 52851.c -o 52851

সাথে চালান:

$ ./52851

এর জন্য সর্বোচ্চ নির্ধারক আউটপুট করতে পারে Can n = 1..10আমার কম্পিউটারে 115 সেকেন্ডের ।

প্রোগ্রামটি কেবলমাত্র আকারের প্রতিটি বাইনারি টোপলিটজ ম্যাট্রিক্স নির্ধারণকারীকে পেয়েছে n, তবে আকারের ম্যাট্রিক্সের প্রতিটি নির্ধারক5x5 বা তার চেয়ে কম মেমোয়েজেশন ব্যবহার করে ক্যাশে হবে।

প্রথম আমি ভুলভাবে অধিকৃত যে একটি Toeplitz ম্যাট্রিক্স প্রতিটি submatrix এছাড়াও, একটি Toeplitz ম্যাট্রিক্স করা হবে যাতে আমি শুধুমাত্র memoize করা প্রয়োজন 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

@ থমাসকওয়া আমি জানতাম না যে এখানে দ্রুত অ্যালগরিদম রয়েছে, সুতরাং হ্যাঁ এই সমাধানটি বেশ খারাপ।
টাইলো

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

@ ব্রেনস্টিল, হ্যাঁ আমি এটির দিকে তাকিয়েছিলাম, তবে আমি O(n^2)আমার উত্তরটি আপডেট করে দিলে আমিও সম্ভবত একটি অ্যালগরিদমের জন্য যেতে পারি।
টাইলো

একটি নৈমিত্তিক উইকিপিডিয়া অনুসন্ধান অনুসারে, টোপলিটজ ম্যাট্রিক্সের নির্ধারকটি নির্ধারণ করা যেতে পারে O(n^2)। তবে আমি মনে করি সমস্যার অস্তিত্ব O(4^n)মেট্রিক nদ্বারা 0-1-এর মধ্যে অনেকগুলি অনুসন্ধান করছে n
লেজেন্ড্রে

2

আর

আপনাকে আর এবং তালিকাভুক্ত প্যাকেজগুলি ইনস্টল করতে হবে 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

প্যারি / জিপি, এন = ১১

এটি নিষ্ঠুর শক্তি কিন্তু সুবিধা গ্রহণ করা 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)সময়মতো টোপলিটজ নির্ধারণকারীদের গণনা সম্পর্কে : আমার সীমিত গবেষণায়, আমি অ্যালগরিদমগুলিকে কাজ করার জন্য সমস্ত প্রিন্সিপাল প্রিন্সিপাল নাবালককে অবশ্যই ননজারো হওয়া দরকার, যা এই কাজের জন্য একটি বড় বাধা। আপনি যদি আমার চেয়ে এই বিষয়ে আরও কিছু জানেন তবে নির্দ্বিধায় আমাকে পয়েন্টার দিন।


আপনি এই কাগজটি দেখেছেন? scienpress.com/upload/JAMB/Vol%201_1_4.pdf । জটিলতাটি কী তা আমার কাছে পরিষ্কার ছিল না। এন = 5 উদাহরণের জন্য বেশ কয়েকটি পদ রয়েছে বলে মনে হয়েছিল।
রেটো কোরাাদি

@ রিটোকোরাডি হ্যাঁ আমি এটি দেখেছি। দেখে মনে হচ্ছে জটিলতা বহুবচনের নয়, উদাহরণস্বরূপ বিবেচনা করে যে e_{k+1}উপাদানগুলির সংখ্যার হিসাবে 4 গুণ বেশি রয়েছে e_k। কাগজে অনেক বাদ পড়েছে। যদি সমস্ত শীর্ষস্থানীয় নাবালিকা নাজনরো হয় তবে একটি ইনভার্ভেবল ম্যাট্রিক্সের একটি এলইউর পচন থাকে। (বিভাজনগুলি লক্ষ্য করুন, উদাহরণস্বরূপ a_0- স্পষ্টতই তারা ননজারো হওয়ার গ্যারান্টিযুক্ত)) স্বতন্ত্রতা এল ইউনিট ত্রিভুজাকৃতির থেকে আসে। লেখক সংখ্যার স্থায়িত্বের কথাও উল্লেখ করেননি। লিঙ্কটি অনুপলভ্য হয়ে উঠলে, কাগজটি হুয়ান-চু লি (২০১১) দ্বারা "টোপলিটজ ম্যাট্রিক্সের নির্ধারণকারীদের হিসাবের অন" is
মিচ শোয়ার্টজ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.