अनुमानित सहसंबंधों का पता लगाना


14

Sलंबाई के एक बाइनरी स्ट्रिंग पर विचार करें n। से अनुक्रमण 1, हम गणना कर सकता है आलोचनात्मक दूरी के बीच S[1..i+1]और S[n-i..n]सभी के लिए iसे क्रम में 0करने के लिए n-1। समान लंबाई के दो तारों के बीच की हैमिंग दूरी उन पदों की संख्या है, जिन पर संबंधित चिह्न भिन्न होते हैं। उदाहरण के लिए,

S = 01010

देता है

[0, 2, 0, 4, 0].

इसका कारण यह है 0मैचों 0, 01को आलोचनात्मक अंतर दो है 10, 010मैचों 010, 0101को आलोचनात्मक अंतर चार है 1010 और अंत में 01010खुद को मेल खाता है।

हम केवल उन आउटपुट में रुचि रखते हैं जहां हैमिंग की दूरी अधिकतम 1 पर है। इसलिए इस कार्य में हम रिपोर्ट करेंगे Yकि क्या हमिंग की दूरी सबसे अधिक है और Nअन्यथा। तो ऊपर हमारे उदाहरण में हमें मिलेगा

[Y, N, Y, N, Y]

लंबाई के सभी अलग-अलग संभव तारों पर पुनरावृति करते समय एस और एस f(n)के अलग-अलग सरणियों की संख्या को परिभाषित करें ।YN2^nSn

कार्य

बढ़ाने के लिए nसे शुरू 1, अपने कोड उत्पादन करना चाहिए f(n)

उदाहरण उत्तर

इसके लिए n = 1..24, सही उत्तर हैं:

1, 1, 2, 4, 6, 8, 14, 18, 27, 36, 52, 65, 93, 113, 150, 188, 241, 279, 377, 427, 540, 632, 768, 870

स्कोरिंग

आपके कोड को बारी-बारी से n = 1प्रत्येक के लिए उत्तर देने से बचना चाहिए n। मैं पूरे दौड़ने का समय दूंगा, दो मिनट बाद इसे मारूंगा।

आपका स्कोर nउस समय का उच्चतम अंक है ।

एक टाई के मामले में, पहला उत्तर जीत जाता है।

मेरे कोड का परीक्षण कहां किया जाएगा?

मैं अपने कोड को मेरे (थोड़े पुराने) विंडोज 7 लैपटॉप पर साइबरविन के तहत चलाऊंगा। परिणामस्वरूप, कृपया इस आसान को बनाने में आपकी सहायता के लिए कोई भी सहायता दे सकते हैं।

मेरे लैपटॉप में 8GB RAM और एक Intel i7 5600U@2.6 GHz (Broadwell) CPU है जिसमें 2 कोर और 4 धागे हैं। निर्देश सेट में SSE4.2, AVX, AVX2, FMA3 और TSX शामिल हैं।

प्रति भाषा प्रमुख प्रविष्टियाँ

  • n = 40 Rust में CersoMiniSat, Anders Kaseorg द्वारा उपयोग किया जा रहा है। (बॉक्स के तहत लुबंटू अतिथि वीएम में।)
  • एन = 35 में सी ++ साथी पुस्तकालय, ईसाई Seviers से इस्तेमाल करते हैं। (बॉक्स के तहत लुबंटू अतिथि वीएम में।)
  • एन = 34 में Clingo ऐन्डर्स Kaseorg द्वारा। (बॉक्स के तहत लुबंटू अतिथि वीएम में।)
  • n = 31 एंडर्स केसरग द्वारा जंग में ।
  • एन = 29 में Clojure NikoNyrh द्वारा।
  • n = 29 में C द्वारा bartvelle।
  • एन = 27 में हास्केल bartavelle द्वारा
  • n = 24 में एलीफेला द्वारा पेरी / जीपी
  • एन = 22 में अजगर 2 + PyPy मेरे द्वारा।
  • एन = 21 में मेथेमेटिका alephalpha द्वारा। (आत्म सूचना दी)

भविष्य के इनाम

मैं अब दो मिनट में अपनी मशीन पर n = 80 तक उठने वाले किसी भी उत्तर के लिए 200 अंक का इनाम दूंगा ।


क्या आप कुछ चाल के बारे में जानते हैं जो किसी को एक भोली जानवर बल की तुलना में तेजी से एल्गोरिथ्म खोजने की अनुमति देगा? यदि यह चुनौती नहीं है "कृपया इसे x86 में लागू करें" (या शायद अगर हम आपके जीपीयू को जानते हैं ...)।
जोनाथन एलन

@JonathanAllan यह निश्चित रूप से बहुत भोली दृष्टिकोण को गति देने के लिए संभव है। वास्तव में कितनी तेजी से आप प्राप्त कर सकते हैं मुझे यकीन नहीं है। दिलचस्प बात यह है कि यदि हमने प्रश्न को बदल दिया है ताकि आपको एक वाई मिल जाए अगर हेमिंग की दूरी अधिकतम 0 और एक एन पर है, तो एक ज्ञात बंद फार्मूला है।

@ लेम्बिक क्या हम CPU समय या वास्तविक समय को मापते हैं?
दोष

