diff --git a/src/Math-KolmogorovSmirnov/PMKolmogorovSmirnov1Sample.class.st b/src/Math-KolmogorovSmirnov/PMKolmogorovSmirnov1Sample.class.st index 3eeea2e17..d174563b4 100644 --- a/src/Math-KolmogorovSmirnov/PMKolmogorovSmirnov1Sample.class.st +++ b/src/Math-KolmogorovSmirnov/PMKolmogorovSmirnov1Sample.class.st @@ -32,43 +32,41 @@ PMKolmogorovSmirnov1Sample class >> data: aCollection [ ^self new data: aCollection ;yourself ] -{ #category : #accessing } -PMKolmogorovSmirnov1Sample >> cdf: aBlock [ -"the cumulative distribution function to be used. can also be set via #populationDistribution:" -popDistribution:=nil. -compareWith := aBlock -] - { #category : #accessing } PMKolmogorovSmirnov1Sample >> data: aCollection [ -distribution := PMKolmogorovsDistribution exampleSize: aCollection size. -^data := aCollection asSortedCollection . + distribution := PMKolmogorovsDistribution + exampleSize: aCollection size. + ^ data := aCollection asSortedCollection ] { #category : #accessing } PMKolmogorovSmirnov1Sample >> ksStatistic [ -"the kolmogorov-smirnov statistic D" -|s d| -self testDataComplete . -s:=data size. -d:=(1 to:s) collect: [:i||f| f:=compareWith value:(data at:i).(f -((i-1)/s))max: ((i/s)-f)]. -^d max. + "the kolmogorov-smirnov statistic D" + | s d | + s := data size. + d := (1 to: s) + collect: [ :i | + | f | + f := compareWith value: (data at: i). + f - ((i - 1) / s) max: i / s - f ]. + ^ d max ] { #category : #accessing } PMKolmogorovSmirnov1Sample >> pValue [ -"the probability of getting a ksStatistic <= the actual one" -^distribution distributionValue: self ksStatistic . + "the probability of getting a ksStatistic <= the actual one" + ^ distribution distributionValue: self ksStatistic ] { #category : #accessing } PMKolmogorovSmirnov1Sample >> populationDistribution: aDistribution [ -"utility, a simple alternative method to set cdf." -popDistribution:=aDistribution. -popDistribution distributionValue: 0.95."just a test whether it understands #distributionValue:, to raise a dnu early enough because of this block:" -compareWith :=[:x|popDistribution distributionValue:x ] + "utility, a simple alternative method to set cdf." + + popDistribution := aDistribution. + popDistribution distributionValue: 0.95. "just a test whether it understands #distributionValue:, to raise a dnu early enough because of this block:" + compareWith := [ :x | popDistribution distributionValue: x ] ] { #category : #printing } diff --git a/src/Math-KolmogorovSmirnov/PMKolmogorovSmirnov2Sample.class.st b/src/Math-KolmogorovSmirnov/PMKolmogorovSmirnov2Sample.class.st index d717e93c3..0791765c8 100644 --- a/src/Math-KolmogorovSmirnov/PMKolmogorovSmirnov2Sample.class.st +++ b/src/Math-KolmogorovSmirnov/PMKolmogorovSmirnov2Sample.class.st @@ -38,91 +38,126 @@ PMKolmogorovSmirnov2Sample class >> compareData: aCollection withData: anotherCo ] { #category : #private } -PMKolmogorovSmirnov2Sample >> cFrom:i and:j [ -"needs ksStatistic!" -^ (i/smallSize -(j/bigSize))abs < ksStatistic ifTrue:[1]ifFalse:[0] +PMKolmogorovSmirnov2Sample >> cFrom: i and: j [ + "needs ksStatistic!" + ^ (i / smallSize - (j / bigSize)) abs < ksStatistic + ifTrue: [ 1 ] + ifFalse: [ 0 ] ] { #category : #accessing } PMKolmogorovSmirnov2Sample >> data: aCollection [ -ksStatistic:=nil. -^self makeCDFOf: aCollection intoFirst: true . + ksStatistic := nil. + ^ self makeCDFOf: aCollection intoFirst: true ] { #category : #initialization } PMKolmogorovSmirnov2Sample >> initCachedUCalculation [ -"recursive calc, slow without memoization" -uCalcBlock:=[:iandj||cij i j| -i:=iandj first.j:=iandj second. -cij:=self cFrom: i and: j. -i*j=0 - ifTrue:[ cij] - ifFalse:[cij * ((uCalcBlock value:{i.j-1})+(uCalcBlock value:{i-1.j}))]]memoized. + "recursive calc, slow without memoization" + + uCalcBlock := [ :iandj | + | cij i j | + i := iandj first. + j := iandj second. + cij := self cFrom: i and: j. + i * j = 0 + ifTrue: [ cij ] + ifFalse: [ cij + * + ((uCalcBlock + value: + {i. + (j - 1)}) + + + (uCalcBlock + value: + {(i - 1). + j})) ] ] memoized ] { #category : #initialization } PMKolmogorovSmirnov2Sample >> initKSStatistic [ | t | - ksStatistic :=0. - self initCachedUCalculation. "needs to be set lately, iow here" + ksStatistic := 0. + self initCachedUCalculation. "needs to be set lately, iow here" smallSize := data size. bigSize := compareWith size. - smallSize > bigSize ifFalse: [ ^ self ]. + smallSize > bigSize + ifFalse: [ ^ self ]. t := smallSize. smallSize := bigSize. - bigSize := t. - + bigSize := t ] { #category : #accessing } PMKolmogorovSmirnov2Sample >> ksStatistic [ -"the kolmogorov-smirnov statistic D" -|c1 c2 cdfs s| -self testDataComplete . -self initKSStatistic . -c1:=0. c2:=0. -s:=smallSize + bigSize. -cdfs := (SortedCollection new:s) addAll: data; addAll: compareWith; yourself. -cdfs withIndexDo: [:a :i| - (i> makeCDFOf: aCollection intoFirst: aBoolean [ -"if aCollection consists of numbers, + "if aCollection consists of numbers, it returns a sorted array of (number->{cdf.aBoolean})" -|cd s result| -cd:=0. -s:=aCollection size. -result:=aCollection asBag sortedElements do:[:a| - cd:=a value/s+cd. - a value: {cd. aBoolean}]. -^aBoolean ifTrue: [ data:=result ] - ifFalse:[compareWith :=result] + + | cd s result | + cd := 0. + s := aCollection size. + result := aCollection asBag sortedElements + do: [ :a | + cd := a value / s + cd. + a + value: + {cd. + aBoolean} ]. + ^ aBoolean + ifTrue: [ data := result ] + ifFalse: [ compareWith := result ] ] { #category : #accessing } PMKolmogorovSmirnov2Sample >> otherData: aCollection [ -ksStatistic:=nil. -^self makeCDFOf: aCollection intoFirst: false . + ksStatistic := nil. + ^ self makeCDFOf: aCollection intoFirst: false ] { #category : #accessing } PMKolmogorovSmirnov2Sample >> pValue [ -"uses procedure explained in: + "uses procedure explained in: Kim, P. J. & Jennrich, R. I. 'Tables of the exact sampling distribution of the two-sample Kolmogorov–Smirnov criterion...' in 'Selected Tables in Mathematical Statistics Volume I' (1973)." -ksStatistic ifNil: [self ksStatistic ]. -^ (uCalcBlock value: {smallSize.bigSize})/ ((smallSize + bigSize) take:smallSize) + + ksStatistic ifNil: [ self ksStatistic ]. + ^ (uCalcBlock + value: + {smallSize. + bigSize}) / (smallSize + bigSize take: smallSize) ] { #category : #printing } diff --git a/src/Math-KolmogorovSmirnov/PMKolmogorovsDistribution.class.st b/src/Math-KolmogorovSmirnov/PMKolmogorovsDistribution.class.st index 204cddca7..cb00c7004 100644 --- a/src/Math-KolmogorovSmirnov/PMKolmogorovsDistribution.class.st +++ b/src/Math-KolmogorovSmirnov/PMKolmogorovsDistribution.class.st @@ -12,7 +12,7 @@ Class { 'distribution', 'n' ], - #category : 'Math-KolmogorovSmirnov' + #category : #'Math-KolmogorovSmirnov' } { #category : #information } diff --git a/src/Math-Tests-KolmogorovSmirnov/PMKolmogorovSmirnov1sampleTest.class.st b/src/Math-Tests-KolmogorovSmirnov/PMKolmogorovSmirnov1SampleTest.class.st similarity index 84% rename from src/Math-Tests-KolmogorovSmirnov/PMKolmogorovSmirnov1sampleTest.class.st rename to src/Math-Tests-KolmogorovSmirnov/PMKolmogorovSmirnov1SampleTest.class.st index c1edd1c9a..245ef271b 100644 --- a/src/Math-Tests-KolmogorovSmirnov/PMKolmogorovSmirnov1sampleTest.class.st +++ b/src/Math-Tests-KolmogorovSmirnov/PMKolmogorovSmirnov1SampleTest.class.st @@ -20,8 +20,9 @@ PMKolmogorovSmirnov1SampleTest >> numberOfRejectionsFor: aDistribution [ ^ n ] -{ #category : #initialization } +{ #category : #running } PMKolmogorovSmirnov1SampleTest >> setUp [ + super setUp . nd := PMNormalDistribution new. ks := PMKolmogorovSmirnov1Sample new ] @@ -37,10 +38,16 @@ PMKolmogorovSmirnov1SampleTest >> testCorrectPopulationProbabilistic [ { #category : #tests } PMKolmogorovSmirnov1SampleTest >> testRejectOfEqualityHypothesesForSampleVersusDistribution [ - nd := PMNormalDistribution new. "--> Normal distribution( 0, 1)" - ks := PMKolmogorovSmirnov1Sample compareData: ((1 to: 100) collect: [ :i | nd random ]) withDistribution: nd. "--> - a KolmogorovSmirnov(dataSize: 100 cdf: distributionValue of Normal distribution( 0, 1))" - self assert: (ks rejectEqualityHypothesisWithAlpha: 0.05) equals: false + | sample | + "The data below are taken from http://www.maths.qmul.ac.uk/~bb/CTS_Chapter3_Students.pdf" + sample := #(-1.2 0.2 -0.6 0.8 -1.0). + ks := PMKolmogorovSmirnov1Sample + compareData: sample + withDistribution: nd. + + self + assert: (ks rejectEqualityHypothesisWithAlpha: 0.05) + equals: false ] { #category : #tests } diff --git a/src/Math-Tests-KolmogorovSmirnov/PMKolmogorovSmirnov2sampleTest.class.st b/src/Math-Tests-KolmogorovSmirnov/PMKolmogorovSmirnov2SampleTest.class.st similarity index 85% rename from src/Math-Tests-KolmogorovSmirnov/PMKolmogorovSmirnov2sampleTest.class.st rename to src/Math-Tests-KolmogorovSmirnov/PMKolmogorovSmirnov2SampleTest.class.st index 8e0b8fe12..81e1bff62 100644 --- a/src/Math-Tests-KolmogorovSmirnov/PMKolmogorovSmirnov2sampleTest.class.st +++ b/src/Math-Tests-KolmogorovSmirnov/PMKolmogorovSmirnov2SampleTest.class.st @@ -7,23 +7,26 @@ Class { #category : #'Math-Tests-KolmogorovSmirnov' } -{ #category : #initialization } +{ #category : #running } PMKolmogorovSmirnov2SampleTest >> setUp [ + super setUp . k := PMKolmogorovSmirnov2Sample new ] { #category : #tests } PMKolmogorovSmirnov2SampleTest >> testRejectOfEqualityHypothesesForTwoSamples [ - | nd ks | - nd := PMNormalDistribution new. + "The data below are taken from http://www.stats.ox.ac.uk/~massa/Lecture%2013.pdf + According to that paper Dn = 0.6 and Dcrit = 0.645 so the null hypothesis is retained. + " + + | ks | ks := PMKolmogorovSmirnov2Sample - compareData: ((1 to: 100) collect: [ :i | nd random ]) - withData: ((1 to: 100) collect: [ :i | nd random ]). - ks ksStatistic. - ks pValue asFloat. + compareData: #(1.2 1.4 1.9 3.7 4.4 4.8 9.7 17.3 21.1 28.4) + withData: #(5.6 6.5 6.6 6.9 9.2 10.4 10.6 19.3). + self assert: (ks rejectEqualityHypothesisWithAlpha: 0.05) - equals: false + equals: true ] { #category : #tests }