যত তাড়াতাড়ি সম্ভব হাফনিয়ান গণনা করুন


12

চ্যালেঞ্জটি হ'ল ম্যাট্রিক্সের হাফনিয়ান গণনার জন্য দ্রুততম কোডটি লিখতে হবে ।

একটি প্রতিসম 2n- 2nম্যাট্রিক্সের হাফনিয়ান Aহিসাবে সংজ্ঞায়িত করা হয়:

এখানে S 2n থেকে পূর্ণসংখ্যার সব একাধিক বিন্যাসন সেট প্রতিনিধিত্ব করে 1করতে 2nহলো, [1, 2n]

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

একটি দ্রুত অ্যালগরিদম আছে তবে এটি বোঝা শক্ত বলে মনে হচ্ছে। এবং খ্রিস্টান সিভারস হলেন এটি প্রথম প্রয়োগ করেছিলেন (হাস্কেলের মধ্যে)।

এই প্রশ্নের ম্যাট্রিকগুলি সমস্ত মাত্রা সহ বর্গক্ষেত্র এবং প্রতিসম হয়।

রেফারেন্স বাস্তবায়ন (নোট করুন এটি সবচেয়ে ধীরতম পদ্ধতিটি ব্যবহার করছে)।

মিঃ এক্সকোডারের কাছ থেকে পাইথন কোডের কয়েকটি উদাহরণ এখানে।

from itertools import permutations
from math import factorial

def hafnian(matrix):
    my_sum = 0
    n = len(matrix) // 2
    for sigma in permutations(range(n*2)):
        prod = 1
        for j in range(n):
            prod *= matrix[sigma[2*j]][sigma[2*j+1]]
        my_sum += prod
    return my_sum / (factorial(n) * 2 ** n)

print(hafnian([[-1, 1, 1, -1, 0, 0, 1, -1], [1, 0, 1, 0, -1, 0, -1, -1], [1, 1, -1, 1, -1, -1, 0, -1], [-1, 0, 1, -1, -1, 1, -1, 0], [0, -1, -1, -1, -1, 0, 0, -1], [0, 0, -1, 1, 0, 0, 1, 1], [1, -1, 0, -1, 0, 1, 1, 0], [-1, -1, -1, 0, -1, 1, 0, 1]]))
4

M = [[1, 1, 0, 0, 0, 0, 0, 1, 0, 0], [1, 1, -1, 0, -1, 1, 1, 1, 0, -1], [0, -1, -1, -1, 0, -1, -1, 0, -1, 1], [0, 0, -1, 1, -1, 1, -1, 0, 1, -1], [0, -1, 0, -1, -1, -1, -1, 1, -1, 1], [0, 1, -1, 1, -1, 1, -1, -1, 1, -1], [0, 1, -1, -1, -1, -1, 1, 0, 0, 0], [1, 1, 0, 0, 1, -1, 0, 1, 1, -1], [0, 0, -1, 1, -1, 1, 0, 1, 1, 1], [0, -1, 1, -1, 1, -1, 0, -1, 1, 1]]

print(hafnian(M))
-13

M = [[-1, 0, -1, -1, 0, -1, 0, 1, -1, 0, 0, 0], [0, 0, 0, 0, 0, -1, 0, 1, -1, -1, -1, -1], [-1, 0, 0, 1, 0, 0, 0, 1, -1, 1, -1, 0], [-1, 0, 1, -1, 1, -1, -1, -1, 0, -1, -1, -1], [0, 0, 0, 1, 0, 0, 0, 0, 0, 1, -1, 0], [-1, -1, 0, -1, 0, 0, 1, 1, 1, 1, 1, 0], [0, 0, 0, -1, 0, 1, 1, -1, -1, 0, 1, 0], [1, 1, 1, -1, 0, 1, -1, 1, -1, -1, -1, -1], [-1, -1, -1, 0, 0, 1, -1, -1, -1, 1, -1, 0], [0, -1, 1, -1, 1, 1, 0, -1, 1, -1, 1, 1], [0, -1, -1, -1, -1, 1, 1, -1, -1, 1, 0, -1], [0, -1, 0, -1, 0, 0, 0, -1, 0, 1, -1, 1]]

print(hafnian(M))
13

M = [[-1, 1, 0, 1, 0, -1, 0, 0, -1, 1, -1, 1, 0, -1], [1, -1, 1, -1, 1, 1, -1, 0, -1, 1, 1, 0, 0, -1], [0, 1, 1, 1, -1, 1, -1, -1, 0, 0, -1, 0, -1, -1], [1, -1, 1, -1, 1, 0, 1, 1, -1, -1, 0, 0, 1, 1], [0, 1, -1, 1, 0, 1, 0, 1, -1, -1, 1, 1, 0, -1], [-1, 1, 1, 0, 1, 1, -1, 0, 1, -1, -1, -1, 1, -1], [0, -1, -1, 1, 0, -1, -1, -1, 0, 1, -1, 0, 1, -1], [0, 0, -1, 1, 1, 0, -1, 0, 0, -1, 0, 0, 0, 1], [-1, -1, 0, -1, -1, 1, 0, 0, 1, 1, 0, 1, -1, 0], [1, 1, 0, -1, -1, -1, 1, -1, 1, 1, 1, 0, 1, 0], [-1, 1, -1, 0, 1, -1, -1, 0, 0, 1, -1, 0, -1, 0], [1, 0, 0, 0, 1, -1, 0, 0, 1, 0, 0, 1, 1, 1], [0, 0, -1, 1, 0, 1, 1, 0, -1, 1, -1, 1, 1, -1], [-1, -1, -1, 1, -1, -1, -1, 1, 0, 0, 0, 1, -1, -1]]