@flawr मैं वास्तविक समय को माप रहा हूं लेकिन इसे कुछ बार चला रहा हूं और विषमताओं को खत्म करने के लिए न्यूनतम ले रहा हूं।

जवाबों:


9

जंग + क्रिप्टोमिनीसैट , एन o 41

src/main.rs

extern crate cryptominisat;
extern crate itertools;

use std::iter::once;
use cryptominisat::{Lbool, Lit, Solver};
use itertools::Itertools;

fn make_solver(n: usize) -> (Solver, Vec<Lit>) {
    let mut solver = Solver::new();
    let s: Vec<Lit> = (1..n).map(|_| solver.new_var()).collect();
    let d: Vec<Vec<Lit>> = (1..n - 1)
        .map(|k| {
                 (0..n - k)
                     .map(|i| (if i == 0 { s[k - 1] } else { solver.new_var() }))
                     .collect()
             })
        .collect();
    let a: Vec<Lit> = (1..n - 1).map(|_| solver.new_var()).collect();
    for k in 1..n - 1 {
        for i in 1..n - k {
            solver.add_xor_literal_clause(&[s[i - 1], s[k + i - 1], d[k - 1][i]], true);
        }
        for t in (0..n - k).combinations(2) {
            solver.add_clause(&t.iter()
                                   .map(|&i| d[k - 1][i])
                                   .chain(once(!a[k - 1]))
                                   .collect::<Vec<_>>()
                                   [..]);
        }
        for t in (0..n - k).combinations(n - k - 1) {
            solver.add_clause(&t.iter()
                                   .map(|&i| !d[k - 1][i])
                                   .chain(once(a[k - 1]))
                                   .collect::<Vec<_>>()
                                   [..]);
        }
    }
    (solver, a)
}

fn search(n: usize,
          solver: &mut Solver,
          a: &Vec<Lit>,
          assumptions: &mut Vec<Lit>,
          k: usize)
          -> usize {
    match solver.solve_with_assumptions(assumptions) {
        Lbool::True => search_sat(n, solver, a, assumptions, k),
        Lbool::False => 0,
        Lbool::Undef => panic!(),
    }
}

fn search_sat(n: usize,
              solver: &mut Solver,
              a: &Vec<Lit>,
              assumptions: &mut Vec<Lit>,
              k: usize)
              -> usize {
    if k >= n - 1 {
        1
    } else {
        let s = solver.is_true(a[k - 1]);
        assumptions.push(if s { a[k - 1] } else { !a[k - 1] });
        let c = search_sat(n, solver, a, assumptions, k + 1);
        assumptions.pop();
        assumptions.push(if s { !a[k - 1] } else { a[k - 1] });
        let c1 = search(n, solver, a, assumptions, k + 1);
        assumptions.pop();
        c + c1
    }
}

fn f(n: usize) -> usize {
    let (mut solver, proj) = make_solver(n);
    search(n, &mut solver, &proj, &mut vec![], 1)
}

fn main() {
    for n in 1.. {
        println!("{}: {}", n, f(n));
    }
}

Cargo.toml

[package]
name = "correlations-cms"
version = "0.1.0"
authors = ["Anders Kaseorg <andersk@mit.edu>"]

[dependencies]
cryptominisat = "5.0.1"
itertools = "0.6.0"

यह काम किस प्रकार करता है

यह Y / N सरणी के उपसर्गों के लिए सभी आंशिक असाइनमेंट्स के पेड़ के माध्यम से एक पुनरावर्ती खोज करता है, प्रत्येक चरण में जाँचने के लिए SAT सॉल्वर का उपयोग करके कि क्या वर्तमान आंशिक असाइनमेंट संगत है और नहीं तो खोज को prune करें। क्रिप्टोइमनीसैट XOR क्लॉस के लिए अपनी विशेष अनुकूलन के कारण इस नौकरी के लिए सही सैट सॉल्वर है।

तीन परिवारों की अड़चनें हैं

एस मैंएस कश्मीर + मैंडी की , 1 के लिए ≤ कश्मीरn - 2, 0 ≤ मैं ≤ n - कश्मीर ;
डी की 1डी की 2 ∨ ¬ एक कश्मीर , के लिए 1 ≤ कश्मीरn - 2, 0 ≤ मैं 1 < मैं 2n - कश्मीर ;
¬ डी की 11 ¬ k डी की एन - के - 1एक कश्मीर , के लिए 1 ≤ कश्मीरn - 2, 0 ≤ मैं 1 <⋯ < मैं n - कश्मीर - 1n - कश्मीर ;

सिवाय इसके कि, एक अनुकूलन के रूप में, एस 0 false पर मजबूर किया जाता है, ताकि विकास कश्मीर 0 बस है के बराबर एस कश्मीर


2
वाहहुओ! :)

मैं अभी भी इसे विंडोज में संकलित करने की कोशिश कर रहा हूं (साइबरविन + जीसीसी का उपयोग करके)। मैंने क्रिप्टोमिनिसैट क्लोन किया और इसे संकलित किया। लेकिन मैं अभी भी नहीं जानता कि जंग कोड को कैसे संकलित किया जाए। जब मुझे cargo buildमिलता है--- stderr CMake Error: Could not create named generator Visual Studio 14 2015 Win64

