ब्लॉक एन्ट्रापी की गणना करें


12

मुझे एक बार एक फ़ंक्शन लिखने की ज़रूरत थी जो किसी दिए गए ब्लॉक आकार के लिए दिए गए प्रतीक श्रृंखला के ब्लॉक एन्ट्रॉपी की गणना करता है और आश्चर्यचकित था कि परिणाम कितना छोटा था। इस प्रकार मैं आपको ऐसे फ़ंक्शन को कोडगुल्फ़ करने के लिए चुनौती दे रहा हूं। मैं आपको यह नहीं बता रहा हूं कि मैंने अभी (और किस भाषा में) के लिए क्या किया है, लेकिन मैं एक या एक सप्ताह में करूंगा, अगर कोई भी पहले समान या बेहतर विचारों के साथ नहीं आया था।

ब्लॉक एन्ट्रापी की परिभाषा:

एक प्रतीक अनुक्रम A = A_1,…, A_n और एक ब्लॉक आकार m:

  • आकार m का एक खंड किसी भी उपयुक्त i के प्रतीक चिह्न अनुक्रम के निरंतर तत्वों का एक भाग है, अर्थात, A_i,…, A_ (i + m + 1)।
  • यदि x आकार m का प्रतीक अनुक्रम है, N (x) A के ब्लॉक की संख्या को दर्शाता है जो x के समान हैं।
  • p (x) संभावना है कि A से एक ब्लॉक आकार m, यानी p (x) = N (x) / (n + m + 1) के प्रतीक अनुक्रम x के समान है।
  • अंत में, A के ब्लॉक आकार m के लिए ब्लॉक एन्ट्रापी plog (p (x)) का औसत है, जो A या (जो समतुल्य है) के सभी ब्लॉक x का आकार (p (x) का योग है · लॉग (p) (x)) ए में होने वाले आकार के प्रत्येक x पर (आप कोई भी उचित लघुगणक चुन सकते हैं।)

प्रतिबंध और स्पष्टीकरण:

  • आपके फ़ंक्शन को प्रतीक अनुक्रम ए के साथ-साथ ब्लॉक आकार मीटर को एक तर्क के रूप में लेना चाहिए।
  • आप मान सकते हैं कि प्रतीकों को शून्य-आधारित पूर्णांक या किसी अन्य सुविधाजनक प्रारूप के रूप में दर्शाया गया है।
  • आपका कार्यक्रम सिद्धांत में किसी भी उचित तर्क को लेने में सक्षम होना चाहिए और वास्तव में एक मानक कंप्यूटर पर उदाहरण के मामले (नीचे देखें) की गणना करने में सक्षम होना चाहिए।
  • अंतर्निहित कार्यों और पुस्तकालयों को अनुमति दी जाती है, जब तक कि वे एक कॉल में प्रक्रिया के बड़े हिस्से का प्रदर्शन नहीं करते हैं, अर्थात, ए से आकार एम के सभी ब्लॉकों को निकालना, किसी दिए गए ब्लॉक x की घटनाओं की संख्या की गिनती करना या एंट्रोपियों की गणना करना। p मानों के अनुक्रम से - आपको स्वयं उन चीजों को करना होगा।

परीक्षा:

[2, 3, 4, 1, 2, 3, 0, 0, 3, 2, 3, 0, 2, 2, 4, 4, 4, 1, 1, 1, 0, 4, 1,
2, 2, 4, 0, 1, 2, 3, 0, 2, 3, 2, 3, 2, 0, 1, 3, 4, 4, 0, 2, 1, 4, 3,
0, 2, 4, 1, 0, 4, 0, 0, 2, 2, 0, 2, 3, 0, 0, 4, 4, 2, 3, 1, 3, 1, 1,
3, 1, 3, 1, 0, 0, 2, 2, 4, 0, 3, 2, 2, 3, 0, 3, 3, 0, 0, 4, 4, 1, 0,
2, 3, 0, 0, 1, 4, 4, 3]

इस क्रम की पहली ब्लॉक एंट्रॉपी हैं (प्राकृतिक लघुगणक के लिए):

  • एम = 1: 1.599
  • m = 2: 3.065
  • एम = 3: 4.067
  • m = 4: 4.412
  • m = 5: 4.535
  • m = 6: 4.554