print(hafnian(M))
83

কাজটি

আপনার এমন কোড লিখতে হবে যা ম্যাট্রিক্সের 2nদ্বারা দেওয়া হয়েছে 2n, এটি তার হাফিয়ানিয়াকে আউটপুট করে।

যেহেতু আপনার কোডটি পরীক্ষা করার দরকার হবে এটি সহায়ক হবে যদি আপনি আমাকে আপনার কোডটিতে ইনপুট হিসাবে একটি ম্যাট্রিক্স দেওয়ার সহজ উপায় দিতে পারেন, উদাহরণস্বরূপ স্ট্যান্ডার্ড ইন থেকে পড়ে I আমি উপাদানগুলির সাথে এলোমেলোভাবে নির্বাচিত ম্যাট্রিকগুলিতে আপনার কোডটি পরীক্ষা করব {-1, 0, 1 from থেকে নির্বাচিত} এই জাতীয় পরীক্ষার উদ্দেশ্য হফনিয়ান একটি খুব বড় মান হ'ল সুযোগ হ্রাস করা।

আদর্শভাবে আপনার কোডটি মেট্রিক্সে ঠিক যেমন পড়তে সক্ষম হবে ঠিক তেমন স্ট্যান্ডার্ড থেকে এই প্রশ্নের উদাহরণগুলিতে। এটি ইনপুটটিকে [[1,-1],[-1,-1]]উদাহরণ হিসাবে দেখাবে । আপনি যদি অন্য ইনপুট ফর্ম্যাটটি ব্যবহার করতে চান তবে দয়া করে জিজ্ঞাসা করুন এবং আমি যথাসম্ভব চেষ্টা করব।

স্কোর এবং টাই

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

যদি দু'জন লোক একই স্কোর পায় তবে বিজয়ী হ'ল এটির মানটি সবচেয়ে দ্রুত n। সেগুলি যদি একে অপরের 1 সেকেন্ডের মধ্যে থাকে তবে এটি প্রথমে পোস্ট করা।

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

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

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

আরও ভাষায় উত্তরগুলির জন্য কল করুন

আপনার পছন্দসই সুপার ফাস্ট প্রোগ্রামিং ভাষায় উত্তর পাওয়া ভাল লাগবে। জিনিস শুরু করার জন্য, কীভাবে দুর্গ , নিম এবং মরিচা সম্পর্কে ?

লিডারবোর্ড

  • 52 মাইল মাইল সি ++ ব্যবহার করে । 30 সেকেন্ড.
  • 50 এনজিএন দ্বারা সি ব্যবহার করে । 50 সেকেন্ড
  • 46 খ্রিস্টান সিভর্স হাস্কেল ব্যবহার করে । 40 সেকেন্ড
  • পাইথন 2 + পিপি ব্যবহার করে মাইল 40 মাইল । 41 সেকেন্ড
  • পাইগন 3 + পিপি ব্যবহার করে এনএনজি দ্বারা 34 । 29 সেকেন্ড।
  • 28 পাইথন 3 ব্যবহার করে ডেনিস । 35 সেকেন্ড। (পাইপি ধীরে ধীরে)

ম্যাট্রিক্স এন্ট্রিগুলির নিখুঁত মানগুলির জন্য কোনও সীমা আছে? আমরা কি একটি ভাসমান পয়েন্ট আনুমানিক ফিরে আসতে পারি? আমাদের কি নির্বিচারে নির্ভুলতা পূর্ণসংখ্যার ব্যবহার করতে হবে?
ডেনিস

@ ডেনিস অনুশীলনে আমি কেবল পরীক্ষার জন্য -1,0,1 ব্যবহার করব (এলোমেলোভাবে নির্বাচিত)। আমি চাই না এটি একটি বৃহত্তর আন্ত চ্যালেঞ্জ হোক। সমস্ত সততার সাথে আমি জানি না যে কোডটি চালাতে খুব ধীর হয়ে যাওয়ার আগে আমরা bit৪ বিট ইনট সীমাবদ্ধ করব কিনা তবে আমার অনুমান যে আমরা তা করব না। বর্তমানে আমরা এর কাছাকাছি কোথাও নেই।

যদি এন্ট্রিগুলি -1,0,1 এর মধ্যে সীমাবদ্ধ থাকে তবে সে প্রশ্নের উপরে উল্লেখ করা উচিত। আমাদের কোড অন্যান্য ম্যাট্রিকের জন্য আদৌ কাজ করতে হবে?
ডেনিস

@ ডেনিস একটি পুরানো সংস্করণ এটি বলত তবে আমার অবশ্যই এটি লেখা উচিত। কোডটি যদি -1,0,1 এন্ট্রিগুলির জন্য বিশেষ না করা হত তবে আমি এটি পছন্দ করব তবে আমি মনে করি আমি এটি থামাতে পারছি না।

আপনার কি আরও পরীক্ষার কেস আছে? সম্ভবত বৃহত্তর এন জন্য ?
মাইল

উত্তর:


14

Haskell,

import Control.Parallel.Strategies
import qualified Data.Vector.Unboxed as V
import qualified Data.Vector as VB

type Poly = V.Vector Int

type Matrix = VB.Vector ( VB.Vector Poly )