2
@ rahnema1 धन्यवाद, लेकिन ऐसा लगता है कि यह मुद्दा क्रिप्टोमिनिसैट टोकरे में एम्बेडेड सी ++ लाइब्रेरी के सीएमके बिल्ड सिस्टम के साथ है, न कि रुस्ट के साथ।
एंडर्स कासोर्ग

1
@ लेम्बिक मुझे उस पेस्ट से 404 मिल रहे हैं।
मेघो

1
@ChristianSievers अच्छा सवाल। यह काम करता है लेकिन यह थोड़ा धीमा (2 × या तो) लगता है। मुझे यकीन नहीं है कि यह सिर्फ उतना अच्छा क्यों नहीं होना चाहिए, इसलिए शायद CryptoMiniSat को उस तरह के वृद्धिशील कार्यभार के लिए अच्छी तरह से अनुकूलित नहीं किया गया है।
एंडर्स कासोर्ग

9

जंग, एन ≈ 30 या 31 या 32

मेरे लैपटॉप पर (दो कोर, i5-6200U), यह n = 1,…, 31 सेकंड में 53 सेकंड में, लगभग 2.5 GiB मेमोरी का उपयोग करके, या n = 1,… के माध्यम से , 105 सेकंड में, लगभग 5 GiB का उपयोग करके प्राप्त करता है। स्मृति का। साथ cargo build --releaseचलाना और चलाना target/release/correlations

src/main.rs

extern crate rayon;

type S = u32;
const S_BITS: u32 = 32;

fn cat(mut a: Vec<S>, mut b: Vec<S>) -> Vec<S> {
    if a.capacity() >= b.capacity() {
        a.append(&mut b);
        a
    } else {
        b.append(&mut a);
        b
    }
}

fn search(n: u32, i: u32, ss: Vec<S>) -> u32 {
    if ss.is_empty() {
        0
    } else if 2 * i + 1 > n {
        search_end(n, i, ss)
    } else if 2 * i + 1 == n {
        search2(n, i, ss.into_iter().flat_map(|s| vec![s, s | 1 << i]))
    } else {
        search2(n,
                i,
                ss.into_iter()
                    .flat_map(|s| {
                                  vec![s,
                                       s | 1 << i,
                                       s | 1 << n - i - 1,
                                       s | 1 << i | 1 << n - i - 1]
                              }))
    }
}

fn search2<SS: Iterator<Item = S>>(n: u32, i: u32, ss: SS) -> u32 {
    let (shift, mask) = (n - i - 1, !(!(0 as S) << i + 1));
    let close = |s: S| {
        let x = (s ^ s >> shift) & mask;
        x & x.wrapping_sub(1) == 0
    };
    let (ssy, ssn) = ss.partition(|&s| close(s));
    let (cy, cn) = rayon::join(|| search(n, i + 1, ssy), || search(n, i + 1, ssn));
    cy + cn
}

fn search_end(n: u32, i: u32, ss: Vec<S>) -> u32 {
    if i >= n - 1 { 1 } else { search_end2(n, i, ss) }
}

fn search_end2(n: u32, i: u32, mut ss: Vec<S>) -> u32 {
    let (shift, mask) = (n - i - 1, !(!(0 as S) << i + 1));
    let close = |s: S| {
        let x = (s ^ s >> shift) & mask;
        x & x.wrapping_sub(1) == 0
    };
    match ss.iter().position(|&s| close(s)) {
        Some(0) => {
            match ss.iter().position(|&s| !close(s)) {
                Some(p) => {
                    let (ssy, ssn) = ss.drain(p..).partition(|&s| close(s));
                    let (cy, cn) = rayon::join(|| search_end(n, i + 1, cat(ss, ssy)),
                                               || search_end(n, i + 1, ssn));
                    cy + cn
                }
                None => search_end(n, i + 1, ss),
            }
        }
        Some(p) => {
            let (ssy, ssn) = ss.drain(p..).partition(|&s| close(s));
            let (cy, cn) = rayon::join(|| search_end(n, i + 1, ssy),
                                       || search_end(n, i + 1, cat(ss, ssn)));
            cy + cn
        }
        None => search_end(n, i + 1, ss),
    }
}

fn main() {
    for n in 1..S_BITS + 1 {
        println!("{}: {}", n, search(n, 1, vec![0, 1]));
    }
}

Cargo.toml

[package]
name = "correlations"
version = "0.1.0"
authors = ["Anders Kaseorg <andersk@mit.edu>"]

[dependencies]
rayon = "0.7.0"

इसे ऑनलाइन आज़माएं!

मेरे पास बहुत कम मेमोरी का उपयोग करके थोड़ा धीमा संस्करण है


आपने क्या अनुकूलन किया है?