@ m.buettner: यदि आप मेरे नियमों के बारे में अपनी समाधान सीमा रेखा पर विचार करते हैं, तो आप अभी भी इसे आजमा सकते हैं - मैं वास्तव में केवल लाइनों के साथ समाधान से बचना चाहता हूं entropy(probabilities(blocks(A,m)))
::

क्या इसके लिए लॉग बेस 2 का उपयोग करना प्रथागत नहीं है?
जोनाथन वान मैट्रे

अंत में एन्ट्रापी के लिए मूल्य सकारात्मक हैं, लेकिन एक संभावना का लघुगणक नकारात्मक या शून्य है। इसलिए एन्ट्रापी के सूत्र में एक नकारात्मक संकेत गायब है।
हेइको ओबर्डिएक

@JonathanVanMatre: जहां तक ​​मुझे पता है, यह उस अनुशासन पर निर्भर करता है जो लघुगणक का सबसे अधिक उपयोग किया जाने वाला पृष्ठ है। वैसे भी, यह चुनौती के लिए ज्यादा मायने नहीं रखता है और इस प्रकार आप जो चाहे आधार का उपयोग कर सकते हैं।
१६:४४ पर १६:१४

@ हेइकोऑर्डीकेक: धन्यवाद, मैं यह भूल गया।
Wrzlprmft

जवाबों:


6

गणितज्ञ - 81 78 75 72 67 65 62 56 बाइट्स

मैंने इससे पहले गणितज्ञ में कुछ भी नहीं किया है, इसलिए मुझे लगता है कि इसमें सुधार की गुंजाइश है। यह नियमों Partitionऔर Tallyकार्यों के कारण नियमों के अनुरूप नहीं है , लेकिन यह काफी साफ-सुथरा है, इसलिए मैंने सोचा कि मैं इसे वैसे भी पोस्ट करूंगा।