constpoly :: Int -> Int -> Poly
constpoly n c = V.generate (n+1) (\i -> if i==0 then c else 0)

add :: Poly -> Poly -> Poly
add = V.zipWith (+)

shiftmult :: Poly -> Poly -> Poly
shiftmult a b = V.generate (V.length a) 
                           (\i -> sum [ a!j * b!(i-1-j) | j<-[0..i-1] ])
  where (!) = V.unsafeIndex

x :: Matrix -> Int -> Int -> Int -> Poly -> Int
x  _    0  _ m p = m * V.last p
x mat n c m p =
  let mat' = VB.generate (2*n-2) $ \i ->
             VB.generate i       $ \j ->
                 shiftmult (mat!(2*n-1)!i) (mat!(2*n-2)!j) `add`
                 shiftmult (mat!(2*n-1)!j) (mat!(2*n-2)!i) `add`
                 (mat!i!j)
      p' = p `add` shiftmult (mat!(2*n-1)!(2*n-2)) p
      (!) = VB.unsafeIndex
      r = if c>0 then parTuple2 rseq rseq else r0
      (a,b) = (x mat (n-1) (c-1) m p, x mat' (n-1) (c-1) (-m) p')
              `using` r
  in a+b

haf :: [[Int]] -> Int
haf m = let n=length m `div` 2
        in x (VB.fromList $ map (VB.fromList . map (constpoly n)) m) 
             n  5  ((-1)^n)  (constpoly n 1) 

main = getContents >>= print . haf . read

এটি আন্ড্রেয়াস জার্কলুন্ডের অ্যালগরিদম 2 এর একটি প্রকরণকে প্রয়োগ করে : রাইজারের মতো দ্রুত পারফেক্ট ম্যাচিংয়ের গণনা করে

ghcসংকলন সময় বিকল্পগুলি ব্যবহার করে সংকলন করুন -O3 -threadedএবং +RTS -Nসমান্তরালনের জন্য রান টাইম বিকল্পগুলি ব্যবহার করুন । স্টিডিন থেকে ইনপুট নেয়।


2
সম্ভবত যে নোট parallelএবং vectorইনস্টল করা আবশ্যক?
এইচ.পি.উইজ

@ এইচপিউইজ এখানে কেউ অভিযোগ করেনি , তবে নিশ্চিত, এটি লক্ষ্য করে ক্ষতি হবে না। ঠিক আছে, এখন আপনি করেছেন।
খ্রিস্টান সিভারস

@ খ্রিস্টিয়ানসিভার আমার কাছে মনে হয় না তারা অভিযোগ করছে। ওপিকে হাস্কেলের সাথে পরিচিত নাও হতে পারে, তাই কোডটি টাইম করতে সক্ষম হওয়ার জন্য কী ইনস্টল করতে হবে তা স্পষ্ট করে জানিয়ে দিন এটি একটি ভাল ধারণা।
ডেনিস

@ ডেনিস আমার অর্থ "আপনি অভিযোগ করেছিলেন" তা নয় তবে "আপনি এটি নোট করেছেন"। এবং আমি অভিযোগকে একটি নেতিবাচক জিনিস হিসাবে ভাবি নি। ওপি হ'ল আমি যে চ্যালেঞ্জের সাথে লিঙ্ক করেছি তার মতোই, তাই কোনও সমস্যা হওয়া উচিত নয়।
খ্রিস্টান সিভর্স

টিআইওতে 7.5 সেকেন্ডে এন = 40 ... মানুষ, এটি দ্রুত!
ডেনিস


6

সি ++ (জিসিসি)

#define T(x) ((x)*((x)-1)/2)
#define S 1
#define J (1<<S)
#define TYPE int

#include <iostream>
#include <vector>
#include <string>
#include <pthread.h>

using namespace std;

struct H {
    int s, w, t;
    TYPE *b, *g;
};

void *solve(void *a);
void hafnian(TYPE *b, int s, TYPE *g, int w, int t);

int n, m, ti = 0;
TYPE r[J] = {0};
pthread_t pool[J];

int main(void) {
    vector<int> a;
    string s;
    getline(cin, s);

    for (int i = 0; i < s.size(); i++)
        if (s[i] == '0' || s[i] == '1')
            a.push_back((s[i-1] == '-' ? -1 : 1)*(s[i] - '0'));

    for (n = 1; 4*n*n < a.size(); n++);
    m = n+1;

    TYPE z[T(2*n)*m] = {0}, g[m] = {0};

    for (int j = 1; j < 2*n; j++)
        for (int k = 0; k < j; k++)
            z[(T(j)+k)*m] = a[j*2*n+k];
    g[0] = 1;

    hafnian(z, 2*n, g, 1, -1);

    TYPE h = 0;
    for (int t = 0; t < ti; t++) {
        pthread_join(pool[t], NULL);
        h += r[t];
    }

    cout << h << endl;

    return 0;
}

void *solve(void *a) {
    H *p = reinterpret_cast<H*>(a);
    hafnian(p->b, p->s, p->g, p->w, p->t);
    delete[] p->b;
    delete[] p->g;
    delete p;
    return NULL;
}