1
@ लेम्बिक सबसे बड़ा अनुकूलन, संकलित भाषा में बिटवाइज़ अंकगणित के साथ सब कुछ करने के अलावा, केवल वाई / एन सरणी के एक उपसर्ग को नीचे करने के लिए नॉनडेटर्मिनिज़्म का उतना ही उपयोग करना है। मैं वाई / एन सरणी के संभावित उपसर्गों पर एक पुनरावर्ती खोज करता हूं, जो उस उपसर्ग को प्राप्त करने वाले संभावित तारों के एक वेक्टर के साथ ले जा रहा है, लेकिन केवल वे तार जिनके अनएक्समाइंड बीच में शून्य से भरा है। उस ने कहा, यह अभी भी एक घातीय खोज है, और ये अनुकूलन केवल बहुपद कारकों द्वारा इसे गति देते हैं।
एंडर्स कासोर्ग

यह एक अच्छा जवाब है। धन्यवाद। मैं उम्मीद कर रहा हूं कि कोई व्यक्ति कॉम्बीनेटरिक्स में एक महत्वपूर्ण गति प्राप्त करने के लिए खुदाई करेगा।

@ लेम्बिक मैंने एक मेमोरी बर्बाद करने वाली बग को ठीक किया है, अधिक माइक्रो-ऑप्टिमाइज़ेशन किया है, और समानता को जोड़ा है। कृपया मौका मिलने पर पुन: प्रयास करें- मैं अपने स्कोर को 1 या 2 से बढ़ाने की उम्मीद कर रहा हूं। क्या आपके पास कई मजबूत स्टार्टअप के लिए जुझारू विचार हैं? मैं कुछ लेकर नहीं आया हूं।
एंडर्स केसरग

1
@Lembik OEIS प्रविष्टि पर कोई सूत्र नहीं दिया गया है। (वहाँ के गणितज्ञ कोड का उपयोग ब्रूट-फ़ोर्स के लिए भी करते हैं।) यदि आप एक के बारे में जानते हैं, तो आप उन्हें इसके बारे में बताना चाह सकते हैं।
क्रिश्चियन सिवर्स

6

BuDDy लाइब्रेरी का उपयोग करके C ++

एक अलग दृष्टिकोण: एक द्विआधारी सूत्र है ( बाइनरी निर्णय आरेख के रूप में ) जो Sइनपुट के रूप में बिट्स लेता है और सही iff है जो कुछ निश्चित पदों पर Yया कुछ निश्चित मान देता है N। कि सूत्र लगातार झूठी नहीं है, तो एक नि: शुल्क स्थिति का चयन और recurse, कोशिश कर दोनों Yऔर N। यदि कोई मुक्त स्थिति नहीं है, तो हमने संभावित आउटपुट मान पाया है। यदि सूत्र निरंतर गलत है, तो पीछे।

यह अपेक्षाकृत उचित काम करता है क्योंकि बहुत कम संभव मूल्य हैं ताकि हम अक्सर जल्दी वापस आ सकें। मैंने सैट सॉल्वर के साथ एक समान विचार की कोशिश की, लेकिन वह कम सफल रहा।

#include<vector>
#include<iostream>
#include<bdd.h>

// does vars[0..i-1] differ from vars[n-i..n-1] in at least two positions?
bdd cond(int i, int n, const std::vector<bdd>& vars){
  bdd x1 { bddfalse };
  bdd xs { bddfalse };
  for(int k=0; k<i; ++k){
    bdd d { vars[k] ^ vars[n-i+k] };
    xs |= d & x1;
    x1 |= d;
  }
  return xs;
}

void expand(int i, int n, int &c, const std::vector<bdd>& conds, bdd x){
  if (x==bddfalse)
    return;
  if (i==n-2){
    ++c;
    return;
  }

  expand(i+1,n,c,conds, x & conds[2*i]);
  x &= conds[2*i+1];
  expand(i+1,n,c,conds, x);
}

int count(int n){
  if (n==1)   // handle trivial case
    return 1;
  bdd_setvarnum(n-1);
  std::vector<bdd> vars {};
  vars.push_back(bddtrue); // assume first bit is 1
  for(int i=0; i<n-1; ++i)
    if (i%2==0)            // vars in mixed order
      vars.push_back(bdd_ithvar(i/2));
    else
      vars.push_back(bdd_ithvar(n-2-i/2));
  std::vector<bdd> conds {};
  for(int i=n-1; i>1; --i){ // handle long blocks first
    bdd cnd { cond(i,n,vars) };
    conds.push_back( cnd );
    conds.push_back( !cnd );
  }
  int c=0;
  expand(0,n,c,conds,bddtrue);
  return c;
}

int main(void){
  bdd_init(20000000,1000000);
  bdd_gbc_hook(nullptr); // comment out to see GC messages
  for(int n=1; ; ++n){
    std::cout << n << " " << count(n) << "\n" ;
  }
}

डेबियन 8 (जेसी) के साथ संकलन करने के लिए, स्थापित करें libbdd-devऔर करें g++ -std=c++11 -O3 -o hb hb.cpp -lbdd। पहले तर्क को और bdd_initभी अधिक बढ़ाने के लिए यह उपयोगी हो सकता है ।


यह दिलचस्प लग रहा है। इससे आपको क्या मिलता है?

@ लेम्बिक मुझे बहुत पुराने हार्डवेयर पर 100 में 31 मिले जो मुझे तेजी से जवाब नहीं देने देंगे
क्रिश्चियन सेवर्स