f=N@Tr[-Log[p=#2/Length@b&@@@Tally[b=##~Partition~1]]p]&

यह प्रतीकों के किसी भी सेट के साथ काम करता है, और जैसे इस्तेमाल किया जा सकता है

sequence = {2, 3, 4, 1, 2, 3, 0, 0, 3, 2, 3, 0, 2, 2, 4, 4, 4, 1, 1, 
   1, 0, 4, 1, 2, 2, 4, 0, 1, 2, 3, 0, 2, 3, 2, 3, 2, 0, 1, 3, 4, 4, 
   0, 2, 1, 4, 3, 0, 2, 4, 1, 0, 4, 0, 0, 2, 2, 0, 2, 3, 0, 0, 4, 4, 
   2, 3, 1, 3, 1, 1, 3, 1, 3, 1, 0, 0, 2, 2, 4, 0, 3, 2, 2, 3, 0, 3, 
   3, 0, 0, 4, 4, 1, 0, 2, 3, 0, 0, 1, 4, 4, 3};
f[sequence, 3]

> 4.06663

यहाँ कुछ असम्बद्ध संस्करण है:

f[sequence_, m_] := (
    blocks = Partition[sequence, m, 1];
    probabilities = Apply[#2/Length[blocks] &, Tally[blocks], {1}];
    N[Tr[-Log[probabilities]*probabilities]]
)

अगर मैं Nइसके परिणाम पर सीधे आवेदन करता हूं तो यह संभवत: तेजी से चलेगा Tally

वैसे, गणितज्ञ के पास वास्तव में एक Entropyफ़ंक्शन होता है, जो इसे 28 बाइट्स तक कम कर देता है , लेकिन यह निश्चित रूप से नियमों के खिलाफ है।

f=N@Entropy@Partition[##,1]&

दूसरी ओर, एक 128 बाइट संस्करण है जो पुन : लागू होता है Partitionऔर Tally:

f=N@Tr[-Log[p=#2/n&@@@({#[[i;;i+#2-1]],1}~Table~{i,1,(n=Length@#-#2+1)}//.{p___,{s_,x_},q___,{s_,y_},r___}:>{p,{s,x+y},q,r})]p]&

Ungolfed:

f[sequence_, m_] := (
    n = Length[sequence]-m+1; (*number of blocks*)
    blocks = Table[{Take[sequence, {i, i+m-1}], 1},
                   {i, 1, n}];
    blocks = b //. {p___, {s_, x_}, q___, {s_, y_}, r___} :> {p,{s,x+y},q,r};
    probabilities = Apply[#2/n &, blocks, {1}];
    N[Tr[-Log[probabilities]*probabilities]]
)

Partitionऔर Tallyसीमावर्ती मामले नहीं हैं, वे नियमों को एक समान रूप से तोड़ रहे हैं, क्योंकि वे "ए से आकार एम के सभी ब्लॉक निकाल रहे हैं" और "एक दिए गए ब्लॉक एक्स की घटनाओं की संख्या की गिनती", क्रमशः एक कॉल में। फिर भी, आखिरकार मुझे गणितज्ञ के बारे में पता है, मुझे आश्चर्य नहीं होगा, अगर उनके बिना एक सभ्य समाधान था।
१०'१४

1
@Wrzlprmft मैंने एक गैर-गोल्फ संस्करण जोड़ा है जहां मैं पुन: लागू करता हूं Partitionऔर Tally
मार्टिन एंडर

3

पर्ल, 140 बाइट्स

निम्न पर्ल स्क्रिप्ट एक फ़ंक्शन को परिभाषित करती Eहै जो प्रतीक अनुक्रम लेता है, इसके बाद खंड आकार तर्क के रूप में होता है।

sub E{$m=pop;$E=0;%h=();$"=',';$_=",@_,";for$i(0..@_-$m){next
if$h{$s=",@_[$i..$i+$m-1],"}++;$E-=($p=s|(?=$s)||g/(@_-$m+1))*log$p;}return$E}

परीक्षण के साथ Ungolfed संस्करण

sub E { # E for "entropy"
    # E takes the sequence and segment size as arguments
    # and returns the calculated entropy.
    $m = pop;    # get segment size (last argument)
    $E = 0;      # initialize entropy
    %h = ();     # hash that remembers already calculated segments
    $" = ',';#"  # comma is used as separator
    $_ = ",@_,"; # $_ takes sequence as string, with comma as delimiters
    for $i (0 .. @_-$m) {
        $s = ",@_[$i..$i+$m-1],"; # segment
        next if$h{$s}++;          # check, if this segment is already calculated
        $p = s|(?=\Q$s\E)||g / (@_ - $m + 1); # calculate probability
             # N(x) is calculated using the substitution operator
             # with a zero-width look-ahead pattern
             # (golfed version without "\Q...\E", see below)
        $E -= $p * log($p); # update entropy
    }
    return $E
}

# Test

my @A = (
    2, 3, 4, 1, 2, 3, 0, 0, 3, 2, 3, 0, 2, 2, 4, 4, 4, 1, 1, 1, 0, 4, 1,
    2, 2, 4, 0, 1, 2, 3, 0, 2, 3, 2, 3, 2, 0, 1, 3, 4, 4, 0, 2, 1, 4, 3,
    0, 2, 4, 1, 0, 4, 0, 0, 2, 2, 0, 2, 3, 0, 0, 4, 4, 2, 3, 1, 3, 1, 1,
    3, 1, 3, 1, 0, 0, 2, 2, 4, 0, 3, 2, 2, 3, 0, 3, 3, 0, 0, 4, 4, 1, 0,
    2, 3, 0, 0, 1, 4, 4, 3
);

print "m = $_: ", E(@A, $_), "\n" for 1 .. @A;

परिणाम:

m = 1: 1.59938036027528
m = 2: 3.06545141203611
m = 3: 4.06663334311518
m = 4: 4.41210802885304
m = 5: 4.53546705894451
m = 6: 4.55387689160055
m = 7: 4.54329478227001
m = 8: 4.53259949315326
m = 9: 4.52178857704904
...
m = 97: 1.38629436111989
m = 98: 1.09861228866811
m = 99: 0.693147180559945
m = 100: 0

प्रतीक:

प्रतीकों को पूर्णांक तक सीमित नहीं किया गया है, क्योंकि स्ट्रिंग्स के आधार पर पैटर्न मिलान का उपयोग किया जाता है। एक प्रतीक के स्ट्रिंग प्रतिनिधित्व में अल्पविराम नहीं होना चाहिए, क्योंकि यह सीमांकक के रूप में उपयोग होता है। बेशक, अलग-अलग प्रतीकों में अलग-अलग स्ट्रिंग प्रतिनिधित्व होना चाहिए।

गोल्फ संस्करण में, प्रतीकों के स्ट्रिंग प्रतिनिधित्व में पैटर्न के विशेष वर्ण नहीं होने चाहिए। अतिरिक्त चार बाइट्स \Q... \E संख्याओं के लिए आवश्यक नहीं हैं।


1/4 छोटा हो सकता है sub f{($s,$m,$r,%h)=@_;$h{x,@$s[$_..$_+$m-1]}++for 0..@$s-$m;$r-=($_/=@$s-$m+1)*log for values %h;return$r}:; जहां $sएक संदर्भ है, $rऔर 1 असाइनमेंट के साथ अनिर्धारित%h करने के लिए रीसेट किया गया है, सूची हैश कीज़ (थोड़ी मदद के साथ , और कुछ - दुर्भाग्य से) हैं, और सामान्य रूप से थोड़ा कम जटिल है, मुझे लगता है। $;x
user2846289

@VadimR: चतुर! मेरे द्वारा सुझाए गए महत्वपूर्ण परिवर्तनों के कारण, आप एक उत्तर दें। स्थान की values %hआवश्यकता नहीं है, इस प्रकार आपके समाधान को केवल 106 बाइट्स की आवश्यकता है।
हेइको ओबर्डिएक

2

पायथन 127 152B 138B

import math
def E(A,m):N=len(A)-m+1;R=range(N);return sum(math.log(float(N)/b) for b in [sum(A[i:i+m]==A[j:j+m] for i in R) for j in R])/N

नियमों को किसी भी अधिक नहीं तोड़ने के लिए समायोजित किया गया है और थोड़ा सा एल्गोरिथ्म है। छोटा होने के लिए समायोजित

पुराना संस्करण:

import math
def E(A,m):
 N=len(A)-m+1
 B=[A[i:i+m] for i in range(N)]
 return sum([math.log(float(N)/B.count(b)) for b in B])/N

मेरी पहली पायथन स्क्रिप्ट! इसे कार्रवाई में देखें: http://pythonfiddle.com/entropy


अब तक अच्छा है, लेकिन दुर्भाग्य से, countफ़ंक्शन का उपयोग नियमों के विरुद्ध एकमुश्त है, क्योंकि यह "किसी दिए गए ब्लॉक x की घटनाओं की संख्या की गिनती" है।
Wrzlprmft

इसके अलावा, कुछ गोल्‍फिंग टिप्‍स: आप पहली बार को छोड़कर ( ;यदि आवश्‍यक हो तो अलग करके ) हर लाइन को क्रैमिंग करके कुछ अक्षर बचा सकते हैं । इसके अलावा अंतिम पंक्ति में वर्ग कोष्ठक की जरूरत नहीं है।
Wrzlprmft

अच्छा जवाब। फिर से, कुछ गोल्फ युक्तियाँ: बूलियन से पूर्णांक (यानी, and 1 or 0) में संपूर्ण रूपांतरण अनावश्यक है। इसके अलावा, आप कुछ पात्रों को पूर्वनिर्धारित करके बचा सकते हैं range(N)
११:४२

1

पाइथन विद नेम्पी, 146 143 बाइट्स

जैसा कि वादा किया गया था, यहाँ मेरा अपना समाधान है। इसके लिए गैर-नकारात्मक पूर्णांकों के इनपुट की आवश्यकता होती है:

from numpy import*
def e(A,m):
    B=zeros(m*[max(A)+1]);j=0
    while~len(A)<-j-m:B[tuple(A[j:j+m])]+=1;j+=1
    return -sum(x*log(x)for x in B[B>0]/j)

नुकसान यह है कि यह आपकी याददाश्त को एक बड़े पैमाने पर तोड़ देता है mया max(A)

यहाँ ज्यादातर अधूरा और टिप्पणी संस्करण है:

from numpy import *
def e(A,m):
    B = zeros(m*[max(A)+1])          # Generate (max(A)+1)^m-Array of zeroes for counting.
    for j in range(len(A)-m+1):
        B[tuple(A[j:j+m])] += 1      # Do the counting by directly using the array slice
                                     # for indexing.
    C = B[B>0]/(len(A)-m+1)          # Flatten array, take only non-zero entries,
                                     # divide for probability.
    return -sum(x*log(x) for x in C) # Calculate entropy

1

Matlab

function E =BlockEntropy01(Series,Window,Base )

%-----------------------------------------------------------
% Calculates BLOCK ENTROPY of Series
% Series: a Vector of numbers
% Base: 2 or 10 (affects logarithm of the Calculation)
% for 2 we use log2, for 10 log10
% Windows: Length of the "Sliding" BLOCK
% E: Entropy
%-----------------------------------------------------------
% For the ENTROPY Calculations
% http://matlabdatamining.blogspot.gr/2006/....
% 11/introduction-to-entropy.html
% BlogSpot: Will Dwinnell
%-----------------------------------------------------------
% For the BLOCK ENTROPY
% http://codegolf.stackexchange.com/...
% questions/24316/calculate-the-block-entropy
%-----------------------------------------------------------
% Test (Base=10)
% Series=[2, 3, 4, 1, 2, 3, 0, 0, 3, 2, 3, 0, ....
%     2, 2, 4, 4, 4, 1, 1, 1, 0, 4, 1,2, 2, 4, 0, ....
%     1, 2, 3, 0, 2, 3, 2, 3, 2, 0, 1, 3, 4, 4, 0, ....
%     2, 1, 4, 3,0, 2, 4, 1, 0, 4, 0, 0, 2, 2, 0, ....
%     2, 3, 0, 0, 4, 4, 2, 3, 1, 3, 1, 1,3, 1, 3, 1, ....
%     0, 0, 2, 2, 4, 0, 3, 2, 2, 3, 0, 3, 3, 0, 0, 4, ...
%     4, 1, 0,2, 3, 0, 0, 1, 4, 4, 3]';
%
% Results 
%
% Window=1: 1.599
% Window=2: 3.065
% Window=3: 4.067
% Window=4: 4.412
% Window=5: 4.535
% Window=6: 4.554
%-----------------------------------------------------------
n=length(Series);
D=zeros(n,Window); % Pre Allocate Memory
for k=1:Window;    D(:,k)=circshift(Series,1-k);end
D=D(1:end-Window+1,:); % Truncate Last Part
%
% Repace each Row with a "SYMBOL"
% in this Case a Number ...............
[K l]=size(D);
for k=1:K; MyData(k)=polyval(D(k,:),Base);end
clear D
%-----------------------------------------------------------
% ENTROPY CALCULATIONS on MyData
% following  Will Dwinnell
%-----------------------------------------------------------
UniqueMyData = unique(MyData);
nUniqueMyData = length(UniqueMyData);
FreqMyData = zeros(nUniqueMyData,1); % Initialization
for i = 1:nUniqueMyData
    FreqMyData(i) = ....
        sum(double(MyData == UniqueMyData(i)));
end
% Calculate sample class probabilities
P = FreqMyData / sum(FreqMyData);
% Calculate entropy in bits
% Note: floating point underflow is never an issue since we are
%   dealing only with the observed alphabet
if Base==10
    E= -sum(P .* log(P));
elseif BASE==2
    E= -sum(P .* log2(P));
else
end
end

WITH TEST SCRIPT 
%-----------------------------------------------------------
Series=[2, 3, 4, 1, 2, 3, 0, 0, 3, 2, 3, 0, ....
    2, 2, 4, 4, 4, 1, 1, 1, 0, 4, 1,2, 2, 4, 0, ....
    1, 2, 3, 0, 2, 3, 2, 3, 2, 0, 1, 3, 4, 4, 0, ....
    2, 1, 4, 3,0, 2, 4, 1, 0, 4, 0, 0, 2, 2, 0, ....
    2, 3, 0, 0, 4, 4, 2, 3, 1, 3, 1, 1,3, 1, 3, 1, ....
    0, 0, 2, 2, 4, 0, 3, 2, 2, 3, 0, 3, 3, 0, 0, 4, ...
    4, 1, 0,2, 3, 0, 0, 1, 4, 4, 3]';
Base=10;
%-----------------------------------------------------------
for Window=1:6
    E =BlockEntropy01(Series,Window,Base )
end

3
PPCG.SE में आपका स्वागत है! यह एक कोड गोल्फ चुनौती है, जहां लक्ष्य संभव के रूप में कुछ पात्रों में एक समस्या को हल करने के लिए है। कृपया उस कोड में टिप्पणियों, न्यूनतम व्हाट्सएप और एकल-वर्ण चर नामों (और किसी भी अन्य शॉर्टकट के बारे में सोच सकते हैं) के साथ-साथ बाइट्स की संख्या भी जोड़ें।
मार्टिन एंडर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.