void hafnian(TYPE *b, int s, TYPE *g, int w, int t) {
    if (t == -1 && (n < S || s/2 == n-S)) {
        H *p = new H;
        TYPE *c = new TYPE[T(s)*m], *e = new TYPE[m];
        copy(b, b+T(s)*m, c);
        copy(g, g+m, e);
        p->b = c;
        p->s = s;
        p->g = e;
        p->w = w;
        p->t = ti;
        pthread_create(pool+ti, NULL, solve, p);
        ti++;
    }
    else if (s > 0) {
        TYPE c[T(s-2)*m], e[m];
        copy(b, b+T(s-2)*m, c);
        hafnian(c, s-2, g, -w, t);
        copy(g, g+m, e);

        for (int u = 0; u < n; u++) {
            TYPE *d = e+u+1,
                  p = g[u], *x = b+(T(s)-1)*m;
            for (int v = 0; v < n-u; v++)
                d[v] += p*x[v];
        }

        for (int j = 1; j < s-2; j++)
            for (int k = 0; k < j; k++)
                for (int u = 0; u < n; u++) {
                    TYPE *d = c+(T(j)+k)*m+u+1,
                          p = b[(T(s-2)+j)*m+u], *x = b+(T(s-1)+k)*m,
                          q = b[(T(s-2)+k)*m+u], *y = b+(T(s-1)+j)*m;
                    for (int v = 0; v < n-u; v++)
                        d[v] += p*x[v] + q*y[v];
                }

        hafnian(c, s-2, e, w, t);
    }
    else
        r[t] += w*g[n];
}

এটি অনলাইন চেষ্টা করুন! (১৩ এর জন্য এন = ২৪)

আমার অন্যান্য পোস্টে পাইথন দ্রুত প্রয়োগের ভিত্তিতে । #define S 3আপনার 8-কোর মেশিনে দ্বিতীয় লাইনটি সম্পাদনা করুন এবং এর সাথে সংকলন করুন g++ -pthread -march=native -O2 -ftree-vectorize