कोई भी मदद जो आप इसे विंडोज पर संकलित करने के लिए दे सकते हैं (उदाहरण के लिए साइबरविन का उपयोग करके) कृतज्ञता प्राप्त की।

@ लेम्बिक मुझे विंडव्स के बारे में नहीं पता है, लेकिन github.com/fd00/yacp/tree/master/buddy सहायक wrt cygwin लगता है
क्रिश्चियन सेवर्स

1
वाह, ठीक है, आपने मुझे समझा दिया है कि मुझे अपने टूलकिट में इस लाइब्रेरी को जोड़ना होगा। बहुत बढ़िया!
एंडर्स केसरग

4

क्लिंगो, एन or 30 या 31 34

क्लिंगो कोड की पांच पंक्तियों को देखने के लिए मैं थोड़ा आश्चर्यचकित था, अपने पाशविक बल के घोल से आगे निकल गया और वास्तव में क्रिश्चियन के ब्यूडी समाधान के करीब आ गया - ऐसा लग रहा है कि यह एक उच्च समय सीमा के साथ भी हरा देगा।

corr.lp

{s(2..n)}.
d(K,I) :- K=1..n-2, I=1..n-K, s(I), not s(K+I).
d(K,I) :- K=1..n-2, I=1..n-K, not s(I), s(K+I).
a(K) :- K=1..n-2, {d(K,1..n-K)} 1.
#show a/1.

corr.sh

#!/bin/bash
for ((n=1;;n++)); do
    echo "$n $(clingo corr.lp --project -q -n 0 -c n=$n | sed -n 's/Models *: //p')"
done

भूखंड


यह भी खूब रही! यह आपके ग्राफ से लगता है कि BuDDy समाधान अचानक खराब हो जाता है। कोई विचार क्यों?

@ लेम्बिक मैंने निश्चित होने के लिए ब्यूडी की जांच नहीं की है, लेकिन शायद यह उस बिंदु पर कैश से बाहर है?
एंडर्स कासोर्ग

वाह! मुझे लगता है कि 50000 के डिफ़ॉल्ट से अधिक मूल्य के साथ bdd_initकॉल करके नोड तालिका को बढ़ाने में मदद करने के लिए एक उच्चतर पहला मूल्य हो सकता है। bdd_setmaxincrease- क्या आप मेरे कार्यक्रम के परिवर्तित संस्करण का उपयोग कर रहे हैं?
क्रिश्चियन सिवर्स ने

2
मुझे आपका ग्राफ बहुत पसंद है।

1
आप विकल्प का उपयोग करके एक चौंकाने वाला प्रदर्शन बढ़ाते हैं --configuration=crafty( jumpyऔर trendyइसी तरह के परिणाम देते हैं)।
क्रिश्चियन सेवर्स

2

परी / जीपी , 23

डिफ़ॉल्ट रूप से, Pari / GP अपने स्टैक आकार को 8 MB तक सीमित करता है। कोड की पहली पंक्ति default(parisize, "4g"), इस सीमा को 4 GB पर सेट करती है। यदि यह अभी भी स्टैकओवरफ्लो देता है, तो आप इसे 8 जीबी पर सेट कर सकते हैं।

default(parisize, "4g")
f(n) = #vecsort([[2 > hammingweight(bitxor(s >> (n-i) , s % 2^i)) | i <- [2..n-1]] | s <- [0..2^(n-1)]], , 8)
for(n = 1, 100, print(n " -> " f(n)))

22 तक पहुंचता है और फिर स्टैकओवरफ्लो देता है।

24 को हो जाता है।

2

क्लोजर, 75 38 सेकंड में 29, 80 में 30 और 165 में 31

इंटेल i7 6700K से रनटाइम , मेमोरी का उपयोग 200 एमबी से कम है।

project.clj ( मल्टीथ्रेडिंग के लिए com.climate / क्लेम्पोले का उपयोग करता है):

(defproject tests "0.0.1-SNAPSHOT"
  :description "FIXME: write description"
  :dependencies [[org.clojure/clojure "1.8.0"]
                 [com.climate/claypoole "1.1.4"]]
  :javac-options ["-target" "1.6" "-source" "1.6" "-Xlint:-options"]
  :aot [tests.core]
  :main tests.core)

सोर्स कोड:

(ns tests.core
  (:require [com.climate.claypoole :as cp]
            [clojure.set])
  (:gen-class))