অর্ধেক কাজকে বিভক্ত করে, তাই এর মান হওয়া Sউচিত log2(#threads)। ধরনের সহজে পরিবর্তন করা যাবে মধ্যে int, long, float, এবং doubleমান পরিবর্তন করে #define TYPE


এটি এ পর্যন্ত নেতৃস্থানীয় উত্তর। আপনার কোডটি ইনপুটটিতে নির্দিষ্টভাবে পড়েনি কারণ এটি স্পেসগুলি মোকাবেলা করতে পারে না। আমি যেমন করতে হয়েছিলtr -d \ < matrix52.txt > matrix52s.txt

@ ললেবিক দুঃখিত, এটি কেবল 24 মাপের ফাঁকাবিহীন ম্যাট্রিক্সের বিরুদ্ধে ব্যবহার করেছে used যদিও স্পেসগুলির সাথে কাজ করার জন্য এখন ঠিক করা হয়েছে।
মাইল

4

পাইথন ঘ

এটি হাফ (এ) কে একটি স্মৃতিকৃত সমষ্টি হিসাবে গণনা করে (এ [i] [জে] * হাফ (সারি এবং কর্স আই এবং জে ছাড়াই একটি))।

#!/usr/bin/env python3
import json,sys
a=json.loads(sys.stdin.read())
n=len(a)//2
b={0:1}
def haf(x):
 if x not in b:
  i=0
  while not x&(1<<i):i+=1
  x1=x&~(1<<i)
  b[x]=sum(a[i][j]*haf(x1&~(1<<j))for j in range(2*n)if x1&(1<<j)and a[i][j])
 return b[x]
print(haf((1<<2*n)-1))

3

সি

আরেকটি impl আন্দ্রিয়াস Björklund এর কাগজ , যা অনেক বুঝতে করেন তাহলে আপনি তাকান সহজ খ্রিস্টান Sievers এর মধ্যে Haskell কোড । পুনরাবৃত্তির প্রথম কয়েকটি স্তরের জন্য, এটি উপলব্ধ সিপিইউগুলিতে রাউন্ড-রবিন থ্রেড বিতরণ করে। পুনরাবৃত্তির শেষ স্তরটি যা আমন্ত্রণের অর্ধেক অংশ হিসাবে কাজ করে তা হাত দ্বারা অনুকূলিত হয়।

সঙ্গে কম্পাইল: gcc -O3 -pthread -march=native; 2x গতি বাড়ানোর জন্য @ ডেনিসকে ধন্যবাদ

টিআইওতে 24 এর মধ্যে n = 24

#define _GNU_SOURCE
#include<sched.h>
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
#include<unistd.h>
#include<pthread.h>
#define W while
#define R return
#define S static
#define U (1<<31)
#define T(i)((i)*((i)-1)/2)
typedef int I;typedef long L;typedef char C;typedef void V;
I n,ncpu,icpu;
S V f(I*x,I*y,I*z){I i=n,*z1=z+n;W(i){I s=0,*x2=x,*y2=y+--i;W(y2>=y)s+=*x2++**y2--;*z1--+=s;}}
typedef struct{I m;V*a;V*p;pthread_barrier_t*bar;I r;}A;S V*(h1)(V*);
I h(I m,I a[][n+1],I*p){
 m-=2;I i,j,k=0,u=T(m),v=u+m,b[u][n+1],q[n+1];
 if(!m){I*x=a[v+m],*y=p+n-1,s=0;W(y>=p)s-=*x++**y--;R s;}
 memcpy(b,a,sizeof(b));memcpy(q,p,sizeof(q));f(a[v+m],p,q);
 for(i=1;i<m;i++)for(j=0;j<i;j++){f(a[u+i],a[v+j],b[k]);f(a[u+j],a[v+i],b[k]);k++;}
 if(2*n-m>8)R h(m,a,p)-h(m,b,q);
 pthread_barrier_t bar;pthread_barrier_init(&bar,0,2);pthread_t th;
 cpu_set_t cpus;CPU_ZERO(&cpus);CPU_SET(icpu++%ncpu,&cpus);
 pthread_attr_t attr;pthread_attr_init(&attr);
 pthread_attr_setaffinity_np(&attr,sizeof(cpu_set_t),&cpus);
 A arg={m,a,p,&bar};pthread_create(&th,&attr,h1,&arg);
 I r=h(m,b,q);pthread_barrier_wait(&bar);pthread_join(th,0);pthread_barrier_destroy(&bar);
 R arg.r-r;
}
S V*h1(V*x0){A*x=(A*)x0;x->r=h(x->m,x->a,x->p);pthread_barrier_wait(x->bar);R 0;}
I main(){
 ncpu=sysconf(_SC_NPROCESSORS_ONLN);
 S C s[200000];I i=0,j=0,k,l=0;W((k=read(0,s+l,sizeof(s)-l))>0)l+=k;
 n=1;W(s[i]!=']')n+=s[i++]==',';n/=2;
 I a[T(2*n)][n+1];memset(a,0,sizeof(a));k=0;
 for(i=0;i<2*n;i++)for(j=0;j<2*n;j++){
  W(s[k]!='-'&&(s[k]<'0'||s[k]>'9'))k++;
  I v=0,m=s[k]=='-';k+=m;W(k<l&&('0'<=s[k]&&s[k]<='9'))v=10*v+s[k++]-'0';
  if(i>j)*a[T(i)+j]=v*(1-2*m);
 }
 I p[n+1];memset(p,0,sizeof(p));*p=1;
 printf("%d\n",(1-2*(n&1))*h(2*n,a,p));
 R 0;
}

অ্যালগরিদম:

ম্যাট্রিক্স, যা প্রতিসম হয়, নিম্ন বাম ত্রিভুজাকার আকারে সংরক্ষণ করা হয়। ত্রিভুজ সূচকগুলি i,jলিনিয়ার সূচকের সাথে মিলে যায় T(max(i,j))+min(i,j)যেখানে এর Tজন্য ম্যাক্রো i*(i-1)/2। ম্যাট্রিক্স উপাদানের ডিগ্রী polynomials হয় n। একটি বহুবর্ষকে ধ্রুবক পদ ( p[0]) থেকে x এন এর সহগ ( p[n]) থেকে অর্ডার করা সহগের একটি অ্যারে হিসাবে উপস্থাপন করা হয় । প্রাথমিক -1,0,1 ম্যাট্রিক্স মানগুলি প্রথমে কনস্ট পলিনোমিয়ালে রূপান্তরিত হয়।

আমরা দুটি আর্গুমেন্টের সাথে পুনরাবৃত্তিমূলক পদক্ষেপটি সম্পাদন করি: aবহুবর্ষের অর্ধ-ম্যাট্রিক্স (অর্থাত্ ত্রিভুজ) এবং একটি পৃথক বহুবর্ষ p(কাগজে বিটা হিসাবে পরিচিত)। আমরা আকারের mসমস্যাটিকে (প্রাথমিকভাবে m=2*n) পুনরাবৃত্তভাবে আকারের দুটি সমস্যার তুলনায় হ্রাস করি m-2এবং তাদের হাফানিদের পার্থক্য ফিরিয়ে দিই। এর মধ্যে একটি হ'ল aএটির শেষ দুটি সারি ছাড়াই একই ব্যবহার করা , এবং খুব একই p। আর একটি হ'ল ত্রিভুজটি ব্যবহার করা b[i][j] = a[i][j] + shmul(a[m-1][i],a[m-2][j]) + shmul(a[m-1][j],a[m-2][i])(যেখানে shmulবহুবচনগুলির উপর শিফট-গুণক ক্রিয়াকলাপ হয় - এটি যথারীতি বহুবর্ষগত পণ্যের মতো, অতিরিক্ত হিসাবে ভেরিয়েবল "x" দ্বারা গুণিত হয়; x ^ n এর চেয়ে উচ্চতর শক্তিগুলি অগ্রাহ্য করা হয়) এবং পৃথক বহুবচন q = p + shmul(p,a[m-1][m-2])। যখন পুনরাবৃত্তি একটি আকার -0 হিট করে a, আমরা পি এর প্রধান সহগকে ফিরিয়ে দিই p[n]

শিফট-ও-গুণিত ক্রিয়াকলাপটি কার্যকর হয় f(x,y,z)। এটি স্থান পরিবর্তন zকরে। আলগাভাবে বলতে গেলে, তা করে z += shmul(x,y)। এটি সর্বাধিক পারফরম্যান্স-সমালোচনামূলক অংশ বলে মনে হচ্ছে।

পুনরাবৃত্তি শেষ হওয়ার পরে, আমাদের (-1) এন দ্বারা গুণ করে ফলাফলের সাইনটি ঠিক করতে হবে ।


আপনার কোড গ্রহণ করে এমন ইনপুটটির একটি সুস্পষ্ট উদাহরণ আপনি প্রদর্শন করতে পারেন? 2 বাই 2 ম্যাট্রিক্সের জন্য বলুন। এছাড়াও, আপনি আপনার কোডটি গল্ফ করেছেন বলে মনে হচ্ছে! (এটি একটি গল্ফ চ্যালেঞ্জ নয়, একটি দ্রুততম কোড চ্যালেঞ্জ))

@ ল্যাম্বিক রেকর্ডের জন্য, যেমন আমি আড্ডায় বলেছিলাম, ইনপুটটি উদাহরণগুলির মতো একই ফর্ম্যাটে রয়েছে - জেসন (আসলে, এটি কেবল সংখ্যাগুলি পড়ে এবং এন = স্ক্র্যাট (লেন (ইনপুট)) / 2) ব্যবহার করে। আমি সাধারণত শর্ট কোড লিখি, এমনকি যখন গল্ফিংয়ের প্রয়োজন হয় না।
এনএনজি

এই নতুন কোডটি সমর্থন করা উচিত বৃহত্তম আকার ম্যাট্রিক্স কি?

1
-march=nativeএখানে একটি বড় পার্থক্য করতে হবে। কমপক্ষে টিআইও-তে, এটি প্রাচীরের সময়টিকে প্রায় অর্ধেক করে দেয়।
ডেনিস

1
এছাড়াও, কমপক্ষে টিআইও-তে, সিসি দ্বারা নির্বাহিত এক্সিকিউটেবল আরও দ্রুত হবে।
ডেনিস

3

পাইথন

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

from itertools import chain,combinations

def powerset(s):
    return chain.from_iterable(combinations(s, k) for k in range(len(s)+1))

def padd(a, b):
    return [a[i]+b[i] for i in range(len(a))]

def pmul(a, b):
    n = len(a)
    c = [0]*n
    for i in range(n):
        for j in range(n):
            if i+j < n:
                c[i+j] += a[i]*b[j]
    return c

def hafnian(m):
    n = len(m) / 2
    z = [[[c]+[0]*n for c in r] for r in m]
    h = 0
    for x in powerset(range(1, n+1)):
        b = z
        g = [1] + [0]*n
        for i in range(1, n+1):
            if i in x:
                g = pmul(g, [1] + b[0][1][:n])
                b = [[padd(b[j+2][k+2], [0] + padd(pmul(b[0][j+2], b[1][k+2]), pmul(b[0][k+2], b[1][j+2]))[:n]) if j != k else 0 for k in range(2*n-2*i)] for j in range(2*n-2*i)]
            else:
                b = [r[2:] for r in b[2:]]
        h += (-1)**(n - len(x)) * g[n]
    return h

এটি অনলাইন চেষ্টা করুন!

এখানে কয়েকটি সহজ অপ্টিমাইজেশান সহ একটি দ্রুত সংস্করণ।

def hafnian(m):
  n = len(m)/2
  z = [[0]*(n+1) for _ in range(n*(2*n-1))]
  for j in range(1, 2*n):
    for k in range(j):
      z[j*(j-1)/2+k][0] = m[j][k]
  return solve(z, 2*n, 1, [1] + [0]*n, n)

def solve(b, s, w, g, n):
  if s == 0:
    return w*g[n]
  c = [b[(j+1)*(j+2)/2+k+2][:] for j in range(1, s-2) for k in range(j)]
  h = solve(c, s-2, -w, g, n)
  e = g[:]
  for u in range(n):
    for v in range(n-u):
      e[u+v+1] += g[u]*b[0][v]
  for j in range(1, s-2):
    for k in range(j):
      for u in range(n):
        for v in range(n-u):
          c[j*(j-1)/2+k][u+v+1] += b[(j+1)*(j+2)/2][u]*b[(k+1)*(k+2)/2+1][v] + b[(k+1)*(k+2)/2][u]*b[(j+1)*(j+2)/2+1][v]
  return h + solve(c, s-2, w, e, n)

এটি অনলাইন চেষ্টা করুন!

যোগ মজার জন্য, এখানে একটি রেফারেন্স বাস্তবায়ন জে মধ্যে


এটি সমস্ত তালিকা বোধগম্য থেকে এবং তির্যক জুড়ে সমমানের মানগুলি গণনা করা থেকে বেশ ধীরে ধীরে, সুতরাং এটি মাপদণ্ডের প্রয়োজন নেই।
মাইল

অপূর্ব সুন্দর!

খুব সুন্দর! আমি সিম্পির সাথে অনুরূপ একটি জিনিস চেষ্টা করেছিলাম যা মর্মস্পর্শী ধীর হয়ে গিয়েছিল এবং ছোট উদাহরণগুলির জন্য সঠিক হয়ে ফিরে এসেছিল - দীর্ঘদিন পরে - 24 * 24 ম্যাট্রিক্সের জন্য একটি ভুল ফলাফল। সেখানে কী চলছে আমার কোনও ধারণা নেই। - অ্যালগরিদম 2 এর উপরের বর্ণনা অনুসারে, সেখানে বহুত্ববৃত্তীয় গুণটি ইতিমধ্যে কেটে ফেলা হয়েছে।
খ্রিস্টান সিভার্স

2
ইন pmul, ব্যবহার করুন for j in range(n-i):এবং এড়ানোif
ক্রিশ্চিয়ান সিভার্স

1
@ ল্যাম্বিক এটি পুরো ম্যাট্রিক্সের গণনা করে; j != kসঙ্গে প্রায় দুটি একটি ফ্যাক্টর জন্য প্রতিস্থাপন j < k। এটি অন্য ক্ষেত্রে একটি সাবম্যাট্রিক্স অনুলিপি করে যা এড়ানো যায় যখন আমরা প্রথম দুটি সারি এবং কলামগুলির পরিবর্তে শেষ দুটি হ্যান্ডেল করে মুছি। এবং যখন এটি এর সাথে x={1,2,4}এবং পরে এর সাথে গণনা করে x={1,2,4,6}তখন এটি তার গণনাগুলি পুনরাবৃত্তি করে i=5। আমি দুটি বাহ্যিক লুপের কাঠামোটি প্রথম লুপিংয়ের সাথে প্রতিস্থাপন করেছি iএবং তারপরে পুনরাবৃত্তভাবে ধরে নেওয়া i in Xএবং i not in X। - বিটিডাব্লু, অন্যান্য ধীর কর্মসূচির তুলনায় প্রয়োজনীয় সময়ের বর্ধনের দিকে নজর দেওয়া আকর্ষণীয় হতে পারে।
খ্রিস্টান সিভর্স

1

অষ্টক

এটি মূলত ডেনিসের প্রবেশের একটি অনুলিপি , তবে অক্টটাভের জন্য অনুকূলিত। মূল অপ্টিমাইজেশনটি সম্পূর্ণ ইনপুট ম্যাট্রিক্স (এবং এর ট্রান্সপোজ) ব্যবহার করে এবং পুনরাবৃত্তি হ্রাস ম্যাট্রিক্স তৈরির পরিবর্তে কেবল ম্যাট্রিক্স সূচকগুলি ব্যবহার করে করা হয়।

প্রধান সুবিধা ম্যাট্রিকের অনুলিপি হ্রাস করা হয়। যদিও অক্টোভের পয়েন্টার / রেফারেন্স এবং মানগুলির মধ্যে পার্থক্য নেই এবং কার্যত কেবল পাস-বাই-ভ্যালু করেন না, এটি পর্দার আড়ালে একটি আলাদা গল্প। সেখানে, অনুলিপি (অলস অনুলিপি) ব্যবহার করা হয়। তার মানে, a=1;b=a;b=b+1কোডটির bজন্য , ভেরিয়েবলটি কেবলমাত্র পরিবর্তনের সাথে সাথে শেষ বিবৃতিতে একটি নতুন অবস্থানে অনুলিপি করা হয়। যেহেতু matinএবং matranspকখনই পরিবর্তন হয় না, সেগুলি কখনই অনুলিপি করা হবে না। অসুবিধাটি হ'ল ফাংশনটি সঠিক সূচকগুলি গণনায় বেশি সময় ব্যয় করে। এটিকে অপ্টিমাইজ করার জন্য আমাকে সংখ্যাসূচক এবং লজিকাল সূচকগুলির মধ্যে বিভিন্ন প্রকারের চেষ্টা করতে হবে।

গুরুত্বপূর্ণ দ্রষ্টব্য: ইনপুট ম্যাট্রিক্স হওয়া উচিত int32! কল করা একটি ফাইলে ফাংশন সংরক্ষণ করুনhaf.m

function h=haf(matin,indices,matransp,transp)

    if nargin-4
        indices=int32(1:length(matin));
        matransp=matin';
        transp=false;
    end
    if(transp)
        matrix=matransp;
    else
        matrix=matin;
    end
    ind1=indices(1);
    n=length(indices);
    if n==2
        h=matrix(ind1,indices(2));
        return
    end
    h=0*matrix(1); 
    for j=1:(n-1)
        indj=indices(j+1);
        k=matrix(ind1,indj);
        if logical(k)
            indicestemp=true(n,1);
            indicestemp(1:j:j+1)=false;
            h=h+k.*haf(matin,indices(indicestemp),matransp,~transp);
        end
    end
end

পরীক্ষার স্ক্রিপ্ট উদাহরণ:

matrix = int32([0 0 1 -1 1 0 -1 -1 -1 0 -1 1 0 1 1 0 0 1 0 0 1 0 1 1;0 0 1 0 0 -1 -1 -1 -1 0 1 1 1 1 0 -1 -1 0 0 1 1 -1 0 0;-1 -1 0 1 0 1 -1 1 -1 1 0 0 1 -1 0 0 0 -1 0 -1 1 0 0 0;1 0 -1 0 1 1 0 1 1 0 0 0 1 0 0 0 1 -1 -1 -1 -1 1 0 -1;-1 0 0 -1 0 0 1 -1 0 1 -1 -1 -1 1 1 0 1 1 1 0 -1 1 -1 -1;0 1 -1 -1 0 0 1 -1 -1 -1 0 -1 1 0 0 0 -1 0 0 1 0 0 0 -1;1 1 1 0 -1 -1 0 -1 -1 0 1 1 -1 0 1 -1 0 0 1 -1 0 0 0 -1;1 1 -1 -1 1 1 1 0 0 1 0 1 0 0 0 0 1 0 1 0 -1 1 0 0;1 1 1 -1 0 1 1 0 0 -1 1 -1 1 1 1 0 -1 -1 -1 -1 0 1 1 -1;0 0 -1 0 -1 1 0 -1 1 0 1 0 0 0 0 0 1 -1 0 0 0 1 -1 -1;1 -1 0 0 1 0 -1 0 -1 -1 0 0 1 0 0 -1 0 -1 -1 -1 -1 -1 1 -1;-1 -1 0 0 1 1 -1 -1 1 0 0 0 -1 0 0 -1 0 -1 -1 0 1 -1 0 0;0 -1 -1 -1 1 -1 1 0 -1 0 -1 1 0 1 -1 -1 1 -1 1 0 1 -1 1 -1;-1 -1 1 0 -1 0 0 0 -1 0 0 0 -1 0 0 -1 1 -1 -1 0 1 0 -1 -1;-1 0 0 0 -1 0 -1 0 -1 0 0 0 1 0 0 1 1 1 1 -1 -1 0 -1 -1;0 1 0 0 0 0 1 0 0 0 1 1 1 1 -1 0 0 1 -1 -1 -1 0 -1 -1;0 1 0 -1 -1 1 0 -1 1 -1 0 0 -1 -1 -1 0 0 -1 1 0 0 -1 -1 1;-1 0 1 1 -1 0 0 0 1 1 1 1 1 1 -1 -1 1 0 1 1 -1 -1 -1 1;0 0 0 1 -1 0 -1 -1 1 0 1 1 -1 1 -1 1 -1 -1 0 1 1 0 0 -1;0 -1 1 1 0 -1 1 0 1 0 1 0 0 0 1 1 0 -1 -1 0 0 0 1 0;-1 -1 -1 1 1 0 0 1 0 0 1 -1 -1 -1 1 1 0 1 -1 0 0 0 0 0;0 1 0 -1 -1 0 0 -1 -1 -1 1 1 1 0 0 0 1 1 0 0 0 0 1 0;-1 0 0 0 1 0 0 0 -1 1 -1 0 -1 1 1 1 1 1 0 -1 0 -1 0 1;-1 0 0 1 1 1 1 0 1 1 1 0 1 1 1 1 -1 -1 1 0 0 0 -1 0])