(defn f [N]
  (let [n-threads   (.. Runtime getRuntime availableProcessors)
        mask-offset (- 31 N)
        half-N      (quot N 2)
        mid-idx     (bit-shift-left 1 half-N)
        end-idx     (bit-shift-left 1 (dec N))
        lower-half  (bit-shift-right 0x7FFFFFFF mask-offset)
        step        (bit-shift-left 1 12)
        bitcount
          (fn [n]
            (loop [i 0 result 0]
              (if (= i N)
                result
                (recur
                  (inc i)
                  (-> n
                      (bit-xor (bit-shift-right n i))
                      (bit-and (bit-shift-right 0x7FFFFFFF (+ mask-offset i)))
                      Integer/bitCount
                      (< 2)
                      (if (+ result (bit-shift-left 1 i))
                          result))))))]
    (->>
      (cp/upfor n-threads [start (range 0 end-idx step)]
        (->> (for [i      (range start (min (+ start step) end-idx))
                   :when  (<= (Integer/bitCount (bit-shift-right i mid-idx))
                              (Integer/bitCount (bit-and         i lower-half)))]
               (bitcount i))
             (into #{})))
      (reduce clojure.set/union)
      count)))

(defn -main [n]
  (let [n-iters 5]
    (println "Calculating f(n) from 1 to" n "(inclusive)" n-iters "times")
    (doseq [i (range n-iters)]
      (->> n read-string inc (range 1) (map f) doall println time)))
  (shutdown-agents)
  (System/exit 0))

एक जानवर-बल समाधान, प्रत्येक थ्रेड रेंज के सबसेट (2 ^ 12 आइटम) पर जाता है और पूर्णांक मानों का एक सेट बनाता है जो पता लगाए गए पैटर्न को दर्शाता है। ये फिर एक साथ "संघबद्ध" होते हैं और इस प्रकार अलग-अलग गणना की जाती है। मुझे उम्मीद है कि कोड भी मुश्किल नहीं है अंततः यह मैक्रोज़ का बहुत उपयोग करता है । mainजेवीएम को गर्म करने के लिए मेरी परीक्षा कुछ समय चलती है।

अद्यतन: केवल आधे से अधिक पूर्णांकों में परिवर्तन, समरूपता के कारण समान परिणाम प्राप्त करता है। साथ ही संख्या के निचले आधे भाग पर उच्च बिट संख्या के साथ लंघन संख्याओं के साथ-साथ वे डुप्लिकेट का भी उत्पादन करते हैं।

पूर्व-निर्मित uberjar ( v1 ) (3.7 एमबी):

$ wget https://s3-eu-west-1.amazonaws.com/nikonyrh-public/misc/so-124424-v2.jar
$ java -jar so-124424-v2.jar 29
Calculating f(n) from 1 to 29 (inclusive) 5 times
(1 1 2 4 6 8 14 18 27 36 52 65 93 113 150 188 241 279 377 427 540 632 768 870 1082 1210 1455 1656 1974)
"Elapsed time: 41341.863703 msecs"
(1 1 2 4 6 8 14 18 27 36 52 65 93 113 150 188 241 279 377 427 540 632 768 870 1082 1210 1455 1656 1974)
"Elapsed time: 37752.118265 msecs"
(1 1 2 4 6 8 14 18 27 36 52 65 93 113 150 188 241 279 377 427 540 632 768 870 1082 1210 1455 1656 1974)
"Elapsed time: 38568.406528 msecs"
[ctrl+c]

विभिन्न हार्डवेयर पर परिणाम, अपेक्षित रनटाइम है O(n * 2^n)?

i7-6700K  desktop: 1 to 29 in  38 seconds
i7-6820HQ laptop:  1 to 29 in  43 seconds
i5-3570K  desktop: 1 to 29 in 114 seconds

आप आसानी से इस सिंगल-थ्रेड को बना सकते हैं और इसके लिए मानक का उपयोग करके उस 3 पार्टी निर्भरता से बच सकते हैं:

(for [start (range 0 end-idx step)]
  ... )

वैसे बिल्ट-इन pmap भी मौजूद है लेकिन क्लेम्पोल में अधिक विशेषताएं और ट्यूनेबिलिटी है।


हाँ, यह वितरित करने के लिए तुच्छ बनाता है। क्या आपके पास मेरे समाधान का पुनर्मूल्यांकन करने का समय है, मुझे पूरा यकीन है कि अब आप इसे 30 तक ले लेंगे। मेरी दृष्टि में और अधिक अनुकूलन नहीं हैं।
निकोनिर

अफसोस की बात है कि यह 30 के लिए नहीं है। बीता हुआ समय: 217150.87386 मिसे

अहा, यह एक कोशिश देने के लिए धन्यवाद: D इस पर एक वक्र फिट करना बेहतर हो सकता है और प्रक्षेपित किया जा सकता है, जिस पर दशमलव मान 120 सेकंड खर्च होता है, लेकिन यहां तक ​​कि यह एक अच्छा चालान है।
निकोनिरह

1

गणितज्ञ, एन = १ ९

प्रेस alt +। निरस्त करने के लिए और परिणाम मुद्रित किया जाएगा

k = 0;
For[n = 1, n < 1000, n++,
Z = Table[HammingDistance[#[[;; i]], #[[-i ;;]]], {i, Length@#}] & /@
Tuples[{0, 1}, n];
Table[If[Z[[i, j]] < 2, Z[[i, j]] = 0, Z[[i, j]] = 1], {i, 
Length@Z}, {j, n}];
k = Length@Union@Z]
Print["f(", n, ")=", k]

मैं इसे नहीं चला सकता, तो क्या आप बता सकते हैं कि यह घातीय समय लेने से कैसे बचा जाता है? 2 ^ 241 एक बहुत बड़ी संख्या है!

क्या आप कोड का आउटपुट दिखा सकते हैं?

1
मेरा मतलब था f (n) ... फिक्स्ड
J42161217

1

गणितज्ञ, २१

f [n_]: = लंबाई @
     DeleteDuplicates @
      स्थानांतरित @
       टेबल [2> ट्र @ इंटेगरडिजिट्स [#, 2] और / @ 
         BitXor [BitShiftRight [#, n - i], Mod [#, 2 ^ i]], {, 1, 1 
         n - 1}] & @ रेंज [0, 2 ^ (n - 1)];
[Print [n -> f @ n], {n, Infinity}] प्रिंट करें

तुलना के लिए, जेनी_मैथी का जवाबn = 19 मेरे कंप्यूटर पर देता है ।

सबसे धीमा हिस्सा है Tr@IntegerDigits[#, 2] &। यह शर्म की बात है कि गणितज्ञ के पास वजन कम करने के लिए बिल्ट-इन नहीं है।


यदि आप मेरे कोड का परीक्षण करना चाहते हैं, तो आप Mathematica का निःशुल्क परीक्षण डाउनलोड कर सकते हैं ।


1

एसी संस्करण, बिलिन पॉपकाउंट का उपयोग करते हुए

के साथ बेहतर clang -O3काम करता है, लेकिन यह भी काम करता है अगर आप केवल है gcc

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

unsigned long pairs(unsigned int n, unsigned long s) { 
  unsigned long result = 0;

  for(int d=1;d<=n;d++) { 
    unsigned long mx = 1 << d;
    unsigned long mask = mx - 1;

    unsigned long diff = (s >> (n - d)) ^ (s & mask);
    if (__builtin_popcountl(diff) <= 1)
      result |= mx;
  } 
  return result;

}

unsigned long f(unsigned long  n) { 
  unsigned long max = 1 << (n - 1);
#define BLEN (max / 2)
  unsigned char * buf = malloc(BLEN);
  memset(buf, 0, BLEN);
  unsigned long long * bufll = (void *) buf;

  for(unsigned long i=0;i<=max;i++) { 
    unsigned int r = pairs(n, i);
    buf[r / 8] |= 1 << (r % 8);
  } 

  unsigned long result = 0;

  for(unsigned long i=0;i<= max / 2 / sizeof(unsigned long long); i++) { 
    result += __builtin_popcountll(bufll[i]);
  } 

  free(buf);

  return result;
}

int main(int argc, char ** argv) { 
  unsigned int n = 1;

  while(1) { 
    printf("%d %ld\n", n, f(n));
    n++;
  } 
  return 0;
}

यह बहुत जल्दी 24 हो जाता है और फिर समाप्त हो जाता है। आपको सीमा बढ़ाने की आवश्यकता है।

हे भगवान, मैं बेंचमार्क कोड हटाना भूल गया! मैं दो आक्रामक पंक्तियों को हटा दूंगा: /
bartvelle

@ लेम्बिक को अब तय किया जाना चाहिए
बरटावेल

1

हास्केल, (अनौपचारिक n = 20)

यह सिर्फ भोली दृष्टिकोण है - अब तक बिना किसी अनुकूलन के। मैंने सोचा कि यह अन्य भाषाओं के मुकाबले कितना अच्छा होगा।

इसका उपयोग कैसे करें (यह मानते हुए कि आपके पास हैस्केल प्लेटफॉर्म स्थापित है):

  • कोड को एक फ़ाइल में पेस्ट करें approx_corr.hs(या किसी अन्य नाम के अनुसार, निम्नलिखित चरणों को संशोधित करें)
  • फ़ाइल पर नेविगेट करें और निष्पादित करें ghc approx_corr.hs
  • Daud approx_corr.exe
  • अधिकतम दर्ज करें n
  • प्रत्येक गणना का परिणाम प्रदर्शित होता है, साथ ही उस बिंदु तक संचयी वास्तविक समय (एमएस में)।

कोड:

import Data.List
import Data.Time
import Data.Time.Clock.POSIX

num2bin :: Int -> Int -> [Int]
num2bin 0 _ = []
num2bin n k| k >= 2^(n-1) = 1 : num2bin (n-1)( k-2^(n-1))
           | otherwise  = 0: num2bin (n-1) k

genBinNum :: Int -> [[Int]]
genBinNum n = map (num2bin n) [0..2^n-1]

pairs :: [a] -> [([a],[a])]
pairs xs = zip (prefixes xs) (suffixes xs)
   where prefixes = tail . init . inits 
         suffixes = map reverse . prefixes . reverse 

hammingDist :: (Num b, Eq a) => ([a],[a]) -> b     
hammingDist (a,b) = sum $ zipWith (\u v -> if u /= v then 1 else 0) a b

f :: Int -> Int
f n = length $ nub $ map (map ((<=1).hammingDist) . pairs) $ genBinNum n
--f n = sum [1..n]

--time in milliseconds
getTime = getCurrentTime >>= pure . (1000*) . utcTimeToPOSIXSeconds >>= pure . round


main :: IO()
main = do 
    maxns <- getLine 
    let maxn = (read maxns)::Int
    t0 <- getTime 
    loop 1 maxn t0
     where loop n maxn t0|n==maxn = return ()
           loop n maxn t0
             = do 
                 putStrLn $ "fun eval: " ++ (show n) ++ ", " ++ (show $ (f n)) 
                 t <- getTime
                 putStrLn $ "time: " ++ show (t-t0); 
                 loop (n+1) maxn t0

ऐसा प्रतीत होता है कि कोड आउटपुट नहीं देता है क्योंकि यह चलता है। इससे परीक्षण करना थोड़ा कठिन हो जाता है।

अजीब है, क्या यह त्रुटि के बिना संकलन करता है? यदि आप कार्यक्रम को संकलित करने का प्रयास करते हैं तो क्या होता है main = putStrLn "Hello World!"?
दोष

Data.Bitsमॉड्यूल उपयोगी हो सकता है। अपने मुख्य लूप के लिए, आप main = do maxn <- getmax; t0 <- gettime; loop 1जहां loop n|n==maxn = return ()और जैसे कुछ का उपयोग कर सकते हैं loop n = do printresult n (f n); t <- gettime; printtime (t-t0); loop (n+1)getmaxउदाहरण के लिए getArgsकार्यक्रम तर्कों का उपयोग करने के लिए उपयोग कर सकते हैं।
क्रिश्चियन सिवर्स

@ChristianSievers बहुत बहुत धन्यवाद !!! मैंने स्टैकओवरफ्लो में यह सवाल पूछा , मुझे लगता है कि यह बहुत अच्छा होगा यदि आप इसे भी जोड़ सकते हैं!
11

मैं नहीं देखता कि वहाँ कैसे उत्तर दूं। आपके पास पहले से ही एक समान लूप है, और मैंने समय प्राप्त करने के बारे में कुछ नहीं कहा: आप पहले से ही यहां थे।
क्रिश्चियन सिवर्स

1

पॉपकाउंट का उपयोग करके एक हास्केल समाधान, और मैन्युअल रूप से प्रबंधित समानता

संकलित करें: ghc -rtsopts -threaded -O2 -fllvm -Wall foo.hs

(ड्रॉप -llvmअगर यह काम नहीं करता है)

Daud : ./foo +RTS -N

module Main (main) where

import Data.Bits
import Data.Word
import Data.List
import qualified Data.IntSet as S 
import System.IO
import Control.Monad
import Control.Concurrent
import Control.Exception.Base (evaluate)

pairs' :: Int -> Word64 -> Int
pairs' n s = fromIntegral $ foldl' (.|.) 0 $ map mk [1..n]
  where mk d = let mask = 1 `shiftL` d - 1 
                   pc = popCount $! xor (s `shiftR` (n - d)) (s .&. mask)
               in  if pc <= 1 
                     then mask + 1 
                     else 0 

mkSet :: Int -> Word64 -> Word64 -> S.IntSet
mkSet n a b = S.fromList $ map (pairs' n) [a .. b]

f :: Int -> IO Int
f n 
   | n < 4 = return $ S.size $ mkSet n 0 mxbound
   | otherwise = do
        mvs <- replicateM 4 newEmptyMVar
        forM_ (zip mvs cpairs) $ \(mv,(mi,ma)) -> forkIO $ do
          evaluate (mkSet n mi ma) >>= putMVar mv
        set <- foldl' S.union S.empty <$> mapM readMVar mvs
        return $! S.size set
   where
     mxbound = 1 `shiftL` (n - 1)
     bounds = [0,1 `shiftL` (n - 3) .. mxbound]
     cpairs = zip bounds (drop 1 bounds)

main :: IO()
main = do
    hSetBuffering stdout LineBuffering
    mapM_ (f >=> print) [1..]

एक बफ़रिंग की समस्या है, ऐसा लगता है कि मुझे कोई भी आउटपुट नहीं मिलता है अगर मैं इसे साइबरवाइम कमांड लाइन से चलाता हूं।

मैंने अभी-अभी अपना समाधान अपडेट किया है, लेकिन मुझे नहीं पता कि इससे बहुत मदद मिलेगी।
बर्तवेल्ले

@Lembik Unsure यदि यह स्पष्ट है, लेकिन इसका संकलन किया जाना चाहिए -O3, और इसके साथ तेज़ हो सकता है -O3 -fllvm...
bartvelle

(और सभी बिल्ड फ़ाइलों को recompiling करने से पहले हटा दिया जाना चाहिए, यदि स्रोत कोड परिवर्तन नहीं हुआ है)
bartvelle

@ लेम्बिक: मैंने समानता का परिचय दिया। यह थोड़ा तेज होना चाहिए।
बर्तवेल्ले

0

अजगर 2 + pypy, एन = 22

यहाँ बेसलाइन बेंचमार्क के रूप में एक बहुत ही सरल पायथन समाधान है।

import itertools
def hamming(A, B):
    n = len(A)
    assert(len(B) == n)
    return n-sum([A[i] == B[i] for i in xrange(n)])

def prefsufflist(P):
    n = len(P)
    return [hamming(P[:i], P[n-i:n]) for i in xrange(1,n+1)]

bound = 1
for n in xrange(1,25):
    booleans = set()
    for P in itertools.product([0,1], repeat = n):
        booleans.add(tuple(int(HD <= bound) for HD in prefsufflist(P)))
    print "n = ", n, len(booleans)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.