tic
i=1;
while(toc<60)
    tic
    haf(matrix(1:i,1:i));
    i=i+1;
end

আমি টিআইও এবং ম্যাটল্যাব ব্যবহার করে এটি ব্যবহার করে দেখেছি (আমি আসলে কখনই অক্টাভ ইনস্টল করি নি)। আমি এটি কাজ করতে হিসাবে হিসাবে সহজ হিসাবে কল্পনা sudo apt-get install octave। কমান্ডটি octaveঅক্টাভ জিইউআই লোড করবে। যদি এটি এর চেয়ে আরও জটিল হয় তবে আমি আরও উত্তর ইনস্টলেশন নির্দেশনা না দেওয়া পর্যন্ত এই উত্তরটি মুছে ফেলব।


0

সম্প্রতি আন্দ্রেয়াস জোরক্লানড, ব্রজেশ গুপ্ত এবং আমি জটিল ম্যাট্রিক্সের হাফনিয়ানদের জন্য একটি নতুন অ্যালগরিদম প্রকাশ করেছি: https://arxiv.org/pdf/1805.12498.pdf । একটি n \ বার n ম্যাট্রিক্সের জন্য এটি n ^ 3 2 ^ / n / 2 like এর মতো স্কেল করে}

যদি আমি https://arxiv.org/pdf/1107.4466.pdf থেকে আন্দ্রেয়াসের মূল অ্যালগরিদমটি সঠিকভাবে বুঝতে পারি তবে এটি n ^ 4 2 ^ / n / 2} বা n ^ 3 লগ (এন) 2 ^ {n / 2} এর মতো স্কেল করে আপনি যদি বহুত্বীয় গুণগুলি করতে ফুরিয়ার রূপান্তর ব্যবহার করেন।
আমাদের অ্যালগরিদম বিশেষত জটিল ম্যাট্রিকগুলির জন্য টেলরর্ডড তাই এটি এখানে {-1,0,1} ম্যাট্রিকের জন্য বিকাশমান তত দ্রুত হবে না। তবে আমি ভাবছি যদি কেউ আমাদের প্রয়োগকে উন্নত করতে আপনি যে কৌশলগুলি ব্যবহার করেন সেগুলি কেউ ব্যবহার করতে পারে? এছাড়াও যদি লোকেরা আগ্রহী হয় তবে আমি দেখতে চাই যে পূর্ণসংখ্যার পরিবর্তে জটিল সংখ্যা দেওয়া হলে তাদের বাস্তবায়ন কীভাবে হয়। অবশেষে, আমাদের সংগ্রহস্থল https://github.com/XanaduAI/hafnian/ এ যে কোনও মন্তব্য, সমালোচনা, উন্নতি, বাগ, উন্নতি স্বাগত জানানো হয়েছে

চিয়ার্স!


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

পিপিসিজিতে আপনাকে স্বাগতম। আপনার উত্তরটি দুর্দান্ত মন্তব্য করতে পারে, তবে সাইটটি QA এর জন্য নয়। এটি একটি চ্যালেঞ্জের সাইট এবং একটি চ্যালেঞ্জের জবাবের কোড থাকতে হবে এবং অন্য কোনও কিছুর ব্যাখ্যা নয়। দয়া করে আপডেট বা মুছুন (যদি আপনি না করেন তবে মোডগুলি হবে)
মুহাম্মদ সালমান

ঠিক আছে, কোডটি গিথুবটিতে রয়েছে তবে আমি অনুমান করি যে এটি এখানে অনুলিপি করে কেবল অনুলিপি করে।
নিকোলস কুইসদা

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

@ নিকোলসকুইসদা উত্তরগুলি যদি সম্ভব হয় তবে এই সাইটে উত্তরগুলি স্বয়ংসম্পূর্ণ হওয়া উচিত, এর অর্থ আপনার উত্তর / কোড দেখতে আমাদের অন্য কোনও সাইটে যেতে হবে না।
mbomb007
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.