diff --git a/src/BaselineOfPolyMath/BaselineOfPolyMath.class.st b/src/BaselineOfPolyMath/BaselineOfPolyMath.class.st index d327a9a9e..36a2abd6c 100644 --- a/src/BaselineOfPolyMath/BaselineOfPolyMath.class.st +++ b/src/BaselineOfPolyMath/BaselineOfPolyMath.class.st @@ -21,14 +21,12 @@ BaselineOfPolyMath >> baseline: spec [ spec for: #common do: [ - spec blessing: #baseline. - spec repository: 'github://PolyMathOrg/PolyMath/src'. - spec - baseline: 'SMark' - with: [ spec repository: 'github://smarr/SMark:v1.0.4' ]; - baseline: 'XMLWriter' - with: [ spec - repository: 'github://pharo-contributions/XML-XMLWriter:2.9.x/src' ]. + "External dependencies" + self + sMark: spec; + xmlWriter: spec; + polyMathDataStructures: spec. + spec package: 'ExtendedNumberParser'; package: 'Math-Accuracy-Core'; @@ -37,30 +35,20 @@ BaselineOfPolyMath >> baseline: spec [ package: 'Math-ArbitraryPrecisionFloat' with: [ spec requires: #('ExtendedNumberParser') ]; package: 'Math-AutomaticDifferenciation' - with: [ spec requires: #('Math-Numerical' 'Math-Matrix') ]; + with: [ spec requires: #('Math-Numerical' 'PolyMathDataStructures') ]; package: 'Math-Benchmarks-KDTree' with: [ spec requires: #('Math-KDTree' 'SMark') ]; package: 'Math-Benchmarks-ODE' with: [ spec requires: #('Math-ODE' 'SMark' 'XMLWriter') ]; - package: 'Math-Chromosome' - with: [ spec requires: #('Math-Core') ]; - package: 'Math-Clustering' - with: - [ spec requires: #('Math-Numerical' 'Math-Core-Process' 'Math-Matrix') ]; + package: 'Math-Chromosome' with: [ spec requires: #('PolyMathDataStructures') ]; + package: 'Math-Clustering' with: [ spec requires: #('Math-Numerical' 'Math-Core-Process' 'PolyMathDataStructures') ]; package: 'Math-Complex' with: [ spec requires: #('Math-Numerical' 'Math-Polynomials') ]; - package: 'Math-Core'; - package: 'Math-Core-Distribution' - with: [ spec requires: #('Math-Core') ]; - package: 'Math-Core-Process'; - package: 'Math-Numerical' - with: [ spec - requires: - #('Math-Core' 'Math-Core-Process' 'Math-Core-Distribution' 'Math-DistributionGamma' 'Math-DistributionBeta' 'Math-DistributionForHistogram' 'Math-StatisticalMoments' 'Math-Series') ]; - package: 'Math-Polynomials' - with: [ spec - requires: - #('Math-Core' 'Math-Core-Process' 'Math-Core-Distribution' 'Math-DistributionGamma' 'Math-DistributionBeta' 'Math-DistributionForHistogram' 'Math-StatisticalMoments' 'Math-Series') ]; + package: 'Math-Helpers'; + package: 'Math-Core-Distribution' with: [ spec requires: #('PolyMathDataStructures') ]; + package: 'Math-Core-Process' with: [ spec requires: #('Math-Helpers') ]; + package: 'Math-Numerical' with: [ spec requires: #('PolyMathDataStructures' 'Math-Helpers' 'Math-Core-Process' 'Math-Core-Distribution' 'Math-DistributionGamma' 'Math-DistributionBeta' 'Math-DistributionForHistogram' 'Math-StatisticalMoments' 'Math-Series') ]; + package: 'Math-Polynomials' with: [ spec requires: #('PolyMathDataStructures' 'Math-Helpers' 'Math-Core-Process' 'Math-Core-Distribution' 'Math-DistributionGamma' 'Math-DistributionBeta' 'Math-DistributionForHistogram' 'Math-StatisticalMoments' 'Math-Series') ]; package: 'Math-DistributionBeta' with: [ spec requires: #('Math-DistributionGamma') ]; package: 'Math-DistributionForHistogram' @@ -72,47 +60,32 @@ BaselineOfPolyMath >> baseline: spec [ package: 'Math-FunctionFit' with: [ spec requires: - #('Math-Numerical' 'Math-Chromosome' 'Math-Accuracy-Core' 'Math-Core' 'Math-Matrix' 'Math-Polynomials') ]; + #('Math-Numerical' 'Math-Chromosome' 'Math-Accuracy-Core' 'PolyMathDataStructures' 'Math-Helpers' 'Math-Polynomials') ]; package: 'Math-KDTree'; - package: 'Math-KernelSmoothing' - with: [ spec - requires: #('Math-Quantile' 'Math-Numerical' 'Math-Polynomials') ]; + package: 'Math-KernelSmoothing' with: [ spec requires: #('Math-Quantile' 'Math-Numerical' 'Math-Polynomials') ]; package: 'Math-KolmogorovSmirnov' with: [ spec requires: #('Math-Numerical' 'Math-Polynomials') ]; - package: 'Math-Matrix'; package: 'Math-Number-Extensions'; - package: 'Math-ODE' - with: - [ spec requires: #('Math-Numerical' 'Math-Matrix' 'Math-Polynomials') ]; - package: 'Math-Permutation' - with: [ spec requires: #('Math-Core' 'Math-Matrix' 'Math-Core-Process') ]; + package: 'Math-ODE' with: [ spec requires: #('Math-Numerical' 'PolyMathDataStructures' 'Math-Polynomials') ]; + package: 'Math-Permutation' with: [ spec requires: #('PolyMathDataStructures' 'Math-Core-Process') ]; package: 'Math-Physics-Constants'; - package: 'Math-PrincipalComponentAnalysis' - with: - [ spec requires: #('Math-Numerical' 'Math-Matrix' 'Math-Polynomials') ]; + package: 'Math-PrincipalComponentAnalysis' with: [ spec requires: #('Math-Numerical' 'PolyMathDataStructures' 'Math-Polynomials') ]; package: 'Math-Quantile'; package: 'Math-Quaternion' with: [ spec requires: #('Math-Complex' 'Math-Numerical' 'Math-Polynomials') ]; package: 'Math-Random'; package: 'Math-Series'; - package: 'Math-StatisticalMoments' - with: [ spec requires: #('Math-Core' 'Math-DistributionForHistogram') ]; + package: 'Math-StatisticalMoments' with: [ spec requires: #('Math-Helpers' 'Math-DistributionForHistogram') ]; package: 'Math-TSNE'; package: 'Math-Tests-Accuracy' with: [ spec requires: #('Math-Accuracy-Core') ]; package: 'Math-Tests-ArbitraryPrecisionFloat' with: [ spec requires: #('Math-ArbitraryPrecisionFloat') ]; - package: 'Math-Tests-AutomaticDifferenciation' - with: [ spec requires: #('Math-AutomaticDifferenciation' 'Math-Matrix') ]; - package: 'Math-Tests-Clustering' - with: [ spec - requires: - #('Math-Clustering' 'Math-Core' 'Math-Core-Distribution' 'Math-UtilsDataServer') ]; + package: 'Math-Tests-AutomaticDifferenciation' with: [ spec requires: #('Math-AutomaticDifferenciation' 'PolyMathDataStructures') ]; + package: 'Math-Tests-Clustering' with: [ spec requires: #('Math-Clustering' 'Math-Core-Distribution' 'Math-UtilsDataServer') ]; package: 'Math-Tests-Complex' with: [ spec requires: #('Math-Complex') ]; - package: 'Math-Tests-Core' - with: [ spec requires: #('Math-Core') ]; package: 'Math-Tests-Core-Distribution' with: [ spec requires: #('Math-Core-Distribution') ]; package: 'Math-Tests-Core-Process' @@ -130,10 +103,6 @@ BaselineOfPolyMath >> baseline: spec [ package: 'Math-Tests-KolmogorovSmirnov' with: [ spec requires: #('Math-Numerical' 'Math-KolmogorovSmirnov' 'Math-Polynomials') ]; - package: 'Math-Tests-Matrix' - with: [ spec - requires: - #('Math-Core' 'Math-Numerical' 'Math-StatisticalMoments' 'Math-Matrix' 'Math-Polynomials') ]; package: 'Math-Tests-Number-Extensions' with: [ spec requires: #('Math-Number-Extensions') ]; package: 'Math-Tests-ODE' with: [ spec requires: #('Math-ODE') ]; @@ -159,20 +128,38 @@ BaselineOfPolyMath >> baseline: spec [ with: #('Math-Benchmarks-ODE' 'Math-Benchmarks-KDTree'); group: 'Core' with: - #('Math-Complex' 'Math-Quaternion' 'Math-Numerical' 'Math-Random' 'Math-KDTree' 'Math-ODE' 'Math-ArbitraryPrecisionFloat' 'Math-FastFourierTransform' 'ExtendedNumberParser' 'Math-Quantile' 'Math-Physics-Constants' 'Math-Polynomials' 'Math-TSNE' 'Math-Core-Process' 'Math-Core' 'Math-Core-Distribution'); + #('Math-Complex' 'Math-Quaternion' 'Math-Numerical' 'Math-Random' 'Math-KDTree' 'Math-ODE' 'Math-ArbitraryPrecisionFloat' 'Math-FastFourierTransform' 'ExtendedNumberParser' 'Math-Quantile' 'Math-Physics-Constants' 'Math-Polynomials' 'Math-TSNE' 'Math-Core-Process' 'Math-Helpers' 'PolyMathDataStructures' 'Math-Core-Distribution'); group: 'Extensions' with: #('Math-Clustering' 'Math-Number-Extensions' 'Math-Chromosome' 'Math-PrincipalComponentAnalysis' 'Math-FunctionFit' 'Math-AutomaticDifferenciation' 'Math-KernelSmoothing' 'Math-Permutation' 'Math-KolmogorovSmirnov'); group: 'Tests' with: - #('Math-Tests-Matrix' 'Math-Tests-Clustering' 'Math-Tests-Numerical' 'Math-Tests-Complex' 'Math-Tests-Quaternion' 'Math-Tests-Random' 'Math-Tests-ODE' 'Math-Tests-KDTree' 'Math-Tests-FunctionFit' 'Math-Tests-AutomaticDifferenciation' 'Math-Tests-FastFourierTransform' 'Math-Tests-Accuracy' 'Math-Tests-ArbitraryPrecisionFloat' 'Math-Tests-KolmogorovSmirnov' 'Math-Tests-Quantile' 'Math-Tests-Polynomials' 'Math-Tests-PrincipalComponentAnalysis' 'Math-Tests-KernelSmoothing' 'Math-Tests-Number-Extensions' 'Math-Tests-Permutation' 'Math-Tests-TSNE' 'Math-Tests-Core-Process' 'Math-Tests-Core-Distribution' 'Math-Tests-Core'); + #('Math-Tests-Clustering' 'Math-Tests-Numerical' 'Math-Tests-Complex' 'Math-Tests-Quaternion' 'Math-Tests-Random' 'Math-Tests-ODE' 'Math-Tests-KDTree' 'Math-Tests-FunctionFit' 'Math-Tests-AutomaticDifferenciation' 'Math-Tests-FastFourierTransform' 'Math-Tests-Accuracy' 'Math-Tests-ArbitraryPrecisionFloat' 'Math-Tests-KolmogorovSmirnov' 'Math-Tests-Quantile' 'Math-Tests-Polynomials' 'Math-Tests-PrincipalComponentAnalysis' 'Math-Tests-KernelSmoothing' 'Math-Tests-Number-Extensions' 'Math-Tests-Permutation' 'Math-Tests-TSNE' 'Math-Tests-Core-Process' 'Math-Tests-Core-Distribution'); group: 'default' with: #('Core' 'Extensions' 'Tests' 'Benchmarks' 'Accuracy') ] ] +{ #category : #dependencies } +BaselineOfPolyMath >> polyMathDataStructures: spec [ + + spec baseline: 'PolyMathDataStructures' with: [ spec repository: 'github://PolyMathOrg/PolyMath-DataStructures:v1.x.x/src' ] +] + { #category : #accessing } BaselineOfPolyMath >> projectClass [ ^ [ self class environment at: #MetacelloCypressBaselineProject ] on: NotFound do: [ super projectClass ] ] + +{ #category : #dependencies } +BaselineOfPolyMath >> sMark: spec [ + + spec baseline: 'SMark' with: [ spec repository: 'github://smarr/SMark:v1.0.4' ] +] + +{ #category : #dependencies } +BaselineOfPolyMath >> xmlWriter: spec [ + + spec baseline: 'XMLWriter' with: [ spec repository: 'github://pharo-contributions/XML-XMLWriter:2.9.x/src' ] +] diff --git a/src/Math-Tests-Matrix/ManifestMathTestsMatrix.class.st b/src/Math-Chromosome/ManifestMathChromosome.class.st similarity index 58% rename from src/Math-Tests-Matrix/ManifestMathTestsMatrix.class.st rename to src/Math-Chromosome/ManifestMathChromosome.class.st index a5521a9dc..bb6d1fc05 100644 --- a/src/Math-Tests-Matrix/ManifestMathTestsMatrix.class.st +++ b/src/Math-Chromosome/ManifestMathChromosome.class.st @@ -2,12 +2,7 @@ Please describe the package using the class comment of the included manifest class. The manifest class also includes other additional metadata for the package. These meta data are used by other tools such as the SmalllintManifestChecker and the critics Browser " Class { - #name : #ManifestMathTestsMatrix, + #name : #ManifestMathChromosome, #superclass : #PackageManifest, - #category : #'Math-Tests-Matrix-Manifest' + #category : #'Math-Chromosome-Manifest' } - -{ #category : #'meta-data - dependency analyser' } -ManifestMathTestsMatrix class >> manuallyResolvedDependencies [ - ^ #(#'Math-Core-Process') -] diff --git a/src/Math-Core/ArrayedCollection.extension.st b/src/Math-Core/ArrayedCollection.extension.st deleted file mode 100644 index e2adfbba6..000000000 --- a/src/Math-Core/ArrayedCollection.extension.st +++ /dev/null @@ -1,15 +0,0 @@ -Extension { #name : #ArrayedCollection } - -{ #category : #'*Math-Core' } -ArrayedCollection >> addWithVector: aVector [ - "Answers the sum of the receiver with aVector." - | answer n | - answer := self class new: self size. - n := 0. - self with: aVector do: - [ :a :b | - n := n + 1. - answer at: n put: ( a + b). - ]. - ^ answer -] diff --git a/src/Math-Core/Collection.extension.st b/src/Math-Core/Collection.extension.st deleted file mode 100644 index 12e64e0df..000000000 --- a/src/Math-Core/Collection.extension.st +++ /dev/null @@ -1,11 +0,0 @@ -Extension { #name : #Collection } - -{ #category : #'*Math-Core' } -Collection >> asPMVector [ - - | aVector index | - aVector := PMVector new: self size. - index := 0. - self do: [:each | aVector at: (index := index + 1) put: each]. - ^aVector -] diff --git a/src/Math-Core/ManifestMathCore.class.st b/src/Math-Core/ManifestMathCore.class.st deleted file mode 100644 index 258ce9ce6..000000000 --- a/src/Math-Core/ManifestMathCore.class.st +++ /dev/null @@ -1,13 +0,0 @@ -" -Please describe the package using the class comment of the included manifest class. The manifest class also includes other additional metadata for the package. These meta data are used by other tools such as the SmalllintManifestChecker and the critics Browser -" -Class { - #name : #ManifestMathCore, - #superclass : #PackageManifest, - #category : #'Math-Core-Manifest' -} - -{ #category : #'meta-data - dependency analyser' } -ManifestMathCore class >> manuallyResolvedDependencies [ - ^ #(#'Transcript-Core' #'Math-Operations-Extensions') -] diff --git a/src/Math-Core/Number.extension.st b/src/Math-Core/Number.extension.st deleted file mode 100644 index c9b28b082..000000000 --- a/src/Math-Core/Number.extension.st +++ /dev/null @@ -1,13 +0,0 @@ -Extension { #name : #Number } - -{ #category : #'*Math-Core' } -Number >> addWithVector: aVector [ - "Adds itself to each element of the vector" - ^ aVector collect: [ :each | each + self ] -] - -{ #category : #'*Math-Core' } -Number >> productWithVector: aVector [ - "Answers a new vector product of the receiver with aVector." - ^aVector collect: [ :each | each * self] -] diff --git a/src/Math-Core/PMVector.class.st b/src/Math-Core/PMVector.class.st deleted file mode 100644 index c566a150e..000000000 --- a/src/Math-Core/PMVector.class.st +++ /dev/null @@ -1,327 +0,0 @@ -" -A vector is an object in a multidimensional space. It is represented by its components measured on a reference system. - -Here is a typical use of myself - -[[[ -| u v w a b c | -u := #(1 2 3) asPMVector. -v := #(3 4 5) asPMVector. -a := PMMatrix rows: #( ( 1 0 1 ) (-1 -2 3)). -b := PMMatrix rows: #( ( 1 2 3 ) (-2 1 7) (5 6 7)). -w := 4 * u + (3 * v). -c := a * b. -v := a * u. -w := c transpose * v. -w := v * c. -]]] -" -Class { - #name : #PMVector, - #superclass : #Array, - #type : #variable, - #category : #'Math-Core' -} - -{ #category : #'instance creation' } -PMVector class >> new: size random: maxRandomNumber [ - "Answer an instance of me, with number of elements equal to size, each - a randomNumber lower than maxRandomNumber ." - - | random | - random := Random new. - - ^ self newFrom: ((1 to: size ) collect: [ :each | - random nextBetween: 0 and: maxRandomNumber ]). -] - -{ #category : #private } -PMVector class >> ones: anInteger [ - "Creates a vector of ones." - |a| - a := PMVector new: anInteger. - 1 to: a size do: [ :n | a at: n put: 1]. - ^a -] - -{ #category : #private } -PMVector class >> randomSize: anInteger maxNumber: aMaxNumber [ - "Creates a vector of rand numbers from 0 to aMaxNumber." - | random vector | - random := Random new. - - vector := PMVector new: anInteger. - 1 to: vector size do: [ :i | - vector at: i put: (random nextBetween: 0 and: aMaxNumber)]. - - ^ vector -] - -{ #category : #private } -PMVector class >> zeros: anInteger [ - "Creates a vector of zeros." - |a| - a := PMVector new: anInteger. - 1 to: a size do: [ :n | a at: n put: 0]. - ^a -] - -{ #category : #operation } -PMVector >> * aNumberaVectoraMatrix [ - ^ aNumberaVectoraMatrix productWithVector: self -] - -{ #category : #operation } -PMVector >> + aVectorOrNumber [ - "Answers the sum of the receiver with a vector or number." - ^ aVectorOrNumber addWithVector: self -] - -{ #category : #operation } -PMVector >> - aVectorOrNumber [ - "Answers the difference of the receiver with a vector or number." - ^ -1*aVectorOrNumber addWithVector: self -] - -{ #category : #operation } -PMVector >> < aNumber [ - "Apply < operator to every element of a vector and returns a new vector" - ^ ((1 to: self size) collect: [ :n | (self at: n) < aNumber]) asPMVector. -] - -{ #category : #operation } -PMVector >> > aNumber [ - "Apply > function to every element of a vector and return a new vector" - ^ ((1 to: self size) collect: [ :n | (self at: n) > aNumber]) asPMVector. -] - -{ #category : #transformation } -PMVector >> accumulate: aVectorOrAnArray [ - "Modify the receiver adding the contents of the argument to the receiver." - 1 to: self size do: [ :n | self at: n put: ((self at: n) + (aVectorOrAnArray at: n))]. -] - -{ #category : #transformation } -PMVector >> accumulateNegated: aVectorOrAnArray [ - "Modify the receiver adding the negated contents of the argument to the receiver." - 1 to: self size do: [ :n | self at: n put: ((self at: n) - (aVectorOrAnArray at: n))]. -] - -{ #category : #'as yet unclassified' } -PMVector >> argMax [ - | a | - a := self asArray. - ^ a indexOf: a max -] - -{ #category : #converting } -PMVector >> asArray [ - - | array i| - array := Array new: self size. - i := 0. - self do: [:item | array basicAt: (i:=i+1) put: item]. - ^ array -] - -{ #category : #creation } -PMVector >> asPMVector [ - "Answer self since the receiver is a vector." - ^ self -] - -{ #category : #'as yet unclassified' } -PMVector >> checkDimensionalCompatibility: dimensionArray [ - |prod| - prod := 1. - - dimensionArray do: [ :each | prod := prod * each ]. - - self assert: (self size = prod) description: 'Imcompatible combination of Dimensions provided'. - - ^true -] - -{ #category : #comparing } -PMVector >> closeTo: aPMVector [ - "Compare two vectors using the default precision from Float >> #closeTo:." - - ^ self closeTo: aPMVector precision: 0.0001. -] - -{ #category : #comparing } -PMVector >> closeTo: aPMVector precision: aPrecision [ - "Tests whether the total summed difference between self and aPMVector is within aPrecision." - - ^ (self - aPMVector) abs sum < aPrecision -] - -{ #category : #operation } -PMVector >> cos [ - "Apply cos function to every element of a vector" - 1 to: self size do: [ :n | self at: n put: (self at: n) cos]. -] - -{ #category : #operation } -PMVector >> cosh [ - "Apply cosh function to every element of a vector" - 1 to: self size do: [ :n | self at: n put: (self at: n) cosh]. -] - -{ #category : #transformation } -PMVector >> cumsum [ - "Cumulative sum - #(1 2 3 4 5) cumsum = #(1 3 6 10 15) - " - | sum | - sum := 0. - ^ self collect: [ :v | sum := sum + v. sum ] - -] - -{ #category : #operation } -PMVector >> hadamardProduct: aVector [ - "Answers the elementwise product of the receiver with aVector." - - | answer n | - answer := self class new: self size. - n := 0. - self - with: aVector - do: [ :a :b | - n := n + 1. - answer at: n put: a * b ]. - ^ answer -] - -{ #category : #'as yet unclassified' } -PMVector >> householder [ - "returns a collection of the skalar beta and the housholder vector" - |s v b u x | - s :=self allButFirst. - s := s *s. - v := self copy. - v at: 1 put: 1. - s = 0 - ifTrue: [ b :=0 ] - ifFalse: [ - u :=((x:=self at:1)squared + s)sqrt . - v - at: 1 - put: ((x <=0) ifTrue: [x -u] ifFalse: [0 - s / (x + u)]). - b :=(v at: 1) squared * 2 / (s + (v at: 1) squared). - v := v / (v at: 1) ]. - ^Array with: b with: v -] - -{ #category : #testing } -PMVector >> isZero [ - ^ self allSatisfy: [ :element | element = 0 ] -] - -{ #category : #operation } -PMVector >> log [ - "Apply log function to every element of a vector" - 1 to: self size do: [ :n | self at: n put: (self at: n) log]. -] - -{ #category : #transformation } -PMVector >> negate [ - "Inverse the sign of all components of the receiver." - 1 to: self size do: [ :n | self at: n put: (self at: n) negated]. -] - -{ #category : #operation } -PMVector >> negated [ - ^ self * -1 -] - -{ #category : #operation } -PMVector >> norm [ - "Answer the norm of the receiver." - ^(self * self) sqrt -] - -{ #category : #creation } -PMVector >> normalized [ - ^ (1 / self norm) * self -] - -{ #category : #operation } -PMVector >> productWithVector: aVector [ - "Answers the scalar product of aVector with the receiver." - | n | - n := 0. - ^self inject: 0 - into: [ :sum :each | n := n + 1. (aVector at: n) * each + sum] -] - -{ #category : #operation } -PMVector >> scalarProduct: aVector [ - - | product n | - n := 0. - product := self collect: [ :each | n := n + 1. (aVector at: n) * each]. - n := product size. - [ n > 1] - whileTrue:[ | i j| - i := 1. - j := n. - [ i < j] - whileTrue: [ product at: i put: ( product at: i) + ( product at: j). - j := j - 1. - i := i + 1. - ]. - n := i min: j. - ]. - ^product at: 1 -] - -{ #category : #transformation } -PMVector >> scaleBy: aNumber [ - "Modify the receiver elements by a multiplicating factor." - 1 to: self size do: [ :n | self at: n put: ((self at: n) * aNumber)]. -] - -{ #category : #operation } -PMVector >> sin [ - "Apply sin function to every element of a vector" - - 1 to: self size do: [ :n | self at: n put: (self at: n) sin ] -] - -{ #category : #operation } -PMVector >> sinh [ - "Apply sinh function to every element of a vector" - - 1 to: self size do: [ :n | self at: n put: (self at: n) sinh ] -] - -{ #category : #operation } -PMVector >> sqrt [ - "Apply sqrt function to every element of a vector" - - 1 to: self size do: [ :n | self at: n put: (self at: n) sqrt ] -] - -{ #category : #arithmetic } -PMVector >> take: anInteger [ - - " Answer a with the receiver's binomial coefficient at each element for anInteger " - - ^ self collect: [ :each | each numberOfCombinationsTaken: anInteger ] -] - -{ #category : #operation } -PMVector >> tan [ - "Apply tan function to every element of a vector" - - 1 to: self size do: [ :n | self at: n put: (self at: n) tan ] -] - -{ #category : #operation } -PMVector >> tanh [ - "Apply tanh function to every element of a vector" - - ^ self collect: [ :each | each tanh ] -] diff --git a/src/Math-Core/package.st b/src/Math-Core/package.st deleted file mode 100644 index f0574fd8f..000000000 --- a/src/Math-Core/package.st +++ /dev/null @@ -1 +0,0 @@ -Package { #name : #'Math-Core' } diff --git a/src/Math-Core/PMFloatingPointMachine.class.st b/src/Math-Helpers/PMFloatingPointMachine.class.st similarity index 99% rename from src/Math-Core/PMFloatingPointMachine.class.st rename to src/Math-Helpers/PMFloatingPointMachine.class.st index 27eb499e3..5f0f53ab0 100644 --- a/src/Math-Core/PMFloatingPointMachine.class.st +++ b/src/Math-Helpers/PMFloatingPointMachine.class.st @@ -31,7 +31,7 @@ Class { #classVars : [ 'UniqueInstance' ], - #category : #'Math-Core' + #category : #'Math-Helpers' } { #category : #'instance creation' } diff --git a/src/Math-Core/PMWeightedPoint.class.st b/src/Math-Helpers/PMWeightedPoint.class.st similarity index 98% rename from src/Math-Core/PMWeightedPoint.class.st rename to src/Math-Helpers/PMWeightedPoint.class.st index ccb2c2b85..a6826b440 100644 --- a/src/Math-Core/PMWeightedPoint.class.st +++ b/src/Math-Helpers/PMWeightedPoint.class.st @@ -10,7 +10,7 @@ Class { 'weight', 'error' ], - #category : #'Math-Core' + #category : #'Math-Helpers' } { #category : #creation } diff --git a/src/Math-Core/SequenceableCollection.extension.st b/src/Math-Helpers/SequenceableCollection.extension.st similarity index 86% rename from src/Math-Core/SequenceableCollection.extension.st rename to src/Math-Helpers/SequenceableCollection.extension.st index c90d480dc..a864f2c8a 100644 --- a/src/Math-Core/SequenceableCollection.extension.st +++ b/src/Math-Helpers/SequenceableCollection.extension.st @@ -1,6 +1,6 @@ Extension { #name : #SequenceableCollection } -{ #category : #'*Math-Core' } +{ #category : #'*Math-Helpers' } SequenceableCollection >> closeTo: aSequenceableCollection [ self @@ -9,7 +9,7 @@ SequenceableCollection >> closeTo: aSequenceableCollection [ ^ true ] -{ #category : #'*Math-Core' } +{ #category : #'*Math-Helpers' } SequenceableCollection >> equalsTo: aSequenceableCollection [ self diff --git a/src/Math-Helpers/package.st b/src/Math-Helpers/package.st new file mode 100644 index 000000000..546e6d611 --- /dev/null +++ b/src/Math-Helpers/package.st @@ -0,0 +1 @@ +Package { #name : #'Math-Helpers' } diff --git a/src/Math-Matrix/ManifestMathMatrix.class.st b/src/Math-Matrix/ManifestMathMatrix.class.st deleted file mode 100644 index cf1492217..000000000 --- a/src/Math-Matrix/ManifestMathMatrix.class.st +++ /dev/null @@ -1,13 +0,0 @@ -" -Please describe the package using the class comment of the included manifest class. The manifest class also includes other additional metadata for the package. These meta data are used by other tools such as the SmalllintManifestChecker and the critics Browser -" -Class { - #name : #ManifestMathMatrix, - #superclass : #PackageManifest, - #category : #'Math-Matrix-Manifest' -} - -{ #category : #'meta-data - dependency analyser' } -ManifestMathMatrix class >> manuallyResolvedDependencies [ - ^ #(#'Collections-Streams' #'Math-Operations-Extensions') -] diff --git a/src/Math-Matrix/Number.extension.st b/src/Math-Matrix/Number.extension.st deleted file mode 100644 index c092e3426..000000000 --- a/src/Math-Matrix/Number.extension.st +++ /dev/null @@ -1,24 +0,0 @@ -Extension { #name : #Number } - -{ #category : #'*Math-Matrix' } -Number >> addWithRegularMatrix: aMatrix [ - "Adds itself to every row of the matrix" - ^ PMMatrix rows: (aMatrix rowsCollect: [ :row | row + self ]) -] - -{ #category : #'*Math-Matrix' } -Number >> complexConjugate [ - "The complex conjugate of a complex number (a + bi) is another complex number (a - bi). - Every real number x is also a complex number with imaginary part equal to 0. - In other words, x = x + 0i and x = x - 0i. - Therefore, the complex conjugate of a real number is the same real number" - - "Maintenance note: This method is related to complexes but is packaged in Matrix because the version on Number is not dependant of Complexe and is used by matrix algos." - - ^ self -] - -{ #category : #'*Math-Matrix' } -Number >> productWithMatrix: aMatrix [ -^aMatrix class rows: (aMatrix rowsCollect: [:r| self productWithVector: r]) -] diff --git a/src/Math-Matrix/PMJacobiTransformation.class.st b/src/Math-Matrix/PMJacobiTransformation.class.st deleted file mode 100644 index 924355ac1..000000000 --- a/src/Math-Matrix/PMJacobiTransformation.class.st +++ /dev/null @@ -1,193 +0,0 @@ -" -[[[ -| m jacobi eigenvalues eigenvectors | -m := PMSymmetricMatrix rows: #((84 -79 58 55) - (-79 84 -55 -58) - (58 -55 84 79) - (55 -58 79 84)). -jacobi := PMJacobiTransformation matrix: m. -eigenvalues := jacobi evaluate. -eigenvectors := jacobi transform columnsCollect: [ :each | each]. -]]] -" -Class { - #name : #PMJacobiTransformation, - #superclass : #PMIterativeProcess, - #instVars : [ - 'lowerRows', - 'transform' - ], - #category : #'Math-Matrix' -} - -{ #category : #creation } -PMJacobiTransformation class >> matrix: aSymmetricMatrix [ - ^ super new initialize: aSymmetricMatrix -] - -{ #category : #creation } -PMJacobiTransformation class >> new [ - "Prevent using this message to create instances." - - ^ self error: 'Illegal creation message for this class' -] - -{ #category : #operation } -PMJacobiTransformation >> evaluateIteration [ - | indices | - indices := self largestOffDiagonalIndices. - self transformAt: ( indices at: 1) and: ( indices at: 2). - ^precision -] - -{ #category : #transformation } -PMJacobiTransformation >> exchangeAt: anInteger [ - "Private" - | temp n | - n := anInteger + 1. - temp := result at: n. - result at: n put: ( result at: anInteger). - result at: anInteger put: temp. - transform do: - [ :each | - temp := each at: n. - each at: n put: ( each at: anInteger). - each at: anInteger put: temp. - ]. -] - -{ #category : #operation } -PMJacobiTransformation >> finalizeIterations [ - "Transfer the eigenValues into a vector and set this as the result. - eigen values and transform matrix are sorted using a bubble sort." - - | n | - n := 0. - result := lowerRows collect: - [:each | - n := n + 1. - each at: n]. - self sortEigenValues -] - -{ #category : #initialization } -PMJacobiTransformation >> initialize: aSymmetricMatrix [ - "Private" - | n | - n := aSymmetricMatrix numberOfRows. - lowerRows := Array new: n. - transform := Array new: n. - 1 to: n do: - [ :k | - lowerRows at: k put: ( ( aSymmetricMatrix rowAt: k) copyFrom: 1 to: k). - transform at: k put: ( ( Array new: n) atAllPut: 0; at: k put: 1; yourself). - ] -] - -{ #category : #information } -PMJacobiTransformation >> largestOffDiagonalIndices [ - "Private" - | n m abs | - n := 2. - m := 1. - precision := ( ( lowerRows at: n) at: m) abs. - 1 to: lowerRows size do: - [ :i | - 1 to: ( i - 1) do: - [ :j | - abs := ( ( lowerRows at: i) at: j) abs. - abs > precision - ifTrue: [ n := i. - m := j. - precision := abs. - ]. - ]. - ]. - ^Array with: m with: n -] - -{ #category : #display } -PMJacobiTransformation >> printOn: aStream [ - "Append to the argument aStream, a sequence of characters that describes the receiver." - | first | - first := true. - lowerRows do: - [ :each | - first ifTrue: [ first := false] - ifFalse:[ aStream cr]. - each printOn: aStream. - ]. -] - -{ #category : #transformation } -PMJacobiTransformation >> sortEigenValues [ - "Private - Use a bubble sort." - | n bound m | - n := lowerRows size. - bound := n. - [ bound = 0 ] - whileFalse: [ m := 0. - 1 to: bound - 1 do: - [ :j | - ( result at: j) abs > ( result at: j + 1) abs - ifFalse:[ self exchangeAt: j. - m := j. - ]. - ]. - bound := m. - ]. -] - -{ #category : #information } -PMJacobiTransformation >> transform [ - ^PMMatrix rows: transform -] - -{ #category : #transformation } -PMJacobiTransformation >> transformAt: anInteger1 and: anInteger2 [ - "Private" - | d t s c tau apq app aqq arp arq | - apq := ( lowerRows at: anInteger2) at: anInteger1. - apq = 0 - ifTrue: [ ^nil]. - app := ( lowerRows at: anInteger1) at: anInteger1. - aqq := ( lowerRows at: anInteger2) at: anInteger2. - d := aqq - app. - arp := d * 0.5 / apq. - t := arp > 0 ifTrue: [ 1 / ( ( arp squared + 1) sqrt + arp)] - ifFalse:[ 1 / ( arp - ( arp squared + 1) sqrt)]. - c := 1 / ( t squared + 1) sqrt. - s := t * c. - tau := s / ( 1 + c). - 1 to: ( anInteger1 - 1) - do: [ :r | - arp := ( lowerRows at: anInteger1) at: r. - arq := ( lowerRows at: anInteger2) at: r. - ( lowerRows at: anInteger1) at: r put: ( arp - ( s * (tau * arp + arq))). - ( lowerRows at: anInteger2) at: r put: ( arq + ( s * (arp - (tau * arq)))). - ]. - ( anInteger1 + 1) to: ( anInteger2 - 1) - do: [ :r | - arp := ( lowerRows at: r) at: anInteger1. - arq := ( lowerRows at: anInteger2) at: r. - ( lowerRows at: r) at: anInteger1 put: ( arp - ( s * (tau * arp + arq))). - ( lowerRows at: anInteger2) at: r put: ( arq + ( s * (arp - (tau * arq)))). - ]. - ( anInteger2 + 1) to: lowerRows size - do: [ :r | - arp := ( lowerRows at: r) at: anInteger1. - arq := ( lowerRows at: r) at: anInteger2. - ( lowerRows at: r) at: anInteger1 put: ( arp - ( s * (tau * arp + arq))). - ( lowerRows at: r) at: anInteger2 put: ( arq + ( s * (arp - (tau * arq)))). - ]. - 1 to: lowerRows size - do: [ :r | - arp := ( transform at: r) at: anInteger1. - arq := ( transform at: r) at: anInteger2. - ( transform at: r) at: anInteger1 put: ( arp - ( s * (tau * arp + arq))). - ( transform at: r) at: anInteger2 put: ( arq + ( s * (arp - (tau * arq)))). - ]. - ( lowerRows at: anInteger1) at: anInteger1 put: ( app - (t * apq)). - ( lowerRows at: anInteger2) at: anInteger2 put: ( aqq + (t * apq)). - ( lowerRows at: anInteger2) at: anInteger1 put: 0. -] diff --git a/src/Math-Matrix/PMJacobiTransformationHelper.class.st b/src/Math-Matrix/PMJacobiTransformationHelper.class.st deleted file mode 100644 index be6f6f9ce..000000000 --- a/src/Math-Matrix/PMJacobiTransformationHelper.class.st +++ /dev/null @@ -1,45 +0,0 @@ -" -I store eigenvalues and eigenvectors of a symmetric matrix computed with PMJacobiTransformation -" -Class { - #name : #PMJacobiTransformationHelper, - #superclass : #Object, - #instVars : [ - 'eigenvalues', - 'eigenvectors' - ], - #category : 'Math-Matrix' -} - -{ #category : #creation } -PMJacobiTransformationHelper class >> matrix: aSymmetricMatrix [ - ^ super new initialize: aSymmetricMatrix -] - -{ #category : #creation } -PMJacobiTransformationHelper class >> new [ - "Prevent using this message to create instances." - - ^ self error: 'Illegal creation message for this class' -] - -{ #category : #initialization } -PMJacobiTransformationHelper >> initialize: aSymmetricMatrix [ - - | jacobi | - jacobi := PMJacobiTransformation matrix: aSymmetricMatrix. - eigenvalues := jacobi evaluate. - eigenvectors := jacobi transform columnsCollect: [ :each | each]. -] - -{ #category : #accessing } -PMJacobiTransformationHelper >> values [ - - ^ eigenvalues -] - -{ #category : #accessing } -PMJacobiTransformationHelper >> vectors [ - - ^ eigenvectors -] diff --git a/src/Math-Matrix/PMLUPDecomposition.class.st b/src/Math-Matrix/PMLUPDecomposition.class.st deleted file mode 100644 index 0ff70b679..000000000 --- a/src/Math-Matrix/PMLUPDecomposition.class.st +++ /dev/null @@ -1,201 +0,0 @@ -" -LUP stands for Lower, Upper and Permutation. It comes from the observation that any non-singular square matrix A can be decomposed into a product of 3 square matrices of the same dimension. - -LUP decomposition is another technique to solve a -system of linear equations. It is an alternative to the Gaussian elimination. Gaussian elimination can solve a system with several constant vectors, but all constant vectors must be known before starting the algorithm. - -LUP decomposition is done once for the matrix of a given system. Thus, the system can be solved for any constant vector obtained after the LUP decomposition. In addition, LUP decomposition gives a way to calculate the determinant of a matrix and it can be used to compute the inverse of a matrix. - -Instance variables -- rows contains a copy of the rows of the matrix representing the system of linear equations, i.e.the matrix A; copying the matrix is necessary since LUP decomposition destroys the components; at the end of the LUP decomposition, it will contain the components of the matrices L and U, -- permutation contains an array of integers describing the permutation, i.e.the matrix P, -- parity contains parity of the permutation for efficiency purpose. - -[[[ -| s sol1 sol2 | -s := PMLUPDecomposition equations: #( (3 2 4) (2 -5 -1) (1 -2 2)). -sol1 := s solve: #(16 6 10). -sol2 := s solve: #(7 10 9). -]]] -" -Class { - #name : #PMLUPDecomposition, - #superclass : #Object, - #instVars : [ - 'rows', - 'permutation', - 'parity' - ], - #category : #'Math-Matrix' -} - -{ #category : #creation } -PMLUPDecomposition class >> direct: anArrayOfArrays [ - - ^ self basicNew initialize: anArrayOfArrays. -] - -{ #category : #creation } -PMLUPDecomposition class >> equations: anArrayOfArrays [ - ^ self new initialize: (anArrayOfArrays collect: [ :each | each copy ]) -] - -{ #category : #private } -PMLUPDecomposition >> backwardSubstitution: anArray [ - "Private" - | n sum answer | - n := rows size. - answer := PMVector new: n. - n to: 1 by: -1 do: - [ :i | - sum := anArray at: i. - ( i + 1) to: n do: [ :j | sum := sum - ( ( ( rows at: i) at: j) * ( answer at: j))]. - answer at: i put: sum / ( ( rows at: i) at: i). - ]. - ^answer -] - -{ #category : #private } -PMLUPDecomposition >> decompose [ - "Private" - | n | - n := rows size. - permutation := (1 to: n) asArray. - 1 to: ( n - 1) do: - [ :k | - self swapRow: k withRow: ( self largestPivotFrom: k); - pivotAt: k. - ]. -] - -{ #category : #operations } -PMLUPDecomposition >> determinant [ - | n | - permutation isNil - ifTrue: [ self protectedDecomposition ]. - permutation = 0 - ifTrue: [ ^ 0 ]. "Singular matrix has 0 determinant" - n := 0. - ^ rows inject: parity - into: [ :det :each | n := n + 1. ( each at: n) * det ] -] - -{ #category : #private } -PMLUPDecomposition >> forwardSubstitution: anArray [ - "Private" - | n sum answer| - answer := permutation collect: [ :each | anArray at: each]. - n := rows size. - 2 to: n do: - [ :i | - sum := answer at: i. - 1 to: (i - 1) do: [ :j | sum := sum - (((rows at: i) at: j) * (answer at: j))]. - answer at: i put: sum. - ]. - ^answer -] - -{ #category : #initialization } -PMLUPDecomposition >> initialize: anArrayOfArrays [ - rows := anArrayOfArrays. - parity := 1. - ^ self -] - -{ #category : #operations } -PMLUPDecomposition >> inverseMatrixComponents [ - | n inverseRows column | - permutation isNil - ifTrue: [ self protectedDecomposition]. - permutation = 0 - ifTrue: [ ^ nil]. "Singular matrix has no inverse" - n := rows size. - inverseRows := (1 to: n) asPMVector collect: [ :j | PMVector new: n]. - 1 to: n do: - [ :j | - column := self solve: ( ( Array new: rows size) atAllPut: 0; at: j put: 1; yourself). - column ifNil: [^nil]. "Singular matrix has no inverse" - 1 to: n do: [ :i | ( inverseRows at: i) at: j put: ( column at: i)]. - ]. - ^inverseRows -] - -{ #category : #operations } -PMLUPDecomposition >> largestPivotFrom: anInteger [ - "Private - Answers the largest pivot element in column anInteger, from position anInteger upward." - | valueOfMaximum indexOfMaximum value | - valueOfMaximum := ((rows at: anInteger) at: anInteger) abs. - indexOfMaximum := anInteger. - (anInteger + 1) to: rows size do: - [ :n | - value := ((rows at: n) at: anInteger) abs. - value > valueOfMaximum - ifTrue: [ valueOfMaximum := value. - indexOfMaximum := n ]. - ]. - ^ indexOfMaximum -] - -{ #category : #private } -PMLUPDecomposition >> pivotAt: anInteger [ - "Private" - | inversePivot size k | - inversePivot := 1 / ((rows at: anInteger) at: anInteger). - size := rows size. - k := anInteger + 1. - k to: size - do: [ :i | - (rows at: i) at: anInteger put: ((rows at: i) at: anInteger) * inversePivot. - k to: size - do: [ :j | - (rows at: i) at: j put: ((rows at: i) at: j) - (((rows at: i) at: anInteger) * ((rows at: anInteger) at: j)). - ] - ]. -] - -{ #category : #printing } -PMLUPDecomposition >> printOn: aStream [ - - | delimitingString | - rows do: - [ :row | - delimitingString := '('. - row do: - [ :each | - aStream nextPutAll: delimitingString. - each printOn: aStream. - delimitingString := ' ' ]. - aStream nextPut: $). - ] - separatedBy: [ aStream cr ] -] - -{ #category : #private } -PMLUPDecomposition >> protectedDecomposition [ - "Private - If decomposition fails, set permutation to 0." - [ self decompose] on: Error do: [ :signal | permutation := 0. signal return: nil]. -] - -{ #category : #private } -PMLUPDecomposition >> solve: anArrayOrVector [ - permutation isNil - ifTrue: [ self protectedDecomposition ]. - ^ permutation = 0 - ifTrue: [ nil ] - ifFalse:[ - [self backwardSubstitution: ( self forwardSubstitution: anArrayOrVector)] on: ZeroDivide do: [:e| nil] ] -] - -{ #category : #private } -PMLUPDecomposition >> swapRow: anInteger1 withRow: anInteger2 [ - "Private - Swap the rows indexed by the given integers." - | swappedRow | - anInteger1 = anInteger2 ifTrue: [ ^ self ]. - swappedRow := rows at: anInteger1. - rows at: anInteger1 put: (rows at: anInteger2). - rows at: anInteger2 put: swappedRow. - swappedRow := permutation at: anInteger1. - permutation at: anInteger1 put: (permutation at: anInteger2). - permutation at: anInteger2 put: swappedRow. - parity := parity negated -] diff --git a/src/Math-Matrix/PMLargestEigenValueFinder.class.st b/src/Math-Matrix/PMLargestEigenValueFinder.class.st deleted file mode 100644 index 06dfac388..000000000 --- a/src/Math-Matrix/PMLargestEigenValueFinder.class.st +++ /dev/null @@ -1,108 +0,0 @@ -" -[ [ [ -m := PMMatrix rows: #( ( 84 -79 58 55) - (-79 84 -55 -58) - ( 58 -55 84 79) - ( 55 -58 79 84) ). -finder := PMLargestEigenValueFinder matrix: m. -eigenvalue := finder evaluate. -eigenvector := finder eigenvector. -nextFinder := finder nextLargestEigenValueFinder. -nextEigenvalue := nextFinder evaluate. -nextEigenvector := nextFinder eigenvector. -] ] ] -" -Class { - #name : #PMLargestEigenValueFinder, - #superclass : #PMIterativeProcess, - #instVars : [ - 'matrix', - 'eigenvector', - 'transposeEigenvector' - ], - #category : 'Math-Matrix' -} - -{ #category : #information } -PMLargestEigenValueFinder class >> defaultMaximumIterations [ - "Private - Answers the default maximum number of iterations for newly created instances." - ^100 -] - -{ #category : #creation } -PMLargestEigenValueFinder class >> matrix: aMatrix [ - "Create a new instance of the receiver for a given matrix and default precision." - - ^ self new - initialize: aMatrix; - yourself -] - -{ #category : #creation } -PMLargestEigenValueFinder class >> matrix: aMatrix precision: aNumber [ - "Create a new instance of the receiver for a given matrix and desired precision." - - ^ self new - initialize: aMatrix; - desiredPrecision: aNumber; - yourself -] - -{ #category : #information } -PMLargestEigenValueFinder >> eigenvalue [ - "Answer the eigen value found by the receiver." - - ^result -] - -{ #category : #information } -PMLargestEigenValueFinder >> eigenvector [ - "Answer the normalized eigen vector found by the receiver." - - ^eigenvector * (1 / eigenvector norm) -] - -{ #category : #operation } -PMLargestEigenValueFinder >> evaluateIteration [ - "Iterate the product of the matrix of the eigen vector and the transpose." - - | oldEigenvalue | - oldEigenvalue := result. - transposeEigenvector := transposeEigenvector * matrix. - transposeEigenvector := transposeEigenvector - * (1 / (transposeEigenvector at: 1)). - eigenvector := matrix * eigenvector. - result := eigenvector at: 1. - eigenvector := eigenvector * (1 / result). - ^oldEigenvalue isNil - ifTrue: [2 * desiredPrecision] - ifFalse: [(result - oldEigenvalue) abs] -] - -{ #category : #initialization } -PMLargestEigenValueFinder >> initialize: aMatrix [ - "Defines the matrix for the receiver." - matrix := aMatrix. -] - -{ #category : #operation } -PMLargestEigenValueFinder >> initializeIterations [ - "Initialize the iterations (subclasses must write their own method and call this one last)." - - eigenvector := PMVector new: matrix numberOfRows. - eigenvector atAllPut: 1.0. - transposeEigenvector := PMVector new: eigenvector size. - transposeEigenvector atAllPut: 1.0 -] - -{ #category : #creation } -PMLargestEigenValueFinder >> nextLargestEigenValueFinder [ - "Return an eigen value finder for the same eigen values of the receiver except the one found." - - | norm | - norm := 1 / (eigenvector * transposeEigenvector). - ^self class - matrix: matrix * ((PMSymmetricMatrix identity: eigenvector size) - - (eigenvector * norm tensorProduct: transposeEigenvector)) - precision: desiredPrecision -] diff --git a/src/Math-Matrix/PMLinearEquationSystem.class.st b/src/Math-Matrix/PMLinearEquationSystem.class.st deleted file mode 100644 index 875c9ec99..000000000 --- a/src/Math-Matrix/PMLinearEquationSystem.class.st +++ /dev/null @@ -1,167 +0,0 @@ -" -This class offers Gaussian elimination. - -[[[ - (PMLinearEquationSystem equations: #( (3 2 4) - (2 -5 -1) - (1 -2 2)) - constant: #(16 6 10) - ) solution. -]]] - -Note that Gaussian elimination is solely dedicated to solving systems of linear equations. The algorithm is somewhat slower than LUP decomposition. - -If the system does not have a solution --- that is, if the system's matrix is singular --- an arithmetic error occurs in the -method ==pivotAt:== when the division with the zero pivot is performed. The method ==solutionAt:== traps this error within an -exception handling structure and sets the solution vector to a special value --- the integer 0 --- as a flag to prevent attempting Gaussian elimination a second time. Then, the value ==nil== is returned to represent the non-existent solution. -" -Class { - #name : #PMLinearEquationSystem, - #superclass : #Object, - #instVars : [ - 'rows', - 'solutions' - ], - #category : #'Math-Matrix' -} - -{ #category : #creation } -PMLinearEquationSystem class >> equations: anArrayOfArrays constant: anArray [ - - ^ self basicNew - initialize: anArrayOfArrays - constants: (Array with: anArray) -] - -{ #category : #creation } -PMLinearEquationSystem class >> equations: anArrayOfArrays constants: anArrayOfConstantArrays [ - - ^ self basicNew - initialize: anArrayOfArrays - constants: anArrayOfConstantArrays -] - -{ #category : #transformation } -PMLinearEquationSystem >> backSubstitutionAt: anInteger [ - "Private - Perform the back-substitution step corresponding to the anInteger-th constant array." - | size answer accumulator | - size := rows size. - answer := Array new: size. - size to: 1 by: -1 do: - [ :n | - accumulator := (rows at: n) at: (anInteger + size). - (n + 1) to: size - do: [ :m | accumulator := accumulator - ((answer at: m) * ((rows at: n) at: m))]. - answer at: n put: (accumulator / ( ( rows at: n) at: n)). - ]. - solutions at: anInteger put: answer. -] - -{ #category : #initialization } -PMLinearEquationSystem >> initialize: anArrayOfArrays constants: anArrayOfConstantArrays [ - "Private - Initialize the receiver with system's matrix in anArrayOfArrays and several constants." - | n | - n := 0. - rows := anArrayOfArrays collect: [ :each | n := n + 1. each, (anArrayOfConstantArrays collect: [ :c | c at: n])]. - ^ self -] - -{ #category : #information } -PMLinearEquationSystem >> largestPivotFrom: anInteger [ - "Private - Answers the largest pivot element in column anInteger, from position anInteger upward." - | valueOfMaximum indexOfMaximum | - valueOfMaximum := (rows at: anInteger) at: anInteger. - indexOfMaximum := anInteger. - (anInteger + 2) to: rows size do: - [ :n | - ((rows at: n) at: anInteger) > valueOfMaximum - ifTrue: [ valueOfMaximum := (rows at: n) at: anInteger. - indexOfMaximum := n. - ]. - ]. - ^ indexOfMaximum -] - -{ #category : #transformation } -PMLinearEquationSystem >> pivotAt: anInteger [ - "Private - Performs pivot operation with pivot element at anInteger." - | inversePivot rowPivotValue row pivotRow | - pivotRow := rows at: anInteger. - inversePivot := 1 / (pivotRow at: anInteger). - (anInteger + 1) to: rows size do: - [ :n | - row := rows at: n. - rowPivotValue := (row at: anInteger) * inversePivot. - anInteger to: row size do: - [ :m | - row at: m put: ((row at: m) - ((pivotRow at: m) * rowPivotValue)). - ]. - ]. -] - -{ #category : #transformation } -PMLinearEquationSystem >> pivotStepAt: anInteger [ - "Private - Performs an optimum pivot operation at anInteger." - self swapRow: anInteger withRow: (self largestPivotFrom: anInteger); - pivotAt: anInteger. -] - -{ #category : #printing } -PMLinearEquationSystem >> printOn: aStream [ - "Append to the argument aStream, a sequence of characters that describes the receiver." - | delimitingString n k | - n := rows size. - rows - do: - [ :row | - delimitingString := '('. - k := 0. - row do: - [ :each | - aStream nextPutAll: delimitingString. - each printOn: aStream. - k := k + 1. - delimitingString := k < n ifTrue: [ ' '] ifFalse: [ ' : ']. - ]. - aStream nextPut: $).] - separatedBy: [ aStream cr] - -] - -{ #category : #information } -PMLinearEquationSystem >> solution [ - "Answers the solution corresponding to the first constant array." - ^ self solutionAt: 1 -] - -{ #category : #information } -PMLinearEquationSystem >> solutionAt: anInteger [ - "Answer the solution corresponding to the anInteger-th constant array." - - solutions isNil - ifTrue: [ [self solve] on: Error do: [ :signal |solutions := 0. signal return: nil.] ]. - solutions = 0 - ifTrue: [ ^nil]. - (solutions at: anInteger) isNil - ifTrue: [ self backSubstitutionAt: anInteger]. - ^ solutions at: anInteger -] - -{ #category : #transformation } -PMLinearEquationSystem >> solve [ - "Private - Perform LU decomposition of the system." - 1 to: rows size do: [ :n | self pivotStepAt: n ]. - solutions := Array new: ((rows at: 1) size - rows size). -] - -{ #category : #transformation } -PMLinearEquationSystem >> swapRow: anInteger1 withRow: anInteger2 [ - "Private - Swap the rows indexed by the given integers." - - | swappedRow | - anInteger1 = anInteger2 - ifTrue: [ ^ self ]. - swappedRow := rows at: anInteger1. - rows at: anInteger1 put: (rows at: anInteger2). - rows at: anInteger2 put: swappedRow -] diff --git a/src/Math-Matrix/PMMatrix.class.st b/src/Math-Matrix/PMMatrix.class.st deleted file mode 100644 index 1fd7a6564..000000000 --- a/src/Math-Matrix/PMMatrix.class.st +++ /dev/null @@ -1,1084 +0,0 @@ -" -I represent a mathematical matrix. I can be build from rows as follows: - -[[[ -PMMatrix rows: #((1 2 3)(4 5 6)). -]]] - -I understand the usual matrix operations. - -" -Class { - #name : #PMMatrix, - #superclass : #Object, - #instVars : [ - 'rows', - 'lupDecomposition' - ], - #category : #'Math-Matrix' -} - -{ #category : #example } -PMMatrix class >> example [ -"" -|a b c d| -"This is how we can create a matrix, a and b are 2x3 matrices in -this example" -a := PMMatrix rows: #( ( 1 0 1 ) (-1 -2 3)). -b := PMMatrix rows: #( ( 1 2 3 ) (-2 1 7)). - -"Matrix product" -c := a * b. - -"Elementwise matrix product" -d := a hadamardProduct: b. - -"This is how we can create a vector" -a := #(1 4 9 16 25) asPMVector. - -"Vectors and Matrices support basic logical and arithmetic -operations" -Float pi sin * d. -a sqrt. -a > 3. -c cos. -c < 0. - -"It is possible to create a vector/matrix of random numbers" -a := PMVector randomSize: 10 maxNumber: 3. -b := PMMatrix rows: 2 columns: 3 random: 5. - -"It is also easy to create a vector/matrix of zeros/ones" -a := PMVector ones:15. -b := PMMatrix zerosRows: 2 cols: 3. - -"We can also compute the cumulative sum or regular sum the vector/ -matrix as following" -a := PMMatrix rows: #( ( 1 0 1 ) (-1 -2 3)). -a cumsum. -"a PMVector(1 1 2)" -"a PMVector(-1 -3 0)" -a sum. -"a PMVector(2 0)" - -"Matrix trace (sum of a diagonal elements for a square matrix)" -a := PMMatrix rows: #((1 2 3)(4 5 6)(7 8 9)). -a tr. -"15" -] - -{ #category : #'instance creation' } -PMMatrix class >> identity: dimension [ - ^ PMSymmetricMatrix identity: dimension -] - -{ #category : #'instance creation' } -PMMatrix class >> join: anArrayOfMatrices [ - "Inverse of the split operation." - | rows n row rowSize n1 n2 | - rows := OrderedCollection new. - n1 := ( anArrayOfMatrices at: 1) numberOfColumns. - n2 := n1 + 1. - rowSize := n1 + ( anArrayOfMatrices at: 2) numberOfColumns. - n := 0. - ( anArrayOfMatrices at: 1) rowsDo: - [ :each | - n := n + 1. - row := PMVector new: rowSize. - row replaceFrom: 1 to: n1 with: each startingAt: 1; - replaceFrom: n2 to: rowSize with: ( ( anArrayOfMatrices at: 2) rowAt: n) startingAt: 1. - rows add: row. - ]. - n := 0. - ( anArrayOfMatrices at: 3) rowsDo: - [ :each | - n := n + 1. - row := PMVector new: rowSize. - row replaceFrom: 1 to: n1 with: each startingAt: 1; - replaceFrom: n2 to: rowSize with: ( ( anArrayOfMatrices at: 4) rowAt: n) startingAt: 1. - rows add: row. - ]. - ^self rows: rows -] - -{ #category : #information } -PMMatrix class >> lupCRLCriticalDimension [ - ^ 40 -] - -{ #category : #'instance creation' } -PMMatrix class >> new: dimension [ - "Create an empty square matrix of size dimension x dimension." - - ^ self new initializeSquare: dimension -] - -{ #category : #'instance creation' } -PMMatrix class >> onesRows: rows cols: columns [ - "Creates MxN matrix of ones" - - | a b | - a := (1 to: rows) collect: [ :row | b := PMVector ones: columns ]. - ^ self rows: a -] - -{ #category : #'instance creation' } -PMMatrix class >> rows: anArrayOrVector [ - "Create a new matrix with given components." - - ^ self new initializeRows: anArrayOrVector -] - -{ #category : #'instance creation' } -PMMatrix class >> rows: rowsInteger columns: columnsInteger [ - - ^ self new initializeRows: rowsInteger columns: columnsInteger -] - -{ #category : #'instance creation' } -PMMatrix class >> rows: nRows columns: nCols element: fillElement [ - " Answer a new matrix of nRows x nCols initialized with fillElement in all cells " - - ^ (self new initializeRows: nRows columns: nCols) - atAllPut: fillElement; - yourself - -] - -{ #category : #'instance creation' } -PMMatrix class >> rows: aNumberOfRows columns: aNumberOfColumns random: aMaxNumber [ - "Answer a new Matrix of the given dimensions filled with random numbers" - | random rows | - random := Random new. - - rows := (1 to: aNumberOfRows) collect: [ :i | - (1 to: aNumberOfColumns) collect: [ :j | - random nextBetween: 0 and: aMaxNumber ] ]. - - ^ self rows: rows -] - -{ #category : #'instance creation' } -PMMatrix class >> zerosRows: rows cols: columns [ - "Creates MxN matrix of zeros" - - | a b | - a := (1 to: rows) collect: [ :row | b := PMVector zeros: columns ]. - ^ self rows: a -] - -{ #category : #operation } -PMMatrix >> * aNumberOrMatrixOrVector [ - "Answers the product of the receiver with the argument. The argument can be a number, matrix or vector." - ^ aNumberOrMatrixOrVector productWithMatrix: self -] - -{ #category : #operation } -PMMatrix >> + aMatrixOrNumber [ - "Answers the sum of the receiver with aMatrix." - ^ aMatrixOrNumber addWithRegularMatrix: self -] - -{ #category : #operation } -PMMatrix >> - aMatrix [ - "Answers the difference between the receiver and aMatrix." - ^ aMatrix subtractWithRegularMatrix: self -] - -{ #category : #operation } -PMMatrix >> < aNumber [ - "Apply < operator to each element of the matrix" - - ^ PMMatrix rows: (self rowsCollect: [ :each | each < aNumber ]) -] - -{ #category : #comparing } -PMMatrix >> = aNumberOrMatrix [ - ^ (aNumberOrMatrix species = self species) and: [ self rows = aNumberOrMatrix rows ] -] - -{ #category : #operation } -PMMatrix >> > aNumber [ - "Apply > operator to each element of the matrix" - - ^ PMMatrix rows: (self rowsCollect: [ :each | each > aNumber ]) -] - -{ #category : #arithmetic } -PMMatrix >> abs [ - "Computes the element-wise absolute value." - ^ self class rows: (rows collect: #abs). -] - -{ #category : #'double dispatching' } -PMMatrix >> adaptToNumber: rcvr andSend: selector [ - "selector must obviously be commutative for this simple solution, but at the moment its only used for multiplication" - ^ self perform: selector with: rcvr. -] - -{ #category : #'double dispatching' } -PMMatrix >> addWithRegularMatrix: aMatrix [ - "Answers the sum of the receiver with aMatrix as a PMMatrix." - | n | - n := 0. - - (self numberOfRows = aMatrix numberOfRows) & - (self numberOfColumns = aMatrix numberOfColumns) - ifFalse: [ SizeMismatch signal ]. - - ^ PMMatrix rows: ( self rowsCollect: [ :each | n := n + 1. each + ( aMatrix rowAt: n)]) -] - -{ #category : #'double dispatching' } -PMMatrix >> addWithSymmetricMatrix: aMatrix [ - ^ aMatrix addWithRegularMatrix: self -] - -{ #category : #'as yet unclassified' } -PMMatrix >> argMaxOnColumns [ - ^ self columnsCollect: [ :each | each argMax ] -] - -{ #category : #'as yet unclassified' } -PMMatrix >> argMaxOnRows [ - ^ self rowsCollect: [ :each | each argMax ] -] - -{ #category : #transformation } -PMMatrix >> asSymmetricMatrix [ - "Convert the receiver to a symmetric matrix (no check is made)." - ^ PMSymmetricMatrix rows: rows -] - -{ #category : #converting } -PMMatrix >> asVector [ - ^ self flattenRows. -] - -{ #category : #'cell accessing' } -PMMatrix >> at: aRowIndex at: aColumnIndex [ - "Answers the aRowIndex-th, aColumnIndex-th entry in the receiver." - ^ self rowAt: aRowIndex columnAt: aColumnIndex -] - -{ #category : #'cell accessing' } -PMMatrix >> at: rowIndex at: columnIndex put: value [ - - self rowAt: rowIndex columnAt: columnIndex put: value - - -] - -{ #category : #'cell accessing' } -PMMatrix >> atAllPut: element [ - "Put element at every one of the receiver's cells." - - self rowsDo: [ : row | row atAllPut: element ] -] - -{ #category : #'cell accessing' } -PMMatrix >> atColumn: aColumnNumber [ - - ^ self columnAt: aColumnNumber -] - -{ #category : #'cell accessing' } -PMMatrix >> atColumn: aColumnIndex put: aCollection [ - - aCollection withIndexDo: [: value : rowIndex | - self rowAt: rowIndex columnAt: aColumnIndex put: value ] - - -] - -{ #category : #'cell accessing' } -PMMatrix >> atColumn: columnIndex put: aValue repeat: repNumber [ - " Example: self atColumn: 1 fillWith: 'BM1818' repeat: 3 - produces - [ 'BM1818' nil nil nil - 'BM1818' nil nil nil - 'BM1818' nil nil nil - nil nil nil nil - nil nil nil nil ] -" - 1 to: repNumber do: [ : index | self rowAt: index columnAt: columnIndex put: aValue ]. -] - -{ #category : #'cell accessing' } -PMMatrix >> atColumn: aColumnNumber put: aCollection startingAt: rowNumber [ - " Fill the receiver with aCollection at aColumnNumber begining at rowNumber. " - - aCollection withIndexDo: [: value : rowIndex | - (rowIndex + rowNumber ) <= self numberOfRows - ifTrue: - [ self rowAt: rowIndex + rowNumber - columnAt: aColumnNumber - put: value ]] - - -] - -{ #category : #'cell accessing' } -PMMatrix >> atRow: aRowNumber [ - "answers the aRowNumber-th row in the receiver" - ^ self rowAt: aRowNumber -] - -{ #category : #'cell accessing' } -PMMatrix >> atRow: rowIndex put: aCollection [ - - aCollection withIndexDo: [: value : columnIndex | - self rowAt: rowIndex columnAt: columnIndex put: value ] - - -] - -{ #category : #'cell accessing' } -PMMatrix >> atRow: rowIndex put: aCollection startingAt: startColumnNumber [ - "Fill the receiver with aCollection at rowIndex beggining at startColumnNumber. " - - aCollection withIndexDo: [: value : columnIndex | - (columnIndex + startColumnNumber ) <= self numberOfColumns - ifTrue: - [ self - rowAt: rowIndex - columnAt: columnIndex + startColumnNumber - put: value ]] - - -] - -{ #category : #'as yet unclassified' } -PMMatrix >> choleskyDecomposition [ - | upperTriangular rowSum partialSum diagonalValue nonDiagonalValue factor | - - self isPositiveDefinite ifFalse: [ - Error signal: 'Choleski decomposition can only be applied to positive-definite matrices' ]. - - upperTriangular := self class - zerosRows: self numberOfRows - cols: self numberOfColumns. - - 1 to: self numberOfRows do: [ :i | - 1 to: i do: [ :j | - i = j - ifTrue: [ - rowSum := (1 to: j - 1) inject: 0 into: [ :sum :k | - sum + (upperTriangular at: k at: j) squared ]. - - diagonalValue := ((self at: j at: j) - rowSum) sqrt. - - - upperTriangular at: j at: j put: diagonalValue ] - ifFalse: [ - - partialSum := (1 to: j - 1) inject: 0 into: [ :sum :k | - sum + ((upperTriangular at: k at: i) * (upperTriangular at: k at: j)). - ]. - - factor := upperTriangular at: j at: j. - nonDiagonalValue := ((self at: j at: i) - partialSum) / factor. - - upperTriangular at: j at: i put: nonDiagonalValue. - - ] ] ]. - - ^ upperTriangular -] - -{ #category : #comparing } -PMMatrix >> closeTo: aPMMatrix [ - "Tests that we are within the default Float >> #closeTo: precision of aPMMatrix (0.0001)." - ^ self closeTo: aPMMatrix precision: 0.0001 -] - -{ #category : #comparing } -PMMatrix >> closeTo: aPMMatrix precision: aPrecision [ - ^ (self - aPMMatrix) abs sum sum < aPrecision -] - -{ #category : #iterators } -PMMatrix >> collect: aBlock [ - "Applies aBlock elementwise to each cell of the matrix." - ^ self class rows: (rows collect: [ :r | r collect: aBlock ]) -] - -{ #category : #'cell accessing' } -PMMatrix >> columnAt: anInteger [ - "Answers the anInteger-th column of the receiver." - ^ rows collect: [ :each | each at: anInteger ] -] - -{ #category : #'cell accessing' } -PMMatrix >> columnVectorAt: col size: dimension [ - - ^ (self columnAt: col) copyFrom: col to: dimension -] - -{ #category : #iterators } -PMMatrix >> columnsCollect: aBlock [ - "Perform the collect: operation on the rows of the receiver." - | n | - n := 0. - ^ rows last collect: [ :each | n := n + 1. aBlock value: (self columnAt: n)] -] - -{ #category : #iterators } -PMMatrix >> columnsDo: aBlock [ - "Perform the collect: operation on the rows of the receiver." - | n | - n := 0. - ^ rows last do: [ :each | n := n + 1. aBlock value: ( self columnAt: n)] -] - -{ #category : #operation } -PMMatrix >> cos [ - "Apply cos to each element of a matrix" - - ^ PMMatrix rows: (self rowsCollect: [ :each | each cos ]) -] - -{ #category : #operation } -PMMatrix >> cosh [ - "Apply cosh to each element of a matrix" - - ^ PMMatrix rows: (self rowsCollect: [ :each | each cosh ]) -] - -{ #category : #transformation } -PMMatrix >> cumsum [ - "Computes the cumulative sum for each row." - - ^ PMMatrix rows: (rows collect: [ :each | each cumsum ]) -] - -{ #category : #'as yet unclassified' } -PMMatrix >> decomposeSV [ - ^ PMSingularValueDecomposition decompose: self -] - -{ #category : #accessing } -PMMatrix >> determinant [ - ^ self lupDecomposition determinant -] - -{ #category : #accessing } -PMMatrix >> dimension [ - - ^ self rows size @ (self rows at: 1) size -] - -{ #category : #operation } -PMMatrix >> eigen [ - "Computes all eigenvalues and eigenvectors of a matrix. - Usage: - matrix eigen values. - matrix eigen vectors." - - self isSymmetric - ifTrue: [ ^ self asSymmetricMatrix eigen ] - ifFalse: [ self error: 'Eigenvalues and eigenvectors of non-symmetric matrix are currently not supported' ] -] - -{ #category : #'double dispatching' } -PMMatrix >> elementwiseProductWithMatrix: aMatrix [ - "Answers the elementwise product between aMatrix and the receiver as a Matrix." - | n | - n := 0. - ^ self class rows: ( aMatrix rowsCollect: [ :each | n := n + 1. each hadamardProduct: ( self rowAt: n)]) - -] - -{ #category : #'as yet unclassified' } -PMMatrix >> equalsTo: aMatrix [ - - self - deprecated: 'Use closeTo: instead' - transformWith: '`@rec equalsTo: `@arg' -> '`@rec closeTo: `@arg'. - - ^ self closeTo: aMatrix -] - -{ #category : #'as yet unclassified' } -PMMatrix >> flattenColumns [ - | answer | - answer := #(). - self columnsDo: [ :each | answer := answer , each asArray ]. - ^ answer asPMVector -] - -{ #category : #'as yet unclassified' } -PMMatrix >> flattenRows [ - | answer | - answer := #(). - self rowsDo: [ :each | answer := answer , each asArray ]. - ^ answer asPMVector -] - -{ #category : #operation } -PMMatrix >> hadamardProduct: aMatrix [ - ^ aMatrix elementwiseProductWithMatrix: self -] - -{ #category : #comparing } -PMMatrix >> hash [ - ^ rows hash -] - -{ #category : #initialization } -PMMatrix >> initializeRows: anArrayOrVector [ - "Defines the components of the recevier. No check is made: components are assumed to be orgainized in rows." - rows := anArrayOrVector asPMVector collect: [ :each | each asPMVector]. -] - -{ #category : #initialization } -PMMatrix >> initializeRows: rowsInteger columns: columnsInteger [ - "Build empty components for a matrix." - self assert: [ rowsInteger isInteger and: [ rowsInteger > 0 ] ] description: 'Row size of a matrix must be a positive integer'. - self assert: [ columnsInteger isInteger and: [ columnsInteger > 0 ] ] description: 'Column size of a matrix must be a positive integer'. - rows := (1 to: rowsInteger) asPMVector collect: [ :each | PMVector new: columnsInteger ]. -] - -{ #category : #initialization } -PMMatrix >> initializeSquare: dimension [ - "Build empty components for a square matrix. No check is made: components are assumed to be orgainized in rows." - ^ self initializeRows: dimension columns: dimension -] - -{ #category : #operation } -PMMatrix >> inverse [ - "Answer the inverse of the receiver." - - ^ self isSquare - ifTrue: [ self lupInverse ] - ifFalse: [ self squared inverse * self transpose ] -] - -{ #category : #'as yet unclassified' } -PMMatrix >> inversePivotColumns: anArray [ - "uses vector encoding of an interchange permutation matrix in anArray as in qrFactorizationWithPivoting. Does inverse pivoting!" - | res | - res :=self deepCopy. - anArray reverseWith: (1 to: anArray size ) do: [ :piv :ind | piv ~= ind ifTrue: [res swapColumn: piv withColumn: ind ] ]. - ^ res -] - -{ #category : #operation } -PMMatrix >> inversePureCRL [ - "Answer the inverse of the receiver." - ^ self squared inversePureCRL * self transpose -] - -{ #category : #testing } -PMMatrix >> isHermitian [ - "Hermitian matrix (or self-adjoint matrix) is a complex square matrix that is equal to its own conjugate transpose — that is, the element in the i-th row and j-th column is equal to the complex conjugate of the element in the j-th row and i-th column, for all indices i and j" - - self isSquare ifFalse: [ ^ false ]. - - 1 to: self numberOfRows do: [ :i | - 1 to: (i - 1) do: [ :j | - ((self at: i at: j) complexConjugate = (self at: j at: i)) - ifFalse: [ ^ false ] ] ]. - - ^ true -] - -{ #category : #testing } -PMMatrix >> isNegativeDefinite [ - "A Hermitian matrix is negative definite if and only if all its eigenvalues are strictly negative" - self isHermitian ifFalse: [ ^ false ]. - ^ self eigen values allSatisfy: [ :each | each < 0 ] -] - -{ #category : #testing } -PMMatrix >> isNegativeSemiDefinite [ - "A Hermitian matrix is negative semi-definite if and only if all its eigenvalues are non-positive" - self isHermitian ifFalse: [ ^ false ]. - ^ self eigen values allSatisfy: [ :each | each <= 0 ] -] - -{ #category : #testing } -PMMatrix >> isPositiveDefinite [ - "A Hermitian matrix is positive definite if and only if all its eigenvalues are strictly positive" - self isHermitian ifFalse: [ ^ false ]. - ^ self eigen values allSatisfy: [ :each | each > 0 ] -] - -{ #category : #testing } -PMMatrix >> isPositiveSemiDefinite [ - "A Hermitian matrix is positive semi-definite if and only if all its eigenvalues are non-negative" - self isHermitian ifFalse: [ ^ false ]. - ^ self eigen values allSatisfy: [ :each | each >= 0 ] -] - -{ #category : #testing } -PMMatrix >> isReal [ - "Answer true if all values of the matrix are real numbers" - ^ rows allSatisfy: [ :vector | vector isReal ]. -] - -{ #category : #testing } -PMMatrix >> isSquare [ - "Answers true if the number of rows is equal to the number of columns." - ^ rows size = rows last size -] - -{ #category : #testing } -PMMatrix >> isSymmetric [ - ^ self = self transpose -] - -{ #category : #private } -PMMatrix >> largestPowerOf2SmallerThan: anInteger [ - "Private" - | m m2| - m := 2. - [ m2 := m * 2. - m2 < anInteger] whileTrue:[ m := m2]. - ^m -] - -{ #category : #operation } -PMMatrix >> log [ - "Apply log to each element of a matrix" - ^ PMMatrix rows: ( self rowsCollect: [ :each | each log]) - -] - -{ #category : #accessing } -PMMatrix >> lupDecomposition [ - - lupDecomposition isNil - ifTrue: [ lupDecomposition :=PMLUPDecomposition equations: rows ]. - ^ lupDecomposition -] - -{ #category : #operation } -PMMatrix >> lupInverse [ - self lupDecomposition inverseMatrixComponents - ifNil: [ PMSingularMatrixError new signal ] - ifNotNil: [ :i | ^ self class rows: i ] -] - -{ #category : #operation } -PMMatrix >> minor: rowIndex and: columnIndex [ - - ^ PMMatrix rows: - ((self rows allButFirst: columnIndex) collect: [ :aRow | - aRow allButFirst: rowIndex ]) -] - -{ #category : #'as yet unclassified' } -PMMatrix >> mpInverse [ - "Moore Penrose Inverse. " - |f g| - self numberOfRows < self numberOfColumns - ifTrue:[ f := self transpose qrFactorizationWithPivoting. - g := f first. - f := f second inversePivotColumns: (f at:3) ] - ifFalse: [ f := self qrFactorizationWithPivoting. - g := (f second inversePivotColumns: (f at:3)) transpose. - f := f first transpose ]. - ^ g * ((f *self *g) inverse) *f -] - -{ #category : #transformation } -PMMatrix >> negate [ - "Inverse the sign of all components of the receiver." - rows do: [ :each |each negate ] -] - -{ #category : #accessing } -PMMatrix >> numberOfColumns [ - "Answer the number of rows of the receiver." - ^ rows last size -] - -{ #category : #accessing } -PMMatrix >> numberOfRows [ - "Answer the number of rows of the receiver." - ^ rows size -] - -{ #category : #'as yet unclassified' } -PMMatrix >> orthogonalize [ - "returns an orthonormal basis of column (!) vectors for a matrix of column vectors" - ^ self qrFactorizationWithPivoting first - -] - -{ #category : #'as yet unclassified' } -PMMatrix >> principalDiagonal [ - "https://en.wikipedia.org/wiki/Diagonal#Matrices for definitions" - | diag | - "Check for square" - self isSquare ifFalse: [ self error: 'Diagonal is not defined for a matrix that is not square.' ]. - diag := PMVector new: self rows size. - (1 to: diag size) do: [ :i | diag at: i put: (self at:i at: i) ]. - ^ diag -] - -{ #category : #printing } -PMMatrix >> printOn: aStream [ - (rows isNil or: [rows first isNil]) - ifTrue: [ super printOn: aStream. - aStream nextPutAll:'(uninitialized)'. ^ self ]. - rows - do: [ :each | each printOn: aStream] - separatedBy: [ aStream cr]. - - -] - -{ #category : #private } -PMMatrix >> privateTranspose [ - ^ self transpose -] - -{ #category : #'double dispatching' } -PMMatrix >> productWithMatrix: aMatrix [ - "Answers the product of aMatrix with the receiver (in this order)." - ^ self productWithMatrixFinal: aMatrix -] - -{ #category : #'double dispatching' } -PMMatrix >> productWithMatrixFinal: aMatrix [ - "Answers the product of aMatrix with the receiver (in this order)." - "speed optimized" - |t| - t :=self privateTranspose. - ^ PMMatrix rows: ( aMatrix rowsCollect: [ :row | t rowsCollect: [ :col | row * col]]) -] - -{ #category : #'double dispatching' } -PMMatrix >> productWithTransposeMatrix: aMatrix [ - "Answers the product of the receiver with the transpose of aMatrix(in this order)." - ^ PMMatrix rows: (self rowsCollect: [ :row | aMatrix rowsCollect: [ :col | row * col]]) -] - -{ #category : #'double dispatching' } -PMMatrix >> productWithVector: aVector [ - "Answers the product of the receiver with aVector" - ^ self columnsCollect: [ :each | each * aVector ] -] - -{ #category : #'as yet unclassified' } -PMMatrix >> qrFactorization [ - - ^ (PMQRDecomposition of: self) decompose -] - -{ #category : #'as yet unclassified' } -PMMatrix >> qrFactorizationWithPivoting [ - - | identMat q r hh colSize i lengthArray rank mx pivot | - self numberOfRows < self numberOfColumns ifTrue: [ - self error: 'numberOfRows 0 - ifTrue: [ lengthArray indexOf: mx startingAt: rank + 1 ] - ifFalse: [ 0 ] ] - ifFalse: [ mx := 0 ]. - mx > 0 ] whileTrue. - i := 0. - [ (r rowAt: colSize) allSatisfy: [ :n | n = 0 ] ] whileTrue: [ - i := i + 1. - colSize := colSize - 1 ]. - i > 0 ifTrue: [ - r := PMMatrix rows: (r rows copyFrom: 1 to: colSize). - i := q numberOfColumns - i. - pivot := pivot copyFrom: 1 to: i. - q := PMMatrix rows: - (q rows collect: [ :row | row copyFrom: 1 to: i ]) ]. - ^ Array with: q with: r with: pivot -] - -{ #category : #operation } -PMMatrix >> raisedTo: aPower [ - - " Answers the receiver raised to a power, aPower . - If aPower is negative, inverse of the receiver is raised to the absolute value of aPower." - - |aRaisedPMMatrix| - - self assert: self isSquare description: 'Matrix should be square'. - - aPower < 0 ifTrue: [ - ^ self inverse raisedTo: aPower abs ]. - - aRaisedPMMatrix := PMMatrix identity: self numberOfRows. - - 1 to: aPower do: [ :each | - aRaisedPMMatrix := aRaisedPMMatrix * self ]. - - ^ aRaisedPMMatrix -] - -{ #category : #'as yet unclassified' } -PMMatrix >> rank [ - ^ ((self numberOfRows < self numberOfColumns - ifTrue: [ self transpose ] - ifFalse: [ self ]) qrFactorizationWithPivoting at: 2) rows size -] - -{ #category : #'cell accessing' } -PMMatrix >> rowAt: anInteger [ - "Answers the anInteger-th row of the receiver." - ^ rows at: anInteger -] - -{ #category : #'cell accessing' } -PMMatrix >> rowAt: aRowIndex columnAt: aColumnIndex [ - "Answers the aRowIndex-th, aColumnIndex-th entry in the receiver." - ^ (rows at: aRowIndex) at: aColumnIndex -] - -{ #category : #'cell accessing' } -PMMatrix >> rowAt: aRowIndex columnAt: aColumnIndex put: aValue [ - - ^(rows at: aRowIndex) at: aColumnIndex put: aValue -] - -{ #category : #'cell accessing' } -PMMatrix >> rows [ - ^rows -] - -{ #category : #iterators } -PMMatrix >> rowsCollect: aBlock [ - "Perform the collect: operation on the rows of the receiver." - ^ rows collect: aBlock -] - -{ #category : #iterators } -PMMatrix >> rowsDo: aBlock [ - "Perform the collect: operation on the rows of the receiver." - ^ rows do: aBlock -] - -{ #category : #iterators } -PMMatrix >> rowsWithIndexDo: aBlock [ - - ^ rows withIndexDo: aBlock -] - -{ #category : #transformation } -PMMatrix >> scaleBy: aNumber [ - - rows do: [ :each | each scaleBy: aNumber ] -] - -{ #category : #'cell accessing' } -PMMatrix >> setDiagonal: aVector [ - - | n m | - n := self numberOfRows. - m := self numberOfColumns. - n < m - ifTrue: [ - 1 to: n do: [ :i | self rowAt: i columnAt: i put: (aVector at: i)]. - ] - ifFalse: [ - 1 to: m do: [ :i | self rowAt: i columnAt: i put: (aVector at: i)]. - ]. - ^self -] - -{ #category : #operation } -PMMatrix >> sign [ - "Apply sign to each element of a matrix" - - ^ PMMatrix rows: (self rowsCollect: [ :each | each sign ]) -] - -{ #category : #operation } -PMMatrix >> sin [ - "Apply sin to each element of a matrix" - - ^ PMMatrix rows: (self rowsCollect: [ :each | each sin ]) -] - -{ #category : #operation } -PMMatrix >> sinh [ - "Apply sinh to each element of a matrix" - - ^ PMMatrix rows: (self rowsCollect: [ :each | each sinh ]) -] - -{ #category : #private } -PMMatrix >> species [ - ^ PMMatrix -] - -{ #category : #private } -PMMatrix >> split [ - "Private - Answers an array of 4 matrices split from the receiver." - | n m n1 m1 | - n := self numberOfRows. - m := self numberOfColumns. - n1 := self largestPowerOf2SmallerThan: n. - m1 := self largestPowerOf2SmallerThan: m. - ^ Array - with: ( self class rows: ( ( 1 to: n1) asPMVector collect: [ :k | ( rows at: k) copyFrom: 1 to: m1])) - with:( self class rows: ( ( 1 to: n1) asPMVector collect: [ :k | ( rows at: k) copyFrom: (m1 + 1) to: m])) - with: ( self class rows: ( ( (n1 + 1) to: n) asPMVector collect: [ :k | ( rows at: k) copyFrom: 1 to: m1])) - with:( self class rows: ( ( (n1 + 1) to: n) asPMVector collect: [ :k | ( rows at: k) copyFrom: (m1 + 1) to: m])) -] - -{ #category : #operation } -PMMatrix >> sqrt [ - "Apply sqrt to each element of a matrix" - - ^ PMMatrix rows: ( self rowsCollect: [ :each | each sqrt]) -] - -{ #category : #operation } -PMMatrix >> squared [ - | transposed | - transposed :=self privateTranspose. - ^ PMSymmetricMatrix - new: transposed numberOfRows - function: [ :x :y|(transposed rowAt: x) * (transposed rowAt: y) ] - -] - -{ #category : #private } -PMMatrix >> strassenProductWithMatrix: aMatrix [ - "Private" - | matrixSplit selfSplit p1 p2 p3 p4 p5 p6 p7 | - - ( self numberOfRows > 2 and: [ self numberOfColumns > 2]) - ifFalse:[ ^self class rows: ( aMatrix rowsCollect: [ :row | self columnsCollect: [ :col | row * col]])]. - - self assert: [ self numberOfRows isPowerOfTwo and: self numberOfColumns isPowerOfTwo ] description: 'Matrix size should be a power of two'. - self assert: [ aMatrix numberOfRows isPowerOfTwo and: aMatrix numberOfColumns isPowerOfTwo ] description: 'Matrix size should be a power of two'. - - selfSplit := self split. - matrixSplit := aMatrix split. - p1 := ( ( selfSplit at: 2) - ( selfSplit at: 4)) strassenProductWithMatrix: ( matrixSplit at: 1). - p2 := ( selfSplit at: 4) strassenProductWithMatrix: ( ( matrixSplit at: 1) + ( matrixSplit at: 2)). - p3 := ( selfSplit at: 1) strassenProductWithMatrix: ( ( matrixSplit at: 3) + ( matrixSplit at: 4)). - p4 := ( ( selfSplit at: 3) - ( selfSplit at: 1)) strassenProductWithMatrix: ( matrixSplit at: 4). - p5 := ( ( selfSplit at: 1) + ( selfSplit at: 4)) strassenProductWithMatrix: ( ( matrixSplit at: 1) + ( matrixSplit at: 4)). - p6 := ( ( selfSplit at: 3) + ( selfSplit at: 4)) strassenProductWithMatrix: ( ( matrixSplit at: 2) - ( matrixSplit at: 4)). - p7 := ( ( selfSplit at: 1) + ( selfSplit at: 2)) strassenProductWithMatrix: ( ( matrixSplit at: 1) - ( matrixSplit at: 3)). - ^self class join: ( Array - with: ( p5 + p4 + p6 - p2) - with: (p1 + p2) - with: ( p3 + p4) - with: ( p5 + p1 - p3 - p7) - ) -] - -{ #category : #'double dispatching' } -PMMatrix >> subtractWithRegularMatrix: aMatrix [ - "Answers the difference between aMatrix and the receiver as a Matrix." - | n | - n := 0. - ^ PMMatrix rows: ( aMatrix rowsCollect: [ :each | n := n + 1. each - ( self rowAt: n)]) -] - -{ #category : #'double dispatching' } -PMMatrix >> subtractWithSymmetricMatrix: aMatrix [ - "Answers the difference between aMatrix and the receiver." - ^ self subtractWithRegularMatrix: aMatrix -] - -{ #category : #transformation } -PMMatrix >> sum [ - "Computes the row sum." - - | a | - a := PMVector new: self numberOfRows. - 1 to: a size do: [ :n | a at: n put: (self rowAt: n) sum ]. - ^ a -] - -{ #category : #'as yet unclassified' } -PMMatrix >> swapColumn: anIndex withColumn: a2Index [ - self rowsDo: [ :r| r swap: anIndex with: a2Index ] - -] - -{ #category : #arithmetic } -PMMatrix >> take: anInteger [ - - " Answer a with the receiver's binomial coefficient at each element for anInteger " - - ^ self collect: [ :each | each numberOfCombinationsTaken: anInteger ] -] - -{ #category : #operation } -PMMatrix >> tan [ - "Apply tan to each element of a matrix" - - ^ PMMatrix rows: (self rowsCollect: [ :each | each tan ]) -] - -{ #category : #operation } -PMMatrix >> tanh [ - "Apply tanh to each element of a matrix" - - ^ PMMatrix rows: (self rowsCollect: [ :each | each tanh ]) -] - -{ #category : #operation } -PMMatrix >> tr [ - "Return the trace or sum along diagonals of the array." - "https://en.wikipedia.org/wiki/Trace_(linear_algebra)" - - | result | - result := 0. - 1 to: self numberOfRows do: [ :n | result := result + (self at: n at: n) ]. - ^ result -] - -{ #category : #operation } -PMMatrix >> transpose [ - "Answer a new matrix, transpose of the receiver." - ^ self class rows: ( self columnsCollect: [ :each | each]) -] - -{ #category : #'double dispatching' } -PMMatrix >> transposeProductWithMatrix: aMatrix [ - "Answers the product of the transpose of the receiver with aMatrix (in this order)." - "speed optimized" - |t| - t :=aMatrix privateTranspose. - ^ PMMatrix rows: (self columnsCollect: [ :row | t rowsCollect: [ :col | row * col]]) -] diff --git a/src/Math-Matrix/PMNDArray.class.st b/src/Math-Matrix/PMNDArray.class.st deleted file mode 100644 index bf53739bb..000000000 --- a/src/Math-Matrix/PMNDArray.class.st +++ /dev/null @@ -1,180 +0,0 @@ -Class { - #name : #PMNDArray, - #superclass : #Object, - #instVars : [ - 'array', - 'shape', - 'first', - 'strides' - ], - #category : #'Math-Matrix' -} - -{ #category : #'instance creation' } -PMNDArray class >> fromNestedArray: anArray [ - - ^ self new array: anArray flattened withShape: (self shape:anArray) -] - -{ #category : #'instance creation' } -PMNDArray class >> fromScalar: anInteger [ - - ^ self new array: {anInteger} withShape: #( ) -] - -{ #category : #'instance creation' } -PMNDArray class >> newWith: anInteger [ - - ^ self new array: {anInteger} withShape: #( ) -] - -{ #category : #accessing } -PMNDArray class >> shape: anArray [ - -anArray isArray ifFalse:[^#()] -ifTrue:[ - ^ {anArray size}, (self shape: anArray first) - ] - -] - -{ #category : #comparing } -PMNDArray >> = aPMNDArray [ - - ^ array = aPMNDArray asArray & (first = aPMNDArray first) - & (strides = aPMNDArray strides) & (shape = aPMNDArray shape) -] - -{ #category : #'as yet unclassified' } -PMNDArray >> array: aFlatArray withShape: aShape [ - - array := aFlatArray. - shape := aShape copy. - self updateFirst. - shape ifNotEmpty: [ self updateStrides] -] - -{ #category : #private } -PMNDArray >> asArray [ - ^array -] - -{ #category : #public } -PMNDArray >> at: coords [ - - | position | - position := self flattenedIndexOf: coords. - ^ array at: position -] - -{ #category : #initialization } -PMNDArray >> at: coords put: aValue [ - -array at: (self flattenedIndexOf: coords) put: aValue -] - -{ #category : #accessing } -PMNDArray >> first [ -^first -] - -{ #category : #'primitives - file' } -PMNDArray >> flattenedIndexOf: coords [ - - | position | - position := 1. - coords withIndexDo: [ :elt :i | - position := (elt - 1) * (strides at: i) + position ]. - ^ position -] - -{ #category : #'as yet unclassified' } -PMNDArray >> fromNestedArray: aFlatArray withShape: aShape [ - - array := aFlatArray. - shape := aShape copy. - self updateFirst. - shape ifNotEmpty: [ self updateStrides] -] - -{ #category : #operation } -PMNDArray >> hadamardProduct: aPMNDArray [ - ^ self with: aPMNDArray collect: [:a :b| a*b] - - -] - -{ #category : #testing } -PMNDArray >> hasSameShapeAs: aPMNDArray [ - ^ self shape = aPMNDArray shape -] - -{ #category : #accessing } -PMNDArray >> rank [ - ^ shape size -] - -{ #category : #'as yet unclassified' } -PMNDArray >> reshape: aNewShape [ - - ^ self viewWithShape: aNewShape. - -] - -{ #category : #accessing } -PMNDArray >> shape [ - - ^ shape -] - -{ #category : #accessing } -PMNDArray >> size [ - -^ shape inject: 1 into: [ :each :product | each * product]. - -] - -{ #category : #accessing } -PMNDArray >> strides [ -^strides -] - -{ #category : #'as yet unclassified' } -PMNDArray >> updateFirst [ - - first := Array new: shape size withAll: 1 -] - -{ #category : #'as yet unclassified' } -PMNDArray >> updateStrides [ - - strides := Array new: shape size. - strides at: shape size put: 1. - ((shape size -1) to: 1 by: -1) do: [ :i | - strides at: i put: ((strides at: i + 1) * (shape at: i+1))] -] - -{ #category : #'as yet unclassified' } -PMNDArray >> view [ - - "Share only the array" - - ^ self viewWithShape: shape -] - -{ #category : #'as yet unclassified' } -PMNDArray >> viewWithShape: aNewShape [ - - ^ PMNDArray new array: self asArray withShape: aNewShape - -] - -{ #category : #operation } -PMNDArray >> with: aPMNDArray collect: aBlock [ - (self hasSameShapeAs: aPMNDArray) - ifFalse:[ShapeMismatch signal ]. - ^ self class new array: ((self asArray) with: (aPMNDArray asArray) collect: aBlock) - withShape: self shape. - - -] diff --git a/src/Math-Matrix/PMQRDecomposition.class.st b/src/Math-Matrix/PMQRDecomposition.class.st deleted file mode 100644 index f5213976a..000000000 --- a/src/Math-Matrix/PMQRDecomposition.class.st +++ /dev/null @@ -1,185 +0,0 @@ -" -I am responsible for the decomposition of a matrix, A say, into a product A = QR of an orthogonal matrix Q and an upper triangular matrix R -" -Class { - #name : #PMQRDecomposition, - #superclass : #Object, - #instVars : [ - 'matrixToDecompose', - 'colSize', - 'r', - 'q' - ], - #category : #'Math-Matrix' -} - -{ #category : #'instance creation' } -PMQRDecomposition class >> of: matrix [ - matrix numberOfRows < matrix numberOfColumns ifTrue: [ - self error: 'numberOfRows> decompose [ - - " -The method appears to be using Householder reflection. There is a wiki page -that describes the mechanics: -https://en.wikipedia.org/wiki/QR_decomposition#Using_Householder_reflections -" - - | i matrixOfMinor | - 1 to: self numberOfColumns do: [ :col | - | householderReflection householderMatrix householderVector columnVectorFromRMatrix | - columnVectorFromRMatrix := r columnVectorAt: col size: colSize. - householderReflection := self - householderReflectionOf: - columnVectorFromRMatrix - atColumnNumber: col. - householderVector := householderReflection at: 1. - householderMatrix := householderReflection at: 2. - q := q * householderMatrix. - matrixOfMinor := r minor: col - 1 and: col - 1. - matrixOfMinor := matrixOfMinor - - ((householderVector at: 2) tensorProduct: - (householderVector at: 1) - * (householderVector at: 2) * matrixOfMinor). - matrixOfMinor rowsWithIndexDo: [ :aRow :index | - aRow withIndexDo: [ :element :column | - | rowNumber columnNumber | - rowNumber := col + index - 1. - columnNumber := col + column - 1. - r - rowAt: rowNumber - columnAt: columnNumber - put: ((element closeTo: 0) - ifTrue: [ 0 ] - ifFalse: [ element ]) ] ] ]. - i := 0. - [ (r rowAt: colSize) isZero ] whileTrue: [ - i := i + 1. - colSize := colSize - 1 ]. - i > 0 ifTrue: [ - r := self upperTriangularPartOf: r With: colSize. - i := q numberOfColumns - i. - q := PMMatrix rows: - (q rowsCollect: [ :row | row copyFrom: 1 to: i ]) ]. - ^ Array with: q with: r -] - -{ #category : #arithmetic } -PMQRDecomposition >> decomposeWithPivot [ - - | i vectorOfNormSquareds rank positionOfMaximum pivot matrixOfMinor | - vectorOfNormSquareds := matrixToDecompose columnsCollect: [ - :columnVector | columnVector * columnVector ]. - positionOfMaximum := vectorOfNormSquareds indexOf: vectorOfNormSquareds max. - pivot := Array new: vectorOfNormSquareds size. - rank := 0. - [ - | householderReflection householderMatrix householderVector columnVectorFromRMatrix | - rank := rank + 1. - pivot at: rank put: positionOfMaximum. - r swapColumn: rank withColumn: positionOfMaximum. - vectorOfNormSquareds swap: rank with: positionOfMaximum. - columnVectorFromRMatrix := r columnVectorAt: rank size: colSize. - householderReflection := self - householderReflectionOf: - columnVectorFromRMatrix - atColumnNumber: rank. - householderVector := householderReflection at: 1. - householderMatrix := householderReflection at: 2. - q := q * householderMatrix. - matrixOfMinor := r minor: rank - 1 and: rank - 1. - matrixOfMinor := matrixOfMinor - - ((householderVector at: 2) tensorProduct: - (householderVector at: 1) - * (householderVector at: 2) * matrixOfMinor). - matrixOfMinor rowsWithIndexDo: [ :aRow :index | - aRow withIndexDo: [ :element :column | - | rowNumber columnNumber | - rowNumber := rank + index - 1. - columnNumber := rank + column - 1. - r - rowAt: rowNumber - columnAt: columnNumber - put: ((element closeTo: 0) - ifTrue: [ 0 ] - ifFalse: [ element ]) ] ]. - rank + 1 to: vectorOfNormSquareds size do: [ :ind | - vectorOfNormSquareds - at: ind - put: - (vectorOfNormSquareds at: ind) - - (r rowAt: rank columnAt: ind) squared ]. - rank < vectorOfNormSquareds size - ifTrue: [ - positionOfMaximum := (vectorOfNormSquareds - copyFrom: rank + 1 - to: vectorOfNormSquareds size) max. - (positionOfMaximum closeTo: 0) ifTrue: [ positionOfMaximum := 0 ]. - positionOfMaximum := positionOfMaximum > 0 - ifTrue: [ - vectorOfNormSquareds indexOf: positionOfMaximum startingAt: rank + 1 ] - ifFalse: [ 0 ] ] - ifFalse: [ positionOfMaximum := 0 ]. - positionOfMaximum > 0 ] whileTrue. - i := 0. - [ (r rowAt: colSize) isZero ] whileTrue: [ - i := i + 1. - colSize := colSize - 1 ]. - i > 0 ifTrue: [ - r := self upperTriangularPartOf: r With: colSize. - i := q numberOfColumns - i. - pivot := pivot copyFrom: 1 to: i. - q := PMMatrix rows: - (q rowsCollect: [ :row | row copyFrom: 1 to: i ]) ]. - ^ Array with: q with: r with: pivot -] - -{ #category : #private } -PMQRDecomposition >> householderReflectionOf: columnVector atColumnNumber: columnNumber [ - - | householderVector v identityMatrix householderMatrix | - householderVector := columnVector householder. - v := (PMVector zeros: columnNumber - 1) , (householderVector at: 2). - identityMatrix := PMSymmetricMatrix identity: colSize. - householderMatrix := identityMatrix - - - ((householderVector at: 1) * v tensorProduct: v). - ^ Array with: householderVector with: householderMatrix . -] - -{ #category : #private } -PMQRDecomposition >> initialQMatrix [ - - ^ PMSymmetricMatrix identity: colSize -] - -{ #category : #private } -PMQRDecomposition >> initialRMatrix [ - - ^ PMMatrix rows: matrixToDecompose rows deepCopy -] - -{ #category : #private } -PMQRDecomposition >> numberOfColumns [ - - ^ matrixToDecompose numberOfColumns -] - -{ #category : #'instance creation' } -PMQRDecomposition >> of: matrix [ - - matrixToDecompose := matrix. - colSize := matrixToDecompose numberOfRows. - r := self initialRMatrix. - q := self initialQMatrix. -] - -{ #category : #private } -PMQRDecomposition >> upperTriangularPartOf: matrix With: columnSize [ - - ^ PMMatrix rows: (r rows copyFrom: 1 to: columnSize) -] diff --git a/src/Math-Matrix/PMSingularMatrixError.class.st b/src/Math-Matrix/PMSingularMatrixError.class.st deleted file mode 100644 index 6bf7cc4d7..000000000 --- a/src/Math-Matrix/PMSingularMatrixError.class.st +++ /dev/null @@ -1,22 +0,0 @@ -" -some calculations dont work with singular matrices and result eg with errors like 'receiver of last is nil', deep down in the calculation, which is quite ununderstandable. otoh these errors can occasionally be treated by using another calculation, hence i introduced this error. - -" -Class { - #name : #PMSingularMatrixError, - #superclass : #ArithmeticError, - #category : 'Math-Matrix' -} - -{ #category : #accessing } -PMSingularMatrixError >> messageText [ - "Overwritten to initialize the message text to a standard text if it has not yet been set" - ^ messageText ifNil: [ messageText := self standardMessageText ] -] - -{ #category : #printing } -PMSingularMatrixError >> standardMessageText [ - ^ String streamContents: [ :stream | - stream << (self signalerContext asString findTokens: '>')last. - stream << ' encountered a singular matrix'] -] diff --git a/src/Math-Matrix/PMSingularValueDecomposition.class.st b/src/Math-Matrix/PMSingularValueDecomposition.class.st deleted file mode 100644 index e30eb85e5..000000000 --- a/src/Math-Matrix/PMSingularValueDecomposition.class.st +++ /dev/null @@ -1,117 +0,0 @@ -" -Singular Value Decomposition method. -https://en.wikipedia.org/wiki/Singular_value_decomposition - -A = U * S * V transpose - -Input: - - A - m x n matrix - -Output: - - U - m x m unitary matrix. - - V - n x n unitary matrix. - - S - diagonal matrix with singular components on the main diagonal - -Example: -[ [ [ -matrix := PMMatrix rows: #( - (0 1 0 0) - (0 0 2 0) - (0 0 0 3) - (0 0 0 0)). - -svd := matrix decomposeSV. -u := svd leftSingularForm. -v := svd rightSingularForm. -s := svd sForm. - ] ] ] - - -" -Class { - #name : #PMSingularValueDecomposition, - #superclass : #Object, - #instVars : [ - 'diagonalSingularValueMatrix', - 'leftSingularMatrix', - 'rightSingularMatrix' - ], - #category : #'Math-Matrix' -} - -{ #category : #'instance creation' } -PMSingularValueDecomposition class >> decompose: aMatrix [ - ^ self new initialize: aMatrix -] - -{ #category : #accessing } -PMSingularValueDecomposition >> diagonalSingularValueMatrix [ - "Diagonal matrix S in A = USV decomposition. All elements are 0 except those on the main diagonal. The values on the diagonal are singular values of matrix A. By convention, they are sorted in descending order" - - ^ diagonalSingularValueMatrix -] - -{ #category : #initialization } -PMSingularValueDecomposition >> initialize: aMatrix [ - - | m n symU symV eigenU eigenV diag | - m := aMatrix numberOfRows. - n := aMatrix numberOfColumns. - symU := aMatrix * aMatrix transpose. - symV := aMatrix transpose * aMatrix. - - "Expensive computation" - eigenU := symU eigen. - eigenV := symV eigen. - leftSingularMatrix := (PMMatrix rows: eigenU vectors) transpose. - rightSingularMatrix := (PMMatrix rows: eigenV vectors) transpose. - diag := m < n - ifTrue: [ eigenU values ] - ifFalse: [ eigenV values ]. - diagonalSingularValueMatrix := PMMatrix rows: m columns: n random: 0. - diagonalSingularValueMatrix setDiagonal: diag sqrt -] - -{ #category : #accessing } -PMSingularValueDecomposition >> leftSingularForm [ - - self - deprecated: 'Use leftSingularMatrix instead' - transformWith:'`@receiver leftSingularForm' -> '`@receiver leftSingularMatrix'. - - ^ leftSingularMatrix -] - -{ #category : #accessing } -PMSingularValueDecomposition >> leftSingularMatrix [ - "Matrix U in the A = USV decomposition. The columns of this matrix are the eigenvectors of the A * (A transposed) matrix (called left singular vectors). The columns of this matrix are orthonormal" - - ^ leftSingularMatrix -] - -{ #category : #accessing } -PMSingularValueDecomposition >> rightSingularForm [ - - self - deprecated: 'Use rightSingularMatrix instead' - transformWith: '`@receiver rightSingularForm' -> '`@receiver rightSingularMatrix'. - - ^ rightSingularMatrix -] - -{ #category : #accessing } -PMSingularValueDecomposition >> rightSingularMatrix [ - "Matrix V in the A = USV decomposition. The columns of this matrix are the eigenvectors of the (A transposed) * A matrix (called right singular vectors). The columns of this matrix are orthonormal" - - ^ rightSingularMatrix -] - -{ #category : #accessing } -PMSingularValueDecomposition >> sForm [ - - self - deprecated: 'Use diagonalSingularValueMatrix instead' - transformWith: '`@receiver sForm' -> '`@receiver diagonalSingularValueMatrix'. - - ^ diagonalSingularValueMatrix -] diff --git a/src/Math-Matrix/PMSymmetricMatrix.class.st b/src/Math-Matrix/PMSymmetricMatrix.class.st deleted file mode 100644 index 4ec14fec3..000000000 --- a/src/Math-Matrix/PMSymmetricMatrix.class.st +++ /dev/null @@ -1,292 +0,0 @@ -" -This class can be instantiated like PMMatrix via #rows:, but the user has to make sure that this matrix is indeed symmetric as this is not internally checked for speed reasons. -" -Class { - #name : #PMSymmetricMatrix, - #superclass : #PMMatrix, - #category : #'Math-Matrix' -} - -{ #category : #'instance creation' } -PMSymmetricMatrix class >> identity: anInteger [ - "Create an identity matrix of dimension anInteger" - ^self new initializeIdentity: anInteger -] - -{ #category : #'instance creation' } -PMSymmetricMatrix class >> join: anArrayOfMatrices [ - "Inverse of the split operation" - | rows n | - rows := OrderedCollection new. - n := 0. - ( anArrayOfMatrices at: 1) rowsDo: - [ :each | - n := n + 1. - rows add: each, ( ( anArrayOfMatrices at: 3) columnAt: n). - ]. - n := 0. - ( anArrayOfMatrices at: 2) rowsDo: - [ :each | - n := n + 1. - rows add: ( ( anArrayOfMatrices at: 3) rowAt: n), each. - ]. - ^self rows: rows -] - -{ #category : #information } -PMSymmetricMatrix class >> lupCRLCriticalDimension [ - ^36 -] - -{ #category : #'instance creation' } -PMSymmetricMatrix class >> new: dim function: aBlock [ -"Answer a new symmetric matrix with dimensions dim filled with -aBlock value: RowposRespectivelyColpos value: ColposRespectivelyRowpos" - |a aRow| - a:=self new basicInitialize: dim. - aRow := PMVector new: dim. - 1 to: dim do:[:i|aRow at: i put: (aBlock value: i value:1)]. - a rows at: 1 put: aRow. - 2 to: dim do: [:rowPos| - aRow :=PMVector new: dim . - 1 to: rowPos -1 do:[:pos| aRow at: pos put: ((a rows at: pos) at: rowPos)]. - rowPos to: dim do:[:pos| aRow at: pos put: (aBlock value: rowPos value:pos)]. - (a rows) at: rowPos put: aRow ]. - ^a -] - -{ #category : #'instance creation' } -PMSymmetricMatrix class >> new: dim random: aMaxNumber [ - "Answer a new symmetric matrix of the given dimensions filled with random numbers" - | matrix random aRow | - - matrix := self new: dim. - random := Random new. - - 1 to: dim do: [ :i | - matrix rowAt: 1 columnAt: i put: (random nextBetween: 0 and: aMaxNumber)]. - - 2 to: dim do: [ :j | - aRow :=PMVector new: dim . - - 1 to: j - 1 do: [ :i | aRow at: i put: (matrix rowAt: i columnAt: j) ]. - j to: dim do: [ :i | aRow at: i put: (random nextBetween: 0 and: aMaxNumber) ]. - (matrix rows) at: j put: aRow ] . - ^ matrix -] - -{ #category : #'instance creation' } -PMSymmetricMatrix class >> rows: rows columns: columns random: aMaxNumber [ - ^ self shouldNotImplement -] - -{ #category : #operation } -PMSymmetricMatrix >> + aMatrix [ - "Answers the sum of the receiver with aMatrix." - ^ aMatrix addWithSymmetricMatrix: self -] - -{ #category : #operation } -PMSymmetricMatrix >> - aMatrix [ - "Answers the difference between the receiver and aMatrix" - ^ aMatrix subtractWithSymmetricMatrix: self -] - -{ #category : #'double dispatching' } -PMSymmetricMatrix >> addWithSymmetricMatrix: aMatrix [ - ^self class - new: aMatrix numberOfRows - function: [ :x :y|((rows at:x)at:y)+((aMatrix rows at:x)at:y) ] - -] - -{ #category : #transformation } -PMSymmetricMatrix >> asSymmetricMatrix [ - "simple speed up" - - ^ self -] - -{ #category : #information } -PMSymmetricMatrix >> atColumn: aColumnIndex put: aCollection [ - self shouldNotImplement -] - -{ #category : #information } -PMSymmetricMatrix >> atRow: aRowIndex put: aCollection [ - self shouldNotImplement -] - -{ #category : #initialization } -PMSymmetricMatrix >> basicInitialize: anInteger [ - "private" - rows := PMVector new: anInteger. -] - -{ #category : #initialization } -PMSymmetricMatrix >> clear [ - - rows do: [ :each | each atAllPut: 0]. -] - -{ #category : #information } -PMSymmetricMatrix >> columnAt: anInteger [ - ^ rows at: anInteger -] - -{ #category : #iterators } -PMSymmetricMatrix >> columnsCollect: aBlock [ - ^ rows collect: aBlock -] - -{ #category : #iterators } -PMSymmetricMatrix >> columnsDo: aBlock [ - ^ rows do: aBlock -] - -{ #category : #operation } -PMSymmetricMatrix >> crlInverse [ - "corrected sequence of calcs; s1in matrices at:2 has to be calced first (split returns matrices in this order: b, d, c). -and taken care of degenerate cases (which is unnecessary, if this method is not called outside of inverse)" - | matrices b1 cb1ct cb1 | - rows size = 1 - ifTrue: [ ^self inverse1By1]. - rows size = 2 - ifTrue: [ ^self inverse2By2]. - matrices := self split. - b1 := (matrices at: 1) inverse. - cb1 := (matrices at: 3) * b1. - cb1ct := (cb1 productWithTransposeMatrix: (matrices at: 3))asSymmetricMatrix . - matrices at: 2 put: ((matrices at: 2) - cb1ct ) inverse. - matrices at: 3 put: (matrices at: 2) * cb1. - matrices at: 1 put: ( b1 + (cb1 transposeProductWithMatrix: (matrices at: 3))asSymmetricMatrix). - (matrices at: 3) negate. - ^ self class join: matrices -] - -{ #category : #operation } -PMSymmetricMatrix >> eigen [ - "Computes all eigenvalues and eigenvectors for symmetric matrix using Jacobi transformation - Usage: - matrix eigen values. - matrix eigen vectors." - - ^ PMJacobiTransformationHelper matrix: self. -] - -{ #category : #initialization } -PMSymmetricMatrix >> initializeIdentity: anInteger [ - "Build components for an identity matrix." - rows := ( 1 to: anInteger) asPMVector collect: [ :n | (PMVector new: anInteger) atAllPut: 0; at: n put: 1; yourself]. -] - -{ #category : #operation } -PMSymmetricMatrix >> inverse [ - "Answer the inverse of the receiver" - - ^(rows size < self class lupCRLCriticalDimension or: [lupDecomposition notNil]) - ifTrue: [ self lupInverse ] - ifFalse: [ self crlInverse ] -] - -{ #category : #operation } -PMSymmetricMatrix >> inverse1By1 [ - "Private - Answer the inverse of the receiver when it is a 1x1 matrix (no check is made)." - ^ self class rows: ( PMVector with: ( PMVector with: ( 1/ ((rows at: 1) at: 1)))) -] - -{ #category : #operation } -PMSymmetricMatrix >> inverse2By2 [ - "Private - Answer the inverse of the receiver when it is a 2x2 matrix (no check is made)." - | line1 line2 | - line1 := PMVector with: ((rows at: 2) at: 2) with: ((rows at: 1) at: 2) negated. - line2 := PMVector with: ((rows at: 1) at: 2) negated with: ((rows at: 1) at: 1). - ^self class rows: ( PMVector with: line1 with: line2) * (1 / (((rows at: 1) at: 1) * ((rows at: 2) at: 2) - ((rows at: 1) at: 2) squared)) -] - -{ #category : #operation } -PMSymmetricMatrix >> inversePureCRL [ - "Answer the inverse of the receiver." - | matrices b1 cb1 cb1ct | - [rows size = 1 - ifTrue: [ ^self inverse1By1]]on: ZeroDivide do: [:e| PMSingularMatrixError new signal]. - rows size = 2 - ifTrue: [ ^ self inverse2By2]. - matrices := self split. - b1 := (matrices at: 1) inversePureCRL. - cb1 := (matrices at: 3) * b1. - cb1ct := (cb1 productWithTransposeMatrix: ( matrices at: 3)) asSymmetricMatrix. - matrices at: 2 put: ((matrices at: 2) - cb1ct) inversePureCRL. - matrices at: 3 put: (matrices at: 2) * cb1. - matrices at: 1 put: (b1 + ( cb1 transposeProductWithMatrix: ( matrices at: 3))asSymmetricMatrix). - (matrices at: 3) negate. - ^ self class join: matrices -] - -{ #category : #operation } -PMSymmetricMatrix >> inversePureLUP [ - "Answer the inverse of the receiver." - - lupDecomposition := nil. - self lupDecomposition inverseMatrixComponents - ifNil: [ PMSingularMatrixError new signal ] - ifNotNil: [ :i | ^ self class rows: i ] -] - -{ #category : #testing } -PMSymmetricMatrix >> isHermitian [ - "Every real symmetric matrix is Hermitian" - ^ self isReal -] - -{ #category : #testing } -PMSymmetricMatrix >> isSquare [ - "Answers true because a symmetric matrix is square." - ^true -] - -{ #category : #testing } -PMSymmetricMatrix >> isSymmetric [ - "Answers true because the receiver is a symmetric matrix" - ^true -] - -{ #category : #information } -PMSymmetricMatrix >> numberOfColumns [ - "Answer the number of columns of the receiver." - ^rows size -] - -{ #category : #'private ' } -PMSymmetricMatrix >> privateTranspose [ - ^ self -] - -{ #category : #transformation } -PMSymmetricMatrix >> split [ - "Private - - Answers an array of 3 matrices split from the receiver" - - | n | - n := self largestPowerOf2SmallerThan: rows size. - ^Array - with: (self class rows: ((1 to: n) asPMVector collect: [:k | (rows at: k) - copyFrom: 1 to: n])) - with: (self class rows: ((n + 1 to: rows size) asPMVector collect: [:k | (rows at: k) - copyFrom: n + 1 to: rows size])) - with: (self class superclass rows: ((n + 1 to: rows size) asPMVector collect: [:k | (rows at: k) - copyFrom: 1 to: n])) -] - -{ #category : #'double dispatching' } -PMSymmetricMatrix >> subtractWithSymmetricMatrix: aMatrix [ - ^ self class - new: aMatrix numberOfRows - function: [ :x :y|((aMatrix rows at:x)at:y)-(( rows at:x)at:y) ] -] - -{ #category : #information } -PMSymmetricMatrix >> transpose [ - "Answer a new matrix, transpose of the receiver. optimized" - ^self deepCopy -] diff --git a/src/Math-Matrix/PMVector.extension.st b/src/Math-Matrix/PMVector.extension.st deleted file mode 100644 index bd43674cf..000000000 --- a/src/Math-Matrix/PMVector.extension.st +++ /dev/null @@ -1,30 +0,0 @@ -Extension { #name : #PMVector } - -{ #category : #'*Math-Matrix' } -PMVector >> productWithMatrix: aMatrix [ - - "Answers the product of aMatrix with the receiver." - - ^ aMatrix rowsCollect: [ :each | each * self ] -] - -{ #category : #'*Math-Matrix' } -PMVector >> reshapeWithDimensions: dimensionArray [ - - | computedRows rowNum colNum | - self checkDimensionalCompatibility: dimensionArray. - rowNum := dimensionArray at: 1. - colNum := dimensionArray at: 2. - computedRows := (1 to: rowNum) collect: [ :i | (1 to: colNum) collect: [ :j | self at: i - 1 * colNum + j ] ]. - - ^ PMMatrix rows: computedRows -] - -{ #category : #'*Math-Matrix' } -PMVector >> tensorProduct: aVector [ - "Answers the tensor product of the receiver with aVector." - ^self == aVector "dont use #=" - ifTrue: [PMSymmetricMatrix new: self size function:[:x :y|(self at: x) * (self at: y)]] - ifFalse:[PMMatrix rows: ( self collect: [ :a | aVector collect: [ :b | a * b]])] - -] diff --git a/src/Math-Matrix/ShapeMismatch.class.st b/src/Math-Matrix/ShapeMismatch.class.st deleted file mode 100644 index a79537bc2..000000000 --- a/src/Math-Matrix/ShapeMismatch.class.st +++ /dev/null @@ -1,19 +0,0 @@ -Class { - #name : #ShapeMismatch, - #superclass : #Error, - #category : #'Math-Matrix' -} - -{ #category : #accessing } -ShapeMismatch >> messageText [ - "Overwritten to initialiaze the message text to a standard text if it has not yet been set" - - ^ messageText ifNil: [ messageText := self standardMessageText ] -] - -{ #category : #printing } -ShapeMismatch >> standardMessageText [ - "Generate a standard textual description" - - ^ 'NDArray shapes do not match' -] diff --git a/src/Math-Matrix/package.st b/src/Math-Matrix/package.st deleted file mode 100644 index 206c13a71..000000000 --- a/src/Math-Matrix/package.st +++ /dev/null @@ -1 +0,0 @@ -Package { #name : #'Math-Matrix' } diff --git a/src/Math-Tests-Core/PMVectorTest.class.st b/src/Math-Tests-Core/PMVectorTest.class.st deleted file mode 100644 index 23442b5d4..000000000 --- a/src/Math-Tests-Core/PMVectorTest.class.st +++ /dev/null @@ -1,362 +0,0 @@ -Class { - #name : #PMVectorTest, - #superclass : #TestCase, - #category : #'Math-Tests-Core' -} - -{ #category : #tests } -PMVectorTest >> testAddScalar [ - "Can we add Number to PMVector?" - - | vec num actual expected | - - vec := #(1 2 3) asPMVector. - num := 4. - - actual := vec + num. - expected := #(5 6 7) asPMVector. - - self assert: actual equals: expected. -] - -{ #category : #tests } -PMVectorTest >> testAddToScalar [ - "Can we add PMVector to Number?" - - | num vec actual expected | - - num := 4. - vec := #(1 2 3) asPMVector. - - actual := num + vec. - expected := #(5 6 7) asPMVector. - - self assert: actual equals: expected. -] - -{ #category : #tests } -PMVectorTest >> testArgMax [ - | v1 v2 | - v1 := #(1 5 3 2 0) asPMVector. - v2 := #(1 5 3 5 0) asPMVector. - self assert: v1 argMax equals: 2. - self assert: v2 argMax equals: 2 -] - -{ #category : #tests } -PMVectorTest >> testArgMaxWithVectorOverReals [ - "For vectors over a field of real numbers" - - | v1 v2 | - v1 := #(1.3 5.001 3.1 2.0 0.2) asPMVector. - v2 := #(1.2 15.0000000200 3.14 15.0000000201 0.1) asPMVector. - self assert: v1 argMax equals: 2. - self assert: v2 argMax equals: 4 -] - -{ #category : #tests } -PMVectorTest >> testAsArray [ - self assert: #(1 2 3 4) asPMVector asArray equals: #(1 2 3 4) -] - -{ #category : #tests } -PMVectorTest >> testGreaterThan [ - | vec vecCopy | - vec := #(1 2 3) asPMVector. - vecCopy := vec deepCopy. - self assert: (vec > 1.5) equals: #(false true true) asPMVector. - "Ensure that in-place modification does not take place" - self assert: vec equals: vecCopy asPMVector. -] - -{ #category : #tests } -PMVectorTest >> testHouseholder [ - | u w | - u := #(-1 0 1) asPMVector. "`x <= 0` when x = -1" - w := u householder. - self - assert: (w at: 1) equals: 1.7071067811865475; - assert: (w at: 2) asArray equals: #(1.0 -0.0 -0.4142135623730951). - u := #(1.00001 2.00007) asPMVector. "`x <= 0` when x = 1.00001" - w := u householder. - self - assert: (w at: 1) equals: 0.5527953485259909; - assert: (w at: 2) asArray equals: #(1.0 -1.6180158992689828). -] - -{ #category : #tests } -PMVectorTest >> testLessThan [ - | vec vecCopy | - vec := #(1 2 3) asPMVector. - vecCopy := vec deepCopy. - self assert: (vec < 1.5) equals: #(true false false) asPMVector. - "Ensure that in-place modification does not take place" - self assert: vec equals: vecCopy asPMVector. -] - -{ #category : #tests } -PMVectorTest >> testScalarProduct [ - | u v | - u := PMVector new: 3. - v := PMVector new: 3. - u - at: 1 put: 1; - at: 2 put: 1; - at: 3 put: 1. - v - at: 1 put: 0; - at: 2 put: 2; - at: 3 put: 0. - self assert: (u scalarProduct: v) equals: 2. - v at: 1 put: 2. - self assert: (u scalarProduct: v) equals: 4 -] - -{ #category : #tests } -PMVectorTest >> testScalarProductIsCommutative [ - | u v | - u := PMVector new: 3. - v := PMVector new: 3. - u - at: 1 put: 1; - at: 2 put: 1; - at: 3 put: 1. - v - at: 1 put: 0; - at: 2 put: 2; - at: 3 put: 0. - self assert: (u scalarProduct: v) equals: (v scalarProduct: u) -] - -{ #category : #tests } -PMVectorTest >> testSubFromScalar [ - "Can we subtract PMVector from a Number?" - - | num vec actual expected | - - num := 4. - vec := #(1 2 3) asPMVector. - - actual := num - vec. - expected := #(3 2 1) asPMVector. - - self assert: actual equals: expected. -] - -{ #category : #tests } -PMVectorTest >> testSubtractScalar [ - "Can we subtract Number from PMVector?" - - | vec num actual expected | - - vec := #(5 6 7) asPMVector. - num := 4. - - actual := vec - num. - expected := #(1 2 3) asPMVector. - - self assert: actual equals: expected. -] - -{ #category : #test } -PMVectorTest >> testTake [ - - | m expected | - m := PMVector withAll: #(1 2 3). - expected := PMVector withAll: #(0 1 3). - self assert: (m take: 2) equals: expected. - expected := PMVector withAll: #(0 0 1). - self assert: (m take: 3) equals: expected. - - m := PMVector withAll: #(). - expected := PMVector withAll: #(). - self assert: (m take: 2) equals: expected. -] - -{ #category : #tests } -PMVectorTest >> testTensorProduct [ - | a b c | - a := #(1 2 3) asPMVector. - b := #(2 2 3) asPMVector. - c := a tensorProduct: b. - self deny: c transpose = c. "hence c is not symmetric, but this does not work:" - self deny: c isSymmetric. - "furthermore this is completely permissible:" - b := #(1 2 3 4) asPMVector. - c := a tensorProduct: b. - self assert: (b tensorProduct: a) equals: c transpose -] - -{ #category : #tests } -PMVectorTest >> testVectorCloseTo [ - self assert: (#(1.00001 2.00005) asPMVector closeTo: #(1.00005 2.00001) asPMVector). - self assert: #(1.00001 2.00005) asPMVector closeTo: #(1.00005 2.00001) asPMVector. "Double check that the TestAsserter >> #assert:closeTo: functions properly here." - self deny: (#(1.00001 2.00007) asPMVector closeTo: #(1.00007 2.00001) asPMVector) -] - -{ #category : #tests } -PMVectorTest >> testVectorCloseToPrecision [ - | u v | - u := #(1.2 2.4) asPMVector. - v := #(1.4 2.2) asPMVector. - self assert: (u closeTo: v precision: 0.5). - self deny: (u closeTo: v precision: 0.3). - self deny: (u closeTo: v precision: 0.1). -] - -{ #category : #tests } -PMVectorTest >> testVectorCumulativeSum [ - "Code Example 8.1" - - | u w | - u := #(1 2 3) asPMVector. - w := u cumsum. - self assert: (w size) equals: 3. - self assert: (w at: 1) equals: 1. - self assert: (w at: 2) equals: 3. - self assert: (w at: 3) equals: 6 -] - -{ #category : #tests } -PMVectorTest >> testVectorGreater [ - -| u w | - u := #(-1 0 1) asPMVector. - w := u > 0. - self assert: (w size) equals: 3. - self assert: (w at: 1) equals: false. - self assert: (w at: 2) equals: false. - self assert: (w at: 3) equals: true - -] - -{ #category : #tests } -PMVectorTest >> testVectorHadamardProduct [ - "Code Example 8.1" - - | u v w | - u := #(1 2 3) asPMVector. - v := #(3 4 5) asPMVector. - w := u hadamardProduct: v. - self assert: (w size) equals: 3. - self assert: (w at: 1) equals: 3. - self assert: (w at: 2) equals: 8. - self assert: (w at: 3) equals: 15 -] - -{ #category : #tests } -PMVectorTest >> testVectorLess [ - -| u w | - u := #(-1 0 1) asPMVector. - w := u < 0. - self assert: (w size) equals: 3. - self assert: (w at: 1) equals: true. - self assert: (w at: 2) equals: false. - self assert: (w at: 3) equals: false - -] - -{ #category : #tests } -PMVectorTest >> testVectorNegate [ - "negate modifies the vector. negated makes a new vector with inverse coefficients. " - - | v | - v := #(1 2 3) asPMVector. - self assert: (v negate at: 1) equals: -1. - self assert: 2 equals: (v negate at: 2). - self assert: -2 equals: (v negated at: 2) -] - -{ #category : #tests } -PMVectorTest >> testVectorNorm [ - - | v1 v2 | - v1 := #( 1 0 ) asPMVector. - self assert: v1 norm equals: 1. - v2 := #( 0 1 ) asPMVector. - self assert: v2 norm equals: 1. - self shouldnt: [ (v1 + v2) norm = 1 ]. - "normalized norm may differ from exactly one due to floating point operations" - self assert: ((v1 + v2) normalized norm closeTo: 1) -] - -{ #category : #tests } -PMVectorTest >> testVectorOnes [ - | v | - v := PMVector ones: 3. - self assert: (v size) equals: 3. - self assert: (v at: 1) equals: 1. - self assert: (v at: 2) equals: 1. - self assert: (v at: 3) equals: 1 - -] - -{ #category : #tests } -PMVectorTest >> testVectorOperation [ - "Code Example 8.1" - - | u v w | - u := #(1 2 3) asPMVector. - v := #(3 4 5) asPMVector. - w := 4 * u + (3 * v). - self assert: w size equals: 3. - self assert: (w at: 1) equals: 13. - self assert: (w at: 2) equals: 20. - self assert: (w at: 3) equals: 27 -] - -{ #category : #tests } -PMVectorTest >> testVectorOperationInverse [ - | u v w | - u := #(1 2 3) asPMVector. - v := #(3 4 5) asPMVector. - w := v * 4 - (3 * u). - self assert: w size equals: 3. - self assert: (w at: 1) equals: 9. - self assert: (w at: 2) equals: 10. - self assert: (w at: 3) equals: 11 -] - -{ #category : #tests } -PMVectorTest >> testVectorProduct [ - "Code Example 8.1" - - | u v | - u := #(1 2 3) asPMVector. - v := #(3 4 5) asPMVector. - self assert: u * v equals: 26 -] - -{ #category : #tests } -PMVectorTest >> testVectorSqrt [ - "Code Example 8.1" - - | u w | - u := #(1 4 9) asPMVector. - w := u sqrt. - self assert: (w size) equals: 3. - self assert: (w at: 1) equals: 1. - self assert: (w at: 2) equals: 2. - self assert: (w at: 3) equals: 3 -] - -{ #category : #tests } -PMVectorTest >> testVectorSum [ - "Code Example 8.1" - - | u | - u := #(1 2 3) asPMVector. - self assert: (u sum) equals: 6. -] - -{ #category : #tests } -PMVectorTest >> testVectorZeros [ - | v | - v := PMVector zeros: 3. - self assert: (v size) equals: 3. - self assert: (v at: 1) equals: 0. - self assert: (v at: 2) equals: 0. - self assert: (v at: 3) equals: 0 - -] diff --git a/src/Math-Tests-Core/package.st b/src/Math-Tests-Core/package.st deleted file mode 100644 index 8f219b1d8..000000000 --- a/src/Math-Tests-Core/package.st +++ /dev/null @@ -1 +0,0 @@ -Package { #name : #'Math-Tests-Core' } diff --git a/src/Math-Tests-Matrix/PMAdditionalTest.class.st b/src/Math-Tests-Matrix/PMAdditionalTest.class.st deleted file mode 100644 index 2b64adb4c..000000000 --- a/src/Math-Tests-Matrix/PMAdditionalTest.class.st +++ /dev/null @@ -1,61 +0,0 @@ -" -here are tests that would be in Math-Tests-DHB-Numerical, if it could construct random matrices - -" -Class { - #name : #PMAdditionalTest, - #superclass : #TestCase, - #category : #'Math-Tests-Matrix' -} - -{ #category : #tests } -PMAdditionalTest >> testMatrixInversionSmall [ - "it is here since it uses random matrices" - - | m c i | - c := PMSymmetricMatrix identity: 5. - 3 - timesRepeat: [ [ m := PMSymmetricMatrix new: 5 random: 20. - m determinant = 0 ] whileTrue. "singular matrix not allowed" - self assert: (i := m crlInverse) * m closeTo: c. - self assert: i class equals: PMSymmetricMatrix. - self assert: (i := m inversePureLUP) * m closeTo: c. - self assert: i class equals: PMSymmetricMatrix. - self assert: m * (i := m inversePureCRL) closeTo: c. - self assert: i class equals: PMSymmetricMatrix ]. - 3 - timesRepeat: [ [ m := PMMatrix rows: 5 columns: 5 random: 20. - m determinant = 0 ] whileTrue. - self assert: m * (i := m inverse) closeTo: c. - self assert: i class equals: PMMatrix. - self assert: (i := m inversePureCRL) * m closeTo: c. - self assert: i class equals: PMMatrix ] -] - -{ #category : #tests } -PMAdditionalTest >> testMatrixSquared [ - "this tests squared and is not in Math-Tests-Numerical since it uses random matrices" - - | a | - 10 - timesRepeat: [ a := PMMatrix rows: 20 columns: 21 random: 10.0. - self assert: a squared equals: a transpose * a ]. - self assert: a squared class equals: PMSymmetricMatrix -] - -{ #category : #tests } -PMAdditionalTest >> testTensorProduct [ - "this tests if a tensor product of two vectors is calculated correctly" - - | a b expected | - a := #(3 4) asPMVector. - b := #(1 2) asPMVector. - - "tensor product of two different vectors (a PMMatrix)" - expected := PMMatrix rows: #((3 6)(4 8)). - self assert: (a tensorProduct: b) equals: expected. - - "tensor product of two equal vectors (a PMSymmetricMatrix)" - expected := PMMatrix rows: #((9 12)(12 16)). - self assert: (a tensorProduct: a) equals: expected. -] diff --git a/src/Math-Tests-Matrix/PMJacobiTransformationTest.class.st b/src/Math-Tests-Matrix/PMJacobiTransformationTest.class.st deleted file mode 100644 index e7398f98d..000000000 --- a/src/Math-Tests-Matrix/PMJacobiTransformationTest.class.st +++ /dev/null @@ -1,32 +0,0 @@ -Class { - #name : #PMJacobiTransformationTest, - #superclass : #TestCase, - #category : #'Math-Tests-Matrix' -} - -{ #category : #tests } -PMJacobiTransformationTest >> testEigenvalueOfIdentityMatrixIsOne [ - "The eigenvalue of I is 1" - - | jacobiTransformation identityMatrix expected | - identityMatrix := PMMatrix rows: #(#(1 0) #(0 1)). - - jacobiTransformation := PMJacobiTransformation matrix: identityMatrix. - - expected := #(1 1). - self assert: jacobiTransformation evaluate equals: expected -] - -{ #category : #tests } -PMJacobiTransformationTest >> testEigenvectorsOfIdentityMatrixAreTheUnitVectors [ - "The eigenvectors of I are (1 0) and (0 1), the unit basis vectors" - - | identityMatrix jacobiTransform matrixOfEigenvectors expected | - identityMatrix := PMMatrix rows: #(#(1 0) #(0 1)). - jacobiTransform := PMJacobiTransformation matrix: identityMatrix. - - matrixOfEigenvectors := jacobiTransform transform. - - expected := PMSymmetricMatrix identity: 2. - self assert: matrixOfEigenvectors equals: expected. -] diff --git a/src/Math-Tests-Matrix/PMMatrixTest.class.st b/src/Math-Tests-Matrix/PMMatrixTest.class.st deleted file mode 100644 index 7b61eef75..000000000 --- a/src/Math-Tests-Matrix/PMMatrixTest.class.st +++ /dev/null @@ -1,996 +0,0 @@ -Class { - #name : #PMMatrixTest, - #superclass : #TestCase, - #category : #'Math-Tests-Matrix' -} - -{ #category : #tests } -PMMatrixTest >> testArgMaxOnColumns [ - | m1 m2 | - m1 := PMMatrix rows: #(#(0 1 2) #(3 4 5)). - m2 := PMMatrix rows: #(#(-1 0 -1) #(-2 0 0)). - self assert: m1 argMaxOnColumns equals: #(2 2 2) asPMVector. - self assert: m2 argMaxOnColumns equals: #(1 1 2) asPMVector -] - -{ #category : #tests } -PMMatrixTest >> testArgMaxOnRows [ - | m1 m2 | - m1 := PMMatrix rows: #(#(0 1 2) #(3 4 5)). - m2 := PMMatrix rows: #(#(-1 0 -1) #(-2 0 0)). - self assert: m1 argMaxOnRows equals: #(3 3) asPMVector. - self assert: m2 argMaxOnRows equals: #(2 2) asPMVector. -] - -{ #category : #tests } -PMMatrixTest >> testAtAllPut [ - - | a | - a := PMMatrix new: 3. - a atAllPut: 4. - self assert: a equals: (PMMatrix rows: #(#(4 4 4) #(4 4 4) #(4 4 4))). - -] - -{ #category : #tests } -PMMatrixTest >> testAtColumnPutRepeat [ - - | a | - a := PMMatrix new: 3. - a - atColumn: 1 put: 1 repeat: 3; - atColumn: 2 put: 2 repeat: 3; - atColumn: 3 put: 3 repeat: 3. - self assert: a equals: (PMMatrix rows: #(#(1 2 3) #(1 2 3) #(1 2 3))). - a := PMMatrix new: 3. - a - atColumn: 1 put: 1 repeat: 2. - self assert: a equals: (PMMatrix rows: #(#(1 nil nil) #(1 nil nil) #(nil nil nil))). -] - -{ #category : #tests } -PMMatrixTest >> testAtRow [ - - | a | - a := PMMatrix rows: #(#(1 2 3) #(2 3 4)). - - self assert: (a atRow: 2) equals: (#(2 3 4) asPMVector). - self assert: (a atRow: 1) equals: (#(1 2 3) asPMVector). -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testAtRowPutAtColumnPut [ - | a | - a := PMMatrix rows: #(#(11 12 13) #(21 22 23)). - a atRow: 1 put: (a rowAt: 2). - self assert: a equals: (PMMatrix rows: #(#(21 22 23) #(21 22 23))). - a atColumn: 3 put: (a columnAt: 2). - self assert: a equals: (PMMatrix rows: #(#(21 22 22) #(21 22 22))). - a := PMSymmetricMatrix rows: #(#(11 12) #(21 22)). - self should: [ a atRow: 1 put: (a rowAt: 2) ] raise: Error. - self should: [ a atColumn: 1 put: (a rowAt: 2) ] raise: Error -] - -{ #category : #tests } -PMMatrixTest >> testCholeskyDecomposition [ - | matrix upperTriangular expected | - - matrix := PMMatrix rows: #( - (4 20 8 2 18) - (20 116 80 18 126) - (8 80 117 32 135) - (2 18 32 73 109) - (18 126 135 109 272)). - - upperTriangular := matrix choleskyDecomposition. - - expected := PMMatrix rows: #( - (2 10 4 1 9) - (0 4 10 2 9) - (0 0 1 8 9) - (0 0 0 2 5) - (0 0 0 0 2)). - - self assert: upperTriangular equals: expected. -] - -{ #category : #tests } -PMMatrixTest >> testCholeskyDecompositionIsDecomposition [ - | matrix upperTriangular | - - matrix := PMMatrix rows: #( - (4 12 -16) - (12 37 -43) - (-16 -43 98)). - - upperTriangular := matrix choleskyDecomposition. - - self - assert: upperTriangular transpose * upperTriangular - closeTo: matrix. -] - -{ #category : #tests } -PMMatrixTest >> testCholeskyDecompositionNonSquare [ - | matrix | - - matrix := PMMatrix rows: #( - (4 12 -16) - (12 37 -43)). - - self should: [ matrix choleskyDecomposition ] raise: Error. -] - -{ #category : #tests } -PMMatrixTest >> testCholeskyDecompositionNonSymmetric [ - | matrix | - - matrix := PMMatrix rows: #( - (4 12 -16) - (10 37 -43) - (2 5 98)). - - self should: [ matrix choleskyDecomposition ] raise: Error. -] - -{ #category : #collection } -PMMatrixTest >> testCollect [ - self assert: ((PMMatrix rows: #((1 2) (3 4))) collect: [ :x | 2 * x ]) equals: (PMMatrix rows: #((2 4) ( 6 8))) -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testDeterminant [ - | m | - m := PMMatrix rows: #(#(3 2 4) #(2 -5 -1) #(1 -2 2)). - self assert: m determinant equals: -42 -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testDimension [ - | a | - a := PMMatrix rows: #( ( 1 0 1) (-1 -2 3)). - self assert: a dimension equals: 2@3. - -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testEigenvalues [ - "Code Example 8.15" - - | matrix expectedEigenvalues eigenvalues finder | - - matrix := PMMatrix rows: #( - (3 -2 0) - (-2 7 1) - (0 1 5)). - - expectedEigenvalues := #(8.105482616526306 4.776537928330764 2.1179794551429305). - - finder := PMJacobiTransformation matrix: matrix. - finder desiredPrecision: 1.0e-09. - - eigenvalues := finder evaluate. - - eigenvalues with: expectedEigenvalues do: [ :actual :expected | - self assert: actual closeTo: expected ]. -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testEigenvaluesLargest [ - "Code Example 8.13" - - | matrix expectedEigenvalues firstEigenvalue secondEigenvalue finder | - - matrix := PMMatrix rows: #( - (3 -2 0) - (-2 7 1) - (0 1 5)). - - expectedEigenvalues := #(8.105482616526306 4.776537928330764 2.1179794551429305). - - finder := PMLargestEigenValueFinder matrix: matrix. - finder desiredPrecision: 1.0e-08. - - firstEigenvalue := finder evaluate. - - finder := finder nextLargestEigenValueFinder. - secondEigenvalue := finder evaluate. - - self assert: firstEigenvalue closeTo: expectedEigenvalues first. - self assert: secondEigenvalue closeTo: expectedEigenvalues second. -] - -{ #category : #tests } -PMMatrixTest >> testFlattenColumns [ - | m | - m := PMMatrix rows: #(#(1 2 3) #(4 5 6) #(7 8 9)). - self assert: m flattenColumns equals: #(1 4 7 2 5 8 3 6 9) asPMVector -] - -{ #category : #tests } -PMMatrixTest >> testFlattenRows [ - | m | - m := PMMatrix rows: #(#(1 2 3) #(4 5 6) #(7 8 9)). - self assert: m flattenRows equals: #(1 2 3 4 5 6 7 8 9) asPMVector -] - -{ #category : #tests } -PMMatrixTest >> testIdentityMatrix [ - |expectedIdentityMatrix identityMatrix| - - expectedIdentityMatrix := PMMatrix zerosRows: 3 cols: 3. - - expectedIdentityMatrix at: 1 at: 1 put: 1. - expectedIdentityMatrix at: 2 at: 2 put: 1. - expectedIdentityMatrix at: 3 at: 3 put: 1. - - identityMatrix := PMMatrix identity: 3. - self assert: identityMatrix equals: expectedIdentityMatrix. -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testInversePureCRLSingularMatrixError [ - - self - should: [ (PMSymmetricMatrix rows: #((1 2 3)(2 2 2)(3 2 1))) inversePureCRL ] - raise: PMSingularMatrixError. -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testInversePureLUPSingularMatrixError [ - - self - should: [ (PMSymmetricMatrix rows: #((1 2 3)(2 2 2)(3 2 1))) inversePureLUP ] - raise: PMSingularMatrixError. -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testInverseSingularMatrixError [ - - self - should: [ (PMMatrix rows: #((1 2 3)(3 4 6))) inverse ] - raise: PMSingularMatrixError. -] - -{ #category : #tests } -PMMatrixTest >> testLUPDecomposition [ - "Code Example 8.10" - - | s sol1 sol2 | - s := PMLUPDecomposition equations: #(#(3 2 4) #(2 -5 -1) #(1 -2 2)). - sol1 := s solve: #(16 6 10). - sol2 := s solve: #(7 10 9). - self assert: sol1 size equals: 3. - self assert: (sol1 at: 1) equals: 2. - self assert: (sol1 at: 2) equals: -1. - self assert: (sol1 at: 3) equals: 3. - self assert: sol2 size equals: 3. - self assert: (sol2 at: 1) equals: 1. - self assert: (sol2 at: 2) equals: -2. - self assert: (sol2 at: 3) equals: 2 -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testLinearEquations [ - "Code Example 8.6" - - | s sol1 sol2 | - s := PMLinearEquationSystem - equations: #(#(3 2 4) #(2 -5 -1) #(1 -2 2)) - constants: #(#(16 6 10) #(7 10 9)). - sol1 := s solutionAt: 1. - sol2 := s solutionAt: 2. - self assert: sol1 size equals: 3. - self assert: (sol1 at: 1) equals: 2. - self assert: (sol1 at: 2) equals: -1. - self assert: (sol1 at: 3) equals: 3. - self assert: sol2 size equals: 3. - self assert: (sol2 at: 1) equals: 1. - self assert: (sol2 at: 2) equals: -2. - self assert: (sol2 at: 3) equals: 2 -] - -{ #category : #tests } -PMMatrixTest >> testLinearEquationsSingle [ - - | s sol | - s := PMLinearEquationSystem - equations: #( #( 1 2 0 ) #( 3 5 4 ) #( 5 6 3 ) ) - constant: #( 0.1 12.5 10.3 ). - sol := s solution. - self assert: sol size equals: 3. - self assert: ((sol at: 1) closeTo: 0.5). - self assert: ((sol at: 2) closeTo: -0.2). - self assert: ((sol at: 3) closeTo: 3.0) -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testLinearEquationsSingular [ - | s sol | - s := PMLinearEquationSystem - equations: #(#(1 2 0) #(10 12 6) #(5 6 3)) - constant: #(0.1 12.5 10.3). - sol := s solution. - self assert: sol isNil -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMatrixAdd [ - | a b c | - a := PMMatrix rows: #(#(1 0 1) #(-1 -2 3)). - b := PMMatrix rows: #(#(1 2 3) #(-2 1 7)). - c := a + b. - self assert: c numberOfRows equals: 2. - self assert: c numberOfColumns equals: 3. - self assert: ((c rowAt: 1) at: 1) equals: 2. - self assert: ((c rowAt: 1) at: 2) equals: 2. - self assert: ((c rowAt: 1) at: 3) equals: 4. - self assert: ((c rowAt: 2) at: 1) equals: -3. - self assert: ((c rowAt: 2) at: 2) equals: -1. - self assert: ((c rowAt: 2) at: 3) equals: 10 -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMatrixAddSizeMismatch [ - | a b | - "Matrices of different dimensions should signal SizeMismatch on #+." - a := PMMatrix rows: #(#(1 2) #(3 4)). - b := PMMatrix rows: #(#(1 2)). - self should: [ a + b ] raise: SizeMismatch. - self should: [ b + a ] raise: SizeMismatch. - self should: [ a + b transpose ] raise: SizeMismatch. - self should: [ b transpose + a ] raise: SizeMismatch -] - -{ #category : #comparing } -PMMatrixTest >> testMatrixCloseTo [ - self assert: ((PMMatrix rows: #(#(1.00001 2.00002) #(3.00001 4.00002))) closeTo: (PMMatrix rows: #(#(1.00002 2.00001) #(3.00002 4.00001)))). - self assert: (PMMatrix rows: #(#(1.00001 2.00002) #(3.00001 4.00002))) closeTo: (PMMatrix rows: #(#(1.00002 2.00001) #(3.00002 4.00001))). "Double check that the TestAsserter >> #assert:closeTo: functions properly here." - self deny: ((PMMatrix rows: #(#(1.00001 2.00004) #(3.00001 4.00004))) closeTo: (PMMatrix rows: #(#(1.00004 2.00001) #(3.00004 4.00001)))). -] - -{ #category : #comparing } -PMMatrixTest >> testMatrixCloseToPrecision [ - | a b | - a := PMMatrix rows: #(#(1.2 2.4) #(1.2 2.4)). - b := PMMatrix rows: #(#(1.4 2.2) #(1.4 2.2)). - self assert: (a closeTo: b precision: 1.0). - self deny: (a closeTo: b precision: 0.6). - self deny: (a closeTo: b precision: 0.2) -] - -{ #category : #tests } -PMMatrixTest >> testMatrixConversionWithBothDims [ - - | vect result expected | - vect := #( 1 0.5 0.2 3 1 -1 7 3 2 12 13 3 ) asPMVector. - result := vect reshapeWithDimensions: #( 6 2 ). - - expected := PMMatrix rows: #( #( 1 0.5 ) #( 0.2 3 ) #( 1 -1 ) #( 7 3 ) #( 2 12 ) #( 13 3 ) ). - - self assert: result equals: expected -] - -{ #category : #comparing } -PMMatrixTest >> testMatrixCos [ - | a | - a := PMMatrix rows: (Array with: (Array with: Float pi with: Float pi) with: #(0 0)). - self assert: a cos equals: (PMMatrix rows:#((-1 -1) (1 1))) -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMatrixCumulativeSum [ - | a b | - a := PMMatrix rows: #(#(1 0 1) #(-1 -2 3)). - b := a cumsum. - self assert: b numberOfRows equals: 2. - self assert: b numberOfColumns equals: 3. - self assert: ((b rowAt: 1) at: 1) equals: 1. - self assert: ((b rowAt: 1) at: 2) equals: 1. - self assert: ((b rowAt: 1) at: 3) equals: 2. - self assert: ((b rowAt: 2) at: 1) equals: -1. - self assert: ((b rowAt: 2) at: 2) equals: -3. - self assert: ((b rowAt: 2) at: 3) equals: 0 -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMatrixDo [ - | a | - a := PMMatrix rows: #(#(1 2 3) #(1 2 3) #(1 2 3)). - a rowsDo: [ :row | row at: 1 put: 0 ]. - self assert: (a rowAt: 1 columnAt: 1) equals: 0. - a columnsDo: [ :col | a atRow: 1 put: col ]. - self assert: (a rowAt: 1) equals: #(2 3 3) asPMVector -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMatrixElementwiseAdd [ - | a b | - a := PMMatrix rows: #(#(1 2) #(3 4)). - b := PMMatrix rows: #(#(2 3) #(4 5)). - self assert: a + 0 equals: a. - self assert: 0 + a equals: a. - self assert: a + 1 equals: b. - self assert: 1 + a equals: b. - self assert: -1 + b equals: a. - self assert: b + -1 equals: a. -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMatrixEquality [ - | a c | - a := PMMatrix rows: #(#(1 0 1) #(-1 -2 3)). - c := a. - self assert: c numberOfRows equals: a numberOfRows. - self assert: c numberOfColumns equals: a numberOfColumns. - self assert: (c = a and: [ a = c ]) -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMatrixExtensions [ - "testing at:at: and at:at:put:" - - | a c | - a := PMMatrix rows: #(#(1 0 1) #(-1 -2 3)). - c := a deepCopy. - self assert: (c at: 1 at: 1) equals: (a at: 1 at: 1). - a at: 1 at: 1 put: 42. - self shouldnt: [ (c at: 1 at: 1) = (a at: 1 at: 1) ] -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMatrixExtensionsAtColumn [ - "testing at:at: and at:at:put:" - - | a c | - a := PMMatrix rows: #(#(11 12 13) #(21 22 23)). - c := a deepCopy. - self assert: (c at: 1 at: 1) equals: (a at: 1 at: 1). - c atColumn: 1 put: (a atColumn: 2). - self shouldnt: [ (c at: 1 at: 1) = (a at: 1 at: 1) ]. - self assert: (c at: 1 at: 1) equals: (a at: 1 at: 2). - c := a deepCopy. - c at: 1 at: 1 put: (a at: 1 at: 2). - c atColumn: 1 put: (a atColumn: 2) startingAt: 1. - self assert: (c at: 2 at: 1) equals: (a at: 1 at: 2). - self shouldnt: [ (c at: 1 at: 1) = (a at: 1 at: 1) ] -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMatrixExtensionsAtRow [ - "testing at:at: and at:at:put:" - - | a c | - a := PMMatrix rows: #(#(11 12 13) #(21 22 23)). - c := a deepCopy. - self assert: (c at: 1 at: 1) equals: (a at: 1 at: 1). - c atRow: 1 put: (a rowAt: 2). - self shouldnt: [ (c at: 1 at: 1) = (a at: 1 at: 1) ]. - self assert: (c at: 1 at: 1) equals: (a at: 2 at: 1). - c := a deepCopy. - c atRow: 1 put: (a rowAt: 2) startingAt: 1. - self assert: (c at: 1 at: 2) equals: (a at: 2 at: 1). - self shouldnt: [ (c at: 1 at: 2) = (a at: 1 at: 2) ] -] - -{ #category : #comparing } -PMMatrixTest >> testMatrixGreater [ - | a b | - a := PMMatrix rows: #(#(1 -1 2) #(-4 0 1)). - b := a > 0. - self assert: b numberOfRows equals: 2. - self assert: b numberOfColumns equals: 3. - self assert: ((b rowAt: 1) at: 1) equals: true. - self assert: ((b rowAt: 1) at: 2) equals: false. - self assert: ((b rowAt: 1) at: 3) equals: true. - self assert: ((b rowAt: 2) at: 1) equals: false. - self assert: ((b rowAt: 2) at: 2) equals: false. - self assert: ((b rowAt: 2) at: 3) equals: true -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMatrixHadamardProduct [ - | a b c | - a := PMMatrix rows: #(#(1 0 1) #(-1 -2 3)). - b := PMMatrix rows: #(#(1 2 3) #(-2 1 7)). - c := a hadamardProduct: b. - self assert: c numberOfRows equals: 2. - self assert: c numberOfColumns equals: 3. - self assert: ((c rowAt: 1) at: 1) equals: 1. - self assert: ((c rowAt: 1) at: 2) equals: 0. - self assert: ((c rowAt: 1) at: 3) equals: 3. - self assert: ((c rowAt: 2) at: 1) equals: 2. - self assert: ((c rowAt: 2) at: 2) equals: -2. - self assert: ((c rowAt: 2) at: 3) equals: 21 -] - -{ #category : #comparing } -PMMatrixTest >> testMatrixHash [ - | a b c | - a := PMMatrix rows: #(#(1 0) #(0 1)). - b := a deepCopy. - self assert: a hash equals: b hash. - c := a + b. - self shouldnt: [ a hash = c hash ] -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMatrixInitializationWithNegativeDimensions [ - - " matrices with negative dimension and zero dimension should not be allowed." - self should: [ PMMatrix new: -2 ] raise: AssertionFailure . - self should: [ PMMatrix rows: 0 columns: 4 ] raise: AssertionFailure. -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMatrixInitializeSquare [ - | aPMMatrix | - aPMMatrix := PMMatrix new initializeSquare: 2. - self assert: aPMMatrix numberOfRows equals: 2. - self assert: aPMMatrix numberOfColumns equals: 2. - -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMatrixInversionSmall [ - | m c | - m := PMMatrix rows: #(#(3 2 4) #(2 -5 -1) #(1 -2 2)). - c := m inverse * m. - self assert: c numberOfRows equals: 3. - self assert: c numberOfColumns equals: 3. - self assert: ((c rowAt: 1) at: 1) equals: 1. - self assert: ((c rowAt: 1) at: 2) equals: 0. - self assert: ((c rowAt: 1) at: 3) equals: 0. - self assert: ((c rowAt: 2) at: 1) equals: 0. - self assert: ((c rowAt: 2) at: 2) equals: 1. - self assert: ((c rowAt: 2) at: 3) equals: 0. - self assert: ((c rowAt: 3) at: 1) equals: 0. - self assert: ((c rowAt: 3) at: 2) equals: 0. - self assert: ((c rowAt: 3) at: 3) equals: 1 -] - -{ #category : #comparing } -PMMatrixTest >> testMatrixLess [ - | a b | - a := PMMatrix rows: #(#(1 -1 2) #(-4 0 1)). - b := a < 0. - self assert: b numberOfRows equals: 2. - self assert: b numberOfColumns equals: 3. - self assert: ((b rowAt: 1) at: 1) equals: false. - self assert: ((b rowAt: 1) at: 2) equals: true. - self assert: ((b rowAt: 1) at: 3) equals: false. - self assert: ((b rowAt: 2) at: 1) equals: true. - self assert: ((b rowAt: 2) at: 2) equals: false. - self assert: ((b rowAt: 2) at: 3) equals: false -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMatrixMultiply [ - "Code Example 8.1" - - | a b c | - a := PMMatrix rows: #(#(1 0 1) #(-1 -2 3)). - b := PMMatrix rows: #(#(1 2 3) #(-2 1 7) #(5 6 7)). - c := a * b. - self assert: c numberOfRows equals: 2. - self assert: c numberOfColumns equals: 3. - self assert: ((c rowAt: 1) at: 1) equals: 6. - self assert: ((c rowAt: 1) at: 2) equals: 8. - self assert: ((c rowAt: 1) at: 3) equals: 10. - self assert: ((c rowAt: 2) at: 1) equals: 18. - self assert: ((c rowAt: 2) at: 2) equals: 14. - self assert: ((c rowAt: 2) at: 3) equals: 4 -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMatrixNew [ - | aPMMatrix | - aPMMatrix := PMMatrix new: 3. - self assert: aPMMatrix numberOfRows equals: 3. - self assert: aPMMatrix numberOfColumns equals: 3. - -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMatrixPrincipalDiagonal [ - | a | - a := PMMatrix rows: #(#(1 2 3) #(4 5 6) #(7 8 9)). - self assert: a principalDiagonal equals: #(1 5 9) asPMVector. -] - -{ #category : #comparing } -PMMatrixTest >> testMatrixSign [ - | a | - a := PMMatrix rows: #(#(-2 2 0) #(2 0 -2)). - self assert: a sign equals: (PMMatrix rows: #((-1 1 0) (1 0 -1))) -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMatrixSubtract [ - | a b c | - a := PMMatrix rows: #(#(1 0 1) #(-1 -2 3)). - b := PMMatrix rows: #(#(1 2 3) #(-2 1 7)). - c := a - b. - self assert: c numberOfRows equals: 2. - self assert: c numberOfColumns equals: 3. - self assert: ((c rowAt: 1) at: 1) equals: 0. - self assert: ((c rowAt: 1) at: 2) equals: -2. - self assert: ((c rowAt: 1) at: 3) equals: -2. - self assert: ((c rowAt: 2) at: 1) equals: 1. - self assert: ((c rowAt: 2) at: 2) equals: -3. - self assert: ((c rowAt: 2) at: 3) equals: -4 -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMatrixSum [ - "Code Example 8.1" - - | a v | - a := PMMatrix rows: #(#(1 0 1) #(-1 -2 3)). - v := a sum. - self assert: v size equals: 2. - self assert: (v at: 1) equals: 2. - self assert: (v at: 2) equals: 0 -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMatrixTrace [ - | a | - a := PMMatrix rows: #(#(1 2 3) #(4 5 6) #(7 8 9)). - self assert: a tr equals: 15 -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMinorsOfNonSquareMatrix [ - - | matrix expected | - matrix := PMMatrix rows: { - { 1. 2 }. - { 6. 7 }. - { 5. 4 } }. - - expected := PMMatrix rows: { - { 7 }. - { 4 } }. - self assert: (matrix minor: 0 and: 0) equals: matrix. - self assert: (matrix minor: 1 and: 1) equals: expected -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testMinorsOfSquareMatrix [ - - | matrix expected | - matrix := PMMatrix rows: { - { 1. 2. 3 }. - { 6. 7. 8 }. - { 5. 4. 1 } }. - - expected := PMMatrix rows: { - { 7. 8 }. - { 4. 1 } }. - self assert: (matrix minor: 0 and: 0) equals: matrix. - self assert: (matrix minor: 1 and: 1) equals: expected. - self - assert: (matrix minor: 2 and: 2) - equals: (PMMatrix rows: { { 1 } }) -] - -{ #category : #tests } -PMMatrixTest >> testOnesMatrix [ - | a | - a := PMMatrix onesRows: 2 cols: 3. - self assert: a numberOfRows equals: 2. - self assert: a numberOfColumns equals: 3. - self assert: ((a rowAt: 1) at: 1) equals: 1. - self assert: ((a rowAt: 1) at: 2) equals: 1. - self assert: ((a rowAt: 1) at: 3) equals: 1. - self assert: ((a rowAt: 2) at: 1) equals: 1. - self assert: ((a rowAt: 2) at: 2) equals: 1. - self assert: ((a rowAt: 2) at: 3) equals: 1 -] - -{ #category : #tests } -PMMatrixTest >> testPrintOn [ - | m stream | - stream := String new writeStream. - m := PMMatrix new. - m printOn: stream -] - -{ #category : #tests } -PMMatrixTest >> testRaisedToNegativeInteger [ - - |aPMMatrix expected| - - aPMMatrix := PMMatrix rows: #(#(3 1) #(1 1)). - - aPMMatrix := aPMMatrix raisedTo: -2. - - expected := PMMatrix rows: #(#(0.5 -1) #(-1 2.5)). - self assert: aPMMatrix equals: expected. -] - -{ #category : #tests } -PMMatrixTest >> testRaisedToNonSquareMatrix [ - - |aPMMatrix| - - aPMMatrix := PMMatrix rows: #(#(3 1 4) #(1 1 2)). - - self should: [ aPMMatrix raisedTo: 3 ] raise: AssertionFailure. - -] - -{ #category : #tests } -PMMatrixTest >> testRaisedToPositiveInteger [ - - |aPMMatrix expected| - - aPMMatrix := PMMatrix rows: #(#(3 1) #(1 1)). - - aPMMatrix := aPMMatrix raisedTo: 3. - - expected := PMMatrix rows: #(#(34 14) #(14 6)). - self assert: aPMMatrix equals: expected. -] - -{ #category : #tests } -PMMatrixTest >> testRaisedToZero [ - - |aPMMatrix expected| - - aPMMatrix := PMMatrix rows: #(#(3 1) #(1 1)). - - aPMMatrix := aPMMatrix raisedTo: 0. - - expected := PMMatrix rows: #( #(1 0) #(0 1)). - self assert: aPMMatrix equals: expected. -] - -{ #category : #comparing } -PMMatrixTest >> testRowsColumns [ - | a | - - a := PMMatrix rows: 3 columns: 4. - self assert: a dimension equals: 3 @ 4. -] - -{ #category : #tests } -PMMatrixTest >> testRowsColumnsElement [ - - | a | - - a := PMMatrix rows: 3 columns: 4 element: 1. - self assert: a dimension equals: 3 @ 4. - self assert: a equals: (PMMatrix rows: #(#(1 1 1 1) #(1 1 1 1) #(1 1 1 1))) - -] - -{ #category : #tests } -PMMatrixTest >> testSimpleMatrixOperations [ - | s m s2 r r2 | - "a mix of unsymmetric and symmetric matrices" - m := PMMatrix rows: #(#(1 2 3) #(-1 -2 7) #(5 6 7)). - s := PMSymmetricMatrix rows: #(#(1 2 3) #(2 1 4) #(3 4 0)). - s2 := PMSymmetricMatrix rows: #(#(1 2 0) #(2 1 4) #(0 4 0)). - "just to be sure that s and s2 are indeed symmetric:" - self assert: s equals: s transpose. - self assert: s2 equals: s2 transpose. - r := m * s. - self - assert: r - equals: (PMMatrix rows: #(#(14 16 11) #(16 24 -11) #(38 44 39))). - self assert: r class equals: PMMatrix. - r := s * m. - self - assert: r - equals: (PMMatrix rows: #(#(14 16 38) #(21 26 41) #(-1 -2 37))). - self assert: r class equals: PMMatrix. - r := s * s2. - self deny: r = r transpose. "hence this (here is the bug) must be true:" - self assert: r class equals: PMMatrix. - self - assert: r - equals: (PMMatrix rows: #(#(5 16 8) #(4 21 4) #(11 10 16))). - r := s transposeProductWithMatrix: s2. - self deny: r = r transpose. "hence this must be true:" - self assert: r class equals: PMMatrix. - r := s productWithTransposeMatrix: s2. - self deny: r = r transpose. "hence this must be true:" - self assert: r class equals: PMMatrix. - self assert: s * s equals: s squared. - self assert: m transpose * m equals: m squared. - self assert: (r := m + s) equals: (r2 := s + m). - self assert: r class equals: PMMatrix. - self assert: r2 class equals: PMMatrix. - r2 := PMMatrix rows: #(#(0 0 0) #(-3 -3 3) #(2 2 7)). - self assert: (r := m - s) equals: r2. - self assert: r class equals: PMMatrix. - r := (s - m) negate. - self assert: r equals: r2. - self assert: r class equals: PMMatrix. - self assert: (r := s2 + s) equals: s + s2. - self assert: r class equals: PMSymmetricMatrix. - self assert: (r := s2 - s) equals: (s - s2) negate. - self assert: r class equals: PMSymmetricMatrix. - m := PMMatrix rows: #(#(-1 -2 7) #(5 6 7)). - self assert: m * s equals: (s * m transpose) transpose. - self assert: m transpose * m equals: m squared -] - -{ #category : #tests } -PMMatrixTest >> testSkalarMultiplication [ - | a r | - a := PMMatrix rows: #(#(1 2) #(3 3)). - "this was intended by the author to be possible; it can be seen by the code and the book:" - r := a * 2. - self assert: r class equals: PMMatrix. - self assert: r equals: (PMMatrix rows: #(#(2 4) #(6 6))). - self assert: 2 * a equals: r. - a := PMSymmetricMatrix rows: #(#(1 2) #(2 1)). - r := a * 2. - self assert: r equals: (PMMatrix rows: #(#(2 4) #(4 2))). - self assert: r class equals: PMSymmetricMatrix. - r := 2.0 * a. - self assert: r equals: (PMMatrix rows: #(#(2.0 4.0) #(4.0 2.0))). - self assert: r class equals: PMSymmetricMatrix -] - -{ #category : #tests } -PMMatrixTest >> testStrassenProductWithMatrix [ - - | aPMMatrix expected strassenProduct | - - aPMMatrix := PMMatrix rows: #( (1 2 3 4) (1 0 1 2) (2 3 1 4) (4 3 2 2)). - expected := PMMatrix rows: #( (30 12 27 24) (12 6 11 10) (27 11 30 27) (24 10 27 33)). - strassenProduct := aPMMatrix transpose strassenProductWithMatrix: aPMMatrix. - self assert: strassenProduct equals: expected. -] - -{ #category : #tests } -PMMatrixTest >> testStrassenProductWithMatrixWithInvalidShapes [ - - | aPMMatrix | - - "all the dimension of the matrices should be a power of 2 for strassen multiplication" - aPMMatrix := PMMatrix rows: #( (1 2 3) (1 0 1) (2 3 1) (2 0 1)). - - self should: [ aPMMatrix strassenProductWithMatrix: aPMMatrix transpose ] raise: AssertionFailure. - -] - -{ #category : #tests } -PMMatrixTest >> testSymmetric [ -|a m| -a:=#(1 2 3)asPMVector. -m:=PMMatrix rows: #((1 2)(3 3)). -self deny: (m isSymmetric ). -"but a PMMatrix can of course also be symmetric, -and it is occasionally interesting to know, -hence the result should be correct" -m:=PMMatrix rows: (a tensorProduct: a)rows. -self assert: (m isSymmetric ). - - -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testSymmetricMatrixAdd [ - | a b c | - a := (PMMatrix rows: #(#(11 12 13) #(12 22 23) #(13 23 33))) - asSymmetricMatrix. - b := PMMatrix rows: #(#(1 2 3) #(-2 1 7) #(0 0 0)). - c := a + b. - self assert: c numberOfRows equals: 3. - self assert: c numberOfColumns equals: 3. - self assert: ((c rowAt: 1) at: 1) equals: 12. - self assert: ((c rowAt: 1) at: 2) equals: 14. - self assert: ((c rowAt: 1) at: 3) equals: 16 -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testSymmetricMatrixAdd2 [ - | a b c | - a := PMSymmetricMatrix rows: #(#(11 12 13) #(12 22 23) #(13 23 33)). - b := PMSymmetricMatrix rows: #(#(1 2 3) #(2 1 7) #(3 7 0)). - c := a + b. - self assert: c numberOfRows equals: 3. - self assert: c numberOfColumns equals: 3. - self assert: ((c rowAt: 1) at: 1) equals: 12. - self assert: ((c rowAt: 1) at: 2) equals: 14. - self assert: ((c rowAt: 1) at: 3) equals: 16 -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testSymmetricMatrixAdd3 [ - | a b c | - a := PMMatrix rows: #(#(11 12 13) #(21 22 23) #(31 32 33)). - b := PMSymmetricMatrix rows: #(#(1 2 3) #(-2 1 7) #(0 0 0)). - c := a + b. - self assert: c numberOfRows equals: 3. - self assert: c numberOfColumns equals: 3. - self assert: ((c rowAt: 1) at: 1) equals: 12. - self assert: ((c rowAt: 1) at: 2) equals: 14. - self assert: ((c rowAt: 1) at: 3) equals: 16. - self assert: ((c rowAt: 2) at: 1) equals: 19. - self assert: ((c rowAt: 2) at: 2) equals: 23. - self assert: ((c rowAt: 2) at: 3) equals: 30. - self assert: ((c rowAt: 3) at: 1) equals: 31 -] - -{ #category : #tests } -PMMatrixTest >> testTake [ - - | m expected | - m := PMMatrix rows: #((1 2)(3 3)). - expected := PMMatrix rows: #((0 1) (3 3)). - self assert: (m take: 2) equals: expected. - - m := PMMatrix rows: #((1 2)). - expected := PMMatrix rows: #((0 1)). - self assert: (m take: 2) equals: expected. - - m := PMMatrix rows: #(). - expected := PMMatrix rows: #(). - self assert: (m take: 2) equals: expected. -] - -{ #category : #tests } -PMMatrixTest >> testVectorConversion [ - | m | - m := PMMatrix rows: #(#(1 2 3) #(4 5 6) #(7 8 9)). - self assert: m asVector equals: #(1 2 3 4 5 6 7 8 9) asPMVector -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testVectorMatrixOperation [ - "Code Example 8.1" - - | a u v | - a := PMMatrix rows: #(#(1 0 1) #(-1 -2 3)). - u := #(1 2 3) asPMVector. - v := a * u. - self assert: v size equals: 2. - self assert: (v at: 1) equals: 4. - self assert: (v at: 2) equals: 4 -] - -{ #category : #tests } -PMMatrixTest >> testVectorToVectorConversion [ - - | vect result expected | - vect := #( 1 0.5 0.2 3 1 -1 7 3 2 12 13 3 ) asPMVector. - result := vect reshapeWithDimensions: #( 1 12 ). - - expected := PMMatrix rows: #( #( 1 0.5 0.2 3 1 -1 7 3 2 12 13 3 ) ). - - self assert: result equals: expected -] - -{ #category : #'linear algebra' } -PMMatrixTest >> testVectorTransposeMatrixOperation [ - "Code Example 8.1" - - | c v w | - c := PMMatrix rows: #(#(6 8 10) #(18 14 4)). - v := #(4 4) asPMVector. - w := c transpose * v. - self assert: w size equals: 3. - self assert: (w at: 1) equals: 96. - self assert: (w at: 2) equals: 88. - self assert: (w at: 3) equals: 56 -] - -{ #category : #tests } -PMMatrixTest >> testZerosMatrix [ -|a| - a:=PMMatrix zerosRows: 2 cols: 3. - self assert: a numberOfRows equals: 2. - self assert: a numberOfColumns equals: 3. - self assert: ((a rowAt: 1) at: 1) equals: 0. - self assert: ((a rowAt: 1) at: 2) equals: 0. - self assert: ((a rowAt: 1) at: 3) equals: 0. - self assert: ((a rowAt: 2) at: 1) equals: 0. - self assert: ((a rowAt: 2) at: 2) equals: 0. - self assert: ((a rowAt: 2) at: 3) equals: 0 -] diff --git a/src/Math-Tests-Matrix/PMNDArrayTest.class.st b/src/Math-Tests-Matrix/PMNDArrayTest.class.st deleted file mode 100644 index 4486534df..000000000 --- a/src/Math-Tests-Matrix/PMNDArrayTest.class.st +++ /dev/null @@ -1,243 +0,0 @@ -Class { - #name : #PMNDArrayTest, - #superclass : #TestCase, - #category : #'Math-Tests-Matrix' -} - -{ #category : #tests } -PMNDArrayTest >> testArray [ - - | t1 t2 | - t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - self assert: t1 asArray equals: #( 1 2 3 4 5 6 7 8 ). - - t2 := PMNDArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). - self - assert: t2 asArray - equals: #( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ) -] - -{ #category : #tests } -PMNDArrayTest >> testAt [ - - | t1 t2 | - t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - self assert: (t1 at: #( 2 2 )) equals: 6. - - t2 := PMNDArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). - self assert: (t2 at: #( 3 2 1 )) equals: 11. - - self should:[t1 at: #( 4 4 )] raise:Error -] - -{ #category : #tests } -PMNDArrayTest >> testAtPut [ - - | t1 t2 | - t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - t1 at: #( 2 2 ) put: 3. - self assert: (t1 at: #( 2 2 ) ) equals: 3. - - t2 := PMNDArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) - #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) - #( #( 13 14 ) #( 15 16 ) ) ). - t2 at: #( 2 2 1) put: 10. - self assert: (t2 at: #( 2 2 1 )) equals: 10 -] - -{ #category : #tests } -PMNDArrayTest >> testCreateScalarNDArray [ - - | s | - s := PMNDArray fromScalar: 2. - self assert: (s at: #( )) equals: 2. - self should: [ s at: #( 1 1 ) ] raise: Error. - self assert: s rank equals: 0. - s at: #( ) put: 1. - self assert: (s at: #( )) equals: 1. - self assert: s shape equals: #( ). - self assert: s size equals: 1 -] - -{ #category : #tests } -PMNDArrayTest >> testFirst [ - - | a b | - a := PMNDArray fromNestedArray: (1 to: 6) asArray. - self assert: a first equals: #( 1). - b := a reshape: #( 3 2 ). - self assert: b first equals: #( 1 1 ) -] - -{ #category : #tests } -PMNDArrayTest >> testFlattenedIndexOf [ - - | t1 t2 | - t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8) #( 9 10 11 12)). - self assert: (t1 flattenedIndexOf: #( 3 2 )) equals: 10. - - t2 := PMNDArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). - self assert: (t2 flattenedIndexOf: #( 1 2 2 )) equals: 4 -] - -{ #category : #tests } -PMNDArrayTest >> testFromNestedArray [ - - | t1 t2 | - t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) - #( 5 6 7 8 ) ). - self assert: t1 class equals: PMNDArray. - - t2 := PMNDArray fromNestedArray: #( #( #( 1 1 ) #( 2 2 ) ) - #( #( 3 3 ) #( 4 4 ) ) - #( #( 4 4 ) #( 4 4 ) ) - #( #( 4 4 ) #( 4 4 ) ) ). - self assert: t2 class equals: PMNDArray. - -] - -{ #category : #tests } -PMNDArrayTest >> testHadamardProduct [ -|t1 t2 expectedHadamardProduct| - - t1 := PMNDArray fromNestedArray: #( - #( 1 2 3 4 ) #( 5 6 7 8 ) - ). - t2 := PMNDArray fromNestedArray: #( - #( 4 3 2 9 ) #( 9 7 6 5 ) - ). - expectedHadamardProduct := PMNDArray fromNestedArray:#( - #( 4 6 6 36 ) #( 45 42 42 40 ) - ). - - self assert: (t1 hadamardProduct: t2) equals: expectedHadamardProduct. - - t1 := PMNDArray fromNestedArray: - #( - #( #( 1 2 ) #( 3 4 )) - #( #( 5 6 ) #( 7 8 )) - #( #( 9 10) #( 11 12)) - ). - - t2 := PMNDArray fromNestedArray: - #( - #( #( 1 3 ) #( 2 1)) - #( #( 0 6 ) #( 3 8)) - #( #( 3 5) #( 1 10)) - ). - - expectedHadamardProduct := PMNDArray fromNestedArray:#( - #( #( 1 6 ) #( 6 4 )) - #( #( 0 36 ) #( 21 64 )) - #( #( 27 50 ) #( 11 120 ))). - - -self assert: (t1 hadamardProduct: t2) equals: expectedHadamardProduct - - - - - -] - -{ #category : #tests } -PMNDArrayTest >> testHadamardProductWithDifferentShapesFails [ -|t1 t2| - t1 := PMNDArray fromNestedArray: #( #( 1 2) #(3 4) #(5 6) #(7 8)). - t2 := PMNDArray fromNestedArray: #( #( 4 3 2 9 ) #( 9 7 6 5 ) ). - self should: [t1 hadamardProduct: t2] raise: ShapeMismatch -] - -{ #category : #tests } -PMNDArrayTest >> testRank [ - - | t1 t2 | - - t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - self assert: t1 rank equals: 2. - - t2 := PMNDArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). - self assert: t2 rank equals: 3 -] - -{ #category : #tests } -PMNDArrayTest >> testReshape [ - - | t t1 | - t := PMNDArray fromNestedArray: #( #( 0 1 ) #( 2 3 ) #( 4 5 ) ). - t1 := t reshape: #( 2 3 ). - - self assert: t shape equals: #( 3 2 ). - self assert: t1 shape equals: #( 2 3 ). - self assert: t1 asArray == t asArray equals: true -] - -{ #category : #tests } -PMNDArrayTest >> testShape [ - - | t1 t2 | - t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) - #( 5 6 7 8 ) ). - self assert: t1 shape equals: #( 2 4 ). - - t2 := PMNDArray fromNestedArray: #( #( #( 1 1 ) #( 2 2 ) ) - #( #( 3 3 ) #( 4 4 ) ) - #( #( 4 4 ) #( 4 4 ) ) - #( #( 4 4 ) #( 4 4 ) ) ). - self assert: t2 shape equals: #( 4 2 2 ) -] - -{ #category : #tests } -PMNDArrayTest >> testSize [ - - | t1 t2 | - t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - self assert: t1 size equals: 8. - - t2 := PMNDArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). - self assert: t2 size equals: 16 -] - -{ #category : #tests } -PMNDArrayTest >> testStrides [ - - | a b | - a := PMNDArray fromNestedArray: (1 to: 24) asArray. - self assert: a strides equals: #( 1 ). - b := a reshape: #( 4 6 ). - self assert: b strides equals: #( 6 1 ). - b := a reshape: #( 6 4 ). - self assert: b strides equals: #( 4 1 ). - self assert: (b flattenedIndexOf: #( 4 2 )) equals: 14. - b := a reshape: #( 3 4 2 ). - self assert: b strides equals: #( 8 2 1 ). - self assert: (b flattenedIndexOf: #( 3 2 1)) equals: 19. - b := a reshape: #( 2 3 4 ). - self assert: b strides equals: #( 12 4 1 ). - self assert: (b flattenedIndexOf: #( 2 2 3 )) equals: 19 -] - -{ #category : #tests } -PMNDArrayTest >> testView [ - - | t t1 | - t := PMNDArray fromNestedArray: - #( #( 10 11 12 ) #( 13 14 15 ) #( 16 17 18 ) #( #( 20 21 22 ) - #( 23 24 25 ) #( 26 27 28 ) ) - #( #( 30 31 32 ) #( 33 34 35 ) #( 36 37 38 ) ) ). - t1 := t view. - self assert: t asArray == t1 asArray equals: true. - self assert: t shape equals: t1 shape. - self assert: t shape == t1 shape equals: false. - self assert: t strides equals: t1 strides. - self assert: t strides == t1 strides equals: false. - self assert: t first equals: t1 first. - self assert: t first == t1 first equals: false. - -] diff --git a/src/Math-Tests-Matrix/PMQRTest.class.st b/src/Math-Tests-Matrix/PMQRTest.class.st deleted file mode 100644 index a2fb5c45e..000000000 --- a/src/Math-Tests-Matrix/PMQRTest.class.st +++ /dev/null @@ -1,259 +0,0 @@ -Class { - #name : #PMQRTest, - #superclass : #TestCase, - #category : #'Math-Tests-Matrix' -} - -{ #category : #running } -PMQRTest >> assert: inverse isMoorePenroseInverseOf: aMatrix [ - - "https://en.wikipedia.org/wiki/Moore–Penrose_inverse#Definition" - - | identityMatrix | - "These two assertions are what define a pseudoinverse. They are known as - the Moore–Penrose conditions of which there are four, but here we have two. The other two - are that (A * A+) and A+ * A are Hermitian. - " - self assert: aMatrix * inverse * aMatrix closeTo: aMatrix. - self assert: inverse * aMatrix * inverse closeTo: inverse. - - identityMatrix := aMatrix * inverse. - self assert: identityMatrix transpose closeTo: identityMatrix. - self assert: identityMatrix * aMatrix closeTo: aMatrix. - - "Pseudoinversion commutes with transposition, complex conjugation, and taking the conjugate transpose" - self - assert: aMatrix transpose mpInverse - closeTo: aMatrix mpInverse transpose. -] - -{ #category : #tests } -PMQRTest >> testDecompositionOfMatrixCausingErraticFailure [ - - | a qrDecomposition matricesAndPivot q r expectedMatrix pivot | - a := PMSymmetricMatrix rows: - #( #( 0.41929313699681925 0.05975350554089691 - 0.2771676258543356 0.35628773381760703 ) - #( 0.05975350554089691 0.12794227252152854 - 0.3257742693302102 0.28814463284245906 ) - #( 0.2771676258543356 0.3257742693302102 0.8468441832097453 - 0.9101872061892353 ) - #( 0.35628773381760703 0.28814463284245906 - 0.9101872061892353 0.5163744224777326 ) ). - - qrDecomposition := PMQRDecomposition of: a. - matricesAndPivot := qrDecomposition decomposeWithPivot. - - expectedMatrix := PMMatrix rows: - #( #( 0.2771676258543356 0.35628773381760703 - 0.41929313699681925 0.05975350554089691 ) - #( 0.3257742693302102 0.28814463284245906 - 0.05975350554089691 0.12794227252152854 ) - #( 0.8468441832097453 0.9101872061892353 - 0.2771676258543356 0.3257742693302102 ) - #( 0.9101872061892353 0.5163744224777326 - 0.35628773381760703 0.28814463284245906 ) ). - q := matricesAndPivot at: 1. - r := matricesAndPivot at: 2. - pivot := matricesAndPivot at: 3. - self assert: q * r closeTo: expectedMatrix. - self assert: pivot equals: #( 3 4 3 nil ) -] - -{ #category : #tests } -PMQRTest >> testHorizontalRectangularMatrixCannotBeDecomposed [ - - | horizontalRectangularMatrix | - horizontalRectangularMatrix := PMMatrix rows: { - { 1. 2. 4 }. - { 5. 6. 7 } }. - - self - should: [ - (PMQRDecomposition of: horizontalRectangularMatrix) ] - raise: Error -] - -{ #category : #tests } -PMQRTest >> testMoorePenroseInverseOfLargeNonRandomMatrixAndItsTranspose [ - | a inverse transposeOfA | - a := PMMatrix new initializeRows: - #( #( 5 40 1 2.5 ) #( 0 0 1 2.5 ) #( 0 0 1 2.5 ) ). - inverse := a mpInverse . - self assert: inverse isMoorePenroseInverseOf: a. - - transposeOfA := a transpose. - inverse := transposeOfA mpInverse . - self assert: inverse isMoorePenroseInverseOf: transposeOfA. -] - -{ #category : #tests } -PMQRTest >> testMoorePenroseInverseOfNonRandomMatrix [ - | a inverse | - a := PMMatrix new initializeRows: - #( #( 5 40 1 ) #( 0 0 1 ) #( 0 0 1 ) ). - inverse := a mpInverse . - self assert: inverse isMoorePenroseInverseOf: a. -] - -{ #category : #tests } -PMQRTest >> testMoorePenroseInverseOfProductOfMatrices [ - | a inverse | - a := PMMatrix new initializeRows: - #( #( 5 40 1 ) #( 0 0 1 ) #( 0 0 1 ) ). - - a := a * (PMMatrix rows: 3 columns: 3 random: 5.0). - inverse := a mpInverse . - self assert: inverse isMoorePenroseInverseOf: a. -] - -{ #category : #tests } -PMQRTest >> testMoorePenroseInverseOfRandomMatrixIsAnInverse [ -" -Proofs for the properties below can be found in literature: -If A has real entries, then so does A+ -If A is invertible, its pseudoinverse is its inverse. That is, A+ = A**−1 -" - - | a | - a := PMSymmetricMatrix new: 4 random: 1.0. - self assert: (a mpInverse closeTo: a inverse) -] - -{ #category : #tests } -PMQRTest >> testOrthogonalize [ - - | a b i | - i := 0. - [ - a := PMMatrix rows: 5 columns: 5 random: 5.0. - a rank = 5 ifTrue: [ - a atRow: 2 put: (a rowAt: 1) + (3 * (a rowAt: 3)). - a atRow: 4 put: 3.11 * (a rowAt: 2). - b := a orthogonalize. - self assert: b numberOfColumns equals: 3. - i := i + 1. - self assert: ((b columnAt: 1) * (b columnAt: 2) closeTo: 0). - self assert: ((b columnAt: 1) * (b columnAt: 3) closeTo: 0). - self assert: ((b columnAt: 3) * (b columnAt: 2) closeTo: 0). - self assert: ((b columnAt: 1) * (b columnAt: 1) closeTo: 1). - self assert: ((b columnAt: 3) * (b columnAt: 3) closeTo: 1). - self assert: ((b columnAt: 2) * (b columnAt: 2) closeTo: 1) ]. - i < 10 ] whileTrue -] - -{ #category : #tests } -PMQRTest >> testQRFactorization [ - - | a qr | - 5 timesRepeat: [ - a := PMMatrix rows: 5 columns: 4 random: 10.0. - qr := a qrFactorization. - self assert: (a closeTo: qr first * qr second). - self assert: (qr first squared closeTo: - (PMSymmetricMatrix identity: qr first numberOfColumns)). - 2 to: qr second numberOfRows do: [ :r | - self assert: (((qr second rowAt: r) first: r - 1) closeTo: - (Array new: r - 1 withAll: 0)) ]. - - qr := a qrFactorizationWithPivoting. - self assert: - (a closeTo: qr first * (qr second inversePivotColumns: (qr at: 3))). - self assert: (qr first squared closeTo: - (PMSymmetricMatrix identity: qr first numberOfColumns)). - 2 to: qr second numberOfRows do: [ :r | - self assert: (((qr second rowAt: r) first: r - 1) closeTo: - (Array new: r - 1 withAll: 0)) ]. - - a := PMSymmetricMatrix new: 4 random: 10.0. - qr := a qrFactorization. - self assert: (a closeTo: qr first * qr second). - self assert: (qr first squared closeTo: - (PMSymmetricMatrix identity: qr first numberOfColumns)). - 2 to: qr second numberOfRows do: [ :r | - self assert: (((qr second rowAt: r) first: r - 1) closeTo: - (Array new: r - 1 withAll: 0)) ]. - - qr := a qrFactorizationWithPivoting. - self assert: - (a closeTo: qr first * (qr second inversePivotColumns: (qr at: 3))). - self assert: (qr first squared closeTo: - (PMSymmetricMatrix identity: qr first numberOfColumns)). - 2 to: qr second numberOfRows do: [ :r | - self assert: (((qr second rowAt: r) first: r - 1) closeTo: - (Array new: r - 1 withAll: 0)) ] ] -] - -{ #category : #tests } -PMQRTest >> testRank [ - | random randomNumber matrix | - random := Random new. - - 10 timesRepeat: [ - matrix := PMMatrix rows: 5 columns: 7 random: 5.0. - matrix rank = 5 ifTrue: [ - randomNumber := random nextBetween: 0 and: 3. - matrix atRow: 2 put: (matrix rowAt: 1) + (randomNumber * (matrix rowAt: 3)). - - randomNumber := random nextBetween: 0 and: 3. - matrix atRow: 4 put: (0.5 + randomNumber) * (matrix rowAt: 5). - - self assert: matrix rank equals: 3. - self assert: matrix transpose rank equals: 3 ] ]. -] - -{ #category : #tests } -PMQRTest >> testSimpleQRDecomposition [ - - | a qrDecomposition decomposition | - a := PMMatrix rows: { - { 12. -51. 4 }. - { 6. 167. -68 }. - { -4. 24. -41 } }. - - qrDecomposition := PMQRDecomposition of: a. - - decomposition := qrDecomposition decompose. - decomposition first * decomposition second. - self assert: decomposition first * decomposition second equals: a -] - -{ #category : #tests } -PMQRTest >> testSimpleQRDecompositionWithPivot [ - - | a qrDecomposition decomposition expected | - a := PMMatrix rows: { - { 12. -51. 4 }. - { 6. 167. -68 }. - { -4. 24. -41 } }. - - qrDecomposition := PMQRDecomposition of: a. - - decomposition := qrDecomposition decomposeWithPivot. - decomposition first * decomposition second. - - expected := PMMatrix rows: { - { -51. 4. 12 }. - { 167. -68. 6 }. - { 24. -41. -4 } }. - self - assert: decomposition first * decomposition second - closeTo: expected -] - -{ #category : #tests } -PMQRTest >> testVectorHouseholder [ - - "result is householdermatrix * v" - - (2 to: 5) do: [ :i | - | v h result | - (1 to: 9) do: [ :unimportant | - v := PMVector new: i random: 5.8. - h := v householder. - result := (PMSymmetricMatrix identity: i) - - ((h at: 1) * (h at: 2) tensorProduct: (h at: 2)) * v. - self deny: (result first closeTo: 0). - result allButFirst do: [ :aNumber | - self assert: (aNumber closeTo: 0) ] ] ] -] diff --git a/src/Math-Tests-Matrix/PMRestTest.class.st b/src/Math-Tests-Matrix/PMRestTest.class.st deleted file mode 100644 index 11bcfe72a..000000000 --- a/src/Math-Tests-Matrix/PMRestTest.class.st +++ /dev/null @@ -1,36 +0,0 @@ -Class { - #name : #PMRestTest, - #superclass : #TestCase, - #category : #'Math-Tests-Matrix' -} - -{ #category : #tests } -PMRestTest >> testEqualsTo [ - - | a b | - a := PMMatrix rows: 5 columns: 7 random: 5.0. - b := a deepCopy. - self assert: (a closeTo: b). - b rowAt: 4 columnAt: 6 put: 6. - self deny: (a closeTo: b) -] - -{ #category : #tests } -PMRestTest >> testNewRandom [ -|a | -a:=PMSymmetricMatrix new:7 random: 5.0 . -a:=PMMatrix rows: a rows. -self assert: (a isSymmetric ). - - -] - -{ #category : #tests } -PMRestTest >> testSwapColumnWithColumn [ - | a | - a := PMMatrix new initializeRows: #(#(5 40 1) #(3 0 1) #(2 7 1)). - a swapColumn: 2 withColumn: 1. - self - assert: a - equals: (PMMatrix new initializeRows: #(#(40 5 1) #(0 3 1) #(7 2 1))) -] diff --git a/src/Math-Tests-Matrix/PMSingularValueDecompositionTest.class.st b/src/Math-Tests-Matrix/PMSingularValueDecompositionTest.class.st deleted file mode 100644 index 5597658e1..000000000 --- a/src/Math-Tests-Matrix/PMSingularValueDecompositionTest.class.st +++ /dev/null @@ -1,311 +0,0 @@ -" -Please comment me using the following template inspired by Class Responsibility Collaborator (CRC) design: - -For the Class part: State a one line summary. For example, ""I represent a paragraph of text"". - -For the Responsibility part: Three sentences about my main responsibilities - what I do, what I know. - -For the Collaborators Part: State my main collaborators and one line about how I interact with them. - -Public API and Key Messages -- message one -- message two -- (for bonus points) how to create instances. - - One simple example is simply gorgeous. - -Internal Representation and Key Implementation Points. - - Instance Variables - ones: - randomMatrix: - s_matrix: - u: - v: - - - Implementation Points -" -Class { - #name : #PMSingularValueDecompositionTest, - #superclass : #TestCase, - #instVars : [ - 'matrix', - 'actualU', - 'actualV', - 'actualS' - ], - #category : #'Math-Tests-Matrix' -} - -{ #category : #'as yet unclassified' } -PMSingularValueDecompositionTest >> loadExample1 [ - "Simple example. Square matrix with real values" - - matrix := PMMatrix rows: #( - (0 4) - (0 0)). - - actualU := PMMatrix rows: #( - (1 0) - (0 1)). - - actualV := PMMatrix rows: #( - (0 1) - (1 0)). - - actualS := PMMatrix rows: #( - (4 0) - (0 0)). -] - -{ #category : #'as yet unclassified' } -PMSingularValueDecompositionTest >> loadExample2 [ - "Simple example. Square matrix with real values" - - matrix := PMMatrix rows: #( - (0 1 0 0) - (0 0 2 0) - (0 0 0 3) - (0 0 0 0)). - - actualU := PMMatrix rows: #( - (0 0 1 0) - (0 1 0 0) - (1 0 0 0) - (0 0 0 1)). - - actualV := PMMatrix rows: #( - (0 0 0 1) - (0 0 1 0) - (0 1 0 0) - (1 0 0 0)). - - actualS := PMMatrix rows: #( - (3 0 0 0) - (0 2 0 0) - (0 0 1 0) - (0 0 0 0)). -] - -{ #category : #'as yet unclassified' } -PMSingularValueDecompositionTest >> loadExample3 [ - "Rectangular matrix with real values" - - matrix := PMMatrix rows: #( - (-1 1 0) - (0 -1 1)). - - actualU := PMMatrix rows: ( - Array - with: (Array with: -1 / (2 sqrt) with: 1 / (2 sqrt)) - with: (Array with: 1 / (2 sqrt) with: 1 / (2 sqrt)) ). - - actualV := PMMatrix rows: ( - Array - with: (Array with: 1 / (6 sqrt) with: -1 / (2 sqrt) with: 1 / (3 sqrt)) - with: (Array with: -2 / (6 sqrt) with: 0 with: 1 / (3 sqrt)) - with: (Array with: 1 / (6 sqrt) with: 1 / (2 sqrt) with: 1 / (3 sqrt)) ). - - actualS := PMMatrix rows: ( - Array - with: (Array with: 3 sqrt with: 0 with: 0) - with: (Array with: 0 with: 1 with: 0) ). -] - -{ #category : #'as yet unclassified' } -PMSingularValueDecompositionTest >> loadExample4 [ - "Rectangular matrix with real values" - - matrix := PMMatrix rows: #( - (1 0 0 0 2) - (0 0 3 0 0) - (0 0 0 0 0) - (0 2 0 0 0)). - - actualU := PMMatrix rows: #( - (0 0 1 0) - (0 1 0 0) - (0 0 0 -1) - (1 0 0 0)). - - actualV := PMMatrix rows: (Array - with: ( Array with: 0 with: 0 with: 0.2 sqrt with: 0 with: -1 * (0.8 sqrt)) - with: ( Array with: 1 with: 0 with: 0 with: 0 with: 0) - with: ( Array with: 0 with: 1 with: 0 with: 0 with: 0) - with: ( Array with: 0 with: 0 with: 0 with: 1 with: 0) - with: ( Array with: 0 with: 0 with: 0.8 sqrt with: 0 with: 0.2 sqrt) - ). - - actualS := PMMatrix rows: (Array - with: (Array with: 2 with: 0 with: 0 with: 0 with: 0) - with: (Array with: 0 with: 3 with: 0 with: 0 with: 0) - with: (Array with: 0 with: 0 with: 5 sqrt with: 0 with: 0) - with: (Array with: 0 with: 0 with: 0 with: 0 with: 0) - ) -] - -{ #category : #initialization } -PMSingularValueDecompositionTest >> setUp [ - super setUp. - self loadExample1 - "self loadExample2." - "self loadExample3." - "self loadExample4." -] - -{ #category : #tests } -PMSingularValueDecompositionTest >> testIsExampleCorrect [ - "Verifying that the example SVD is correct" - - | reconstructed | - reconstructed := actualU * actualS * actualV transpose. - self assert: reconstructed closeTo: matrix. -] - -{ #category : #tests } -PMSingularValueDecompositionTest >> testIsExampleOrthonormalU [ - "Verifying that matrix U in the given example is orthonormal. That is, all columns of U are unit vectors and orthogonal to each other." - - | m identity | - - m := actualU numberOfRows. - - identity := PMSymmetricMatrix identity: m. - self assert: (actualU transpose * actualU) closeTo: identity -] - -{ #category : #tests } -PMSingularValueDecompositionTest >> testIsExampleOrthonormalV [ - "Verifying that matrix V in the given example is orthonormal. That is, all columns of V are unit vectors and orthogonal to each other." - - | n identity | - - n := actualV numberOfRows. - - identity := PMSymmetricMatrix identity: n. - self assert: (actualV transpose * actualV) closeTo: identity -] - -{ #category : #tests } -PMSingularValueDecompositionTest >> testIsOrthonormalU [ - - "Verifying that matrix U is orthonormal. That is, all columns of U are unit vectors and orthogonal to each other." - - | u m identity | - u := matrix decomposeSV leftSingularMatrix. - m := u numberOfRows. - identity := PMSymmetricMatrix identity: m. - self assert: u transpose * u closeTo: identity -] - -{ #category : #tests } -PMSingularValueDecompositionTest >> testIsOrthonormalV [ - - "Verifying that matrix U is orthonormal. That is, all columns of U are unit vectors and orthogonal to each other." - - | v n identity | - v := matrix decomposeSV rightSingularMatrix. - n := v numberOfRows. - identity := PMSymmetricMatrix identity: n. - self assert: v transpose * v closeTo: identity -] - -{ #category : #tests } -PMSingularValueDecompositionTest >> testIsSquareU [ - - "U should be a square matrix" - - | u | - u := matrix decomposeSV leftSingularMatrix. - self assert: u numberOfRows equals: u numberOfColumns -] - -{ #category : #tests } -PMSingularValueDecompositionTest >> testIsSquareV [ - - "V should be a square matrix" - - | v | - v := matrix decomposeSV rightSingularMatrix. - self assert: v numberOfRows equals: v numberOfColumns -] - -{ #category : #tests } -PMSingularValueDecompositionTest >> testReconstruction [ - - | svd u v s reconstructed | - svd := matrix decomposeSV. - u := svd leftSingularMatrix. - v := svd rightSingularMatrix. - s := svd diagonalSingularValueMatrix. - reconstructed := u * s * v transpose. - self assert: reconstructed closeTo: matrix -] - -{ #category : #tests } -PMSingularValueDecompositionTest >> testShapeS [ - - "If A is an (m x n) matrix, then S should be an (m x n) matrix" - - | s m n | - s := matrix decomposeSV diagonalSingularValueMatrix. - m := matrix numberOfRows. - n := matrix numberOfColumns. - self assert: s numberOfRows equals: m. - self assert: s numberOfColumns equals: n -] - -{ #category : #tests } -PMSingularValueDecompositionTest >> testShapeU [ - - "If A is an (m x n) matrix, then U should be an (m x m) matrix" - - | u m | - u := matrix decomposeSV leftSingularMatrix. - m := matrix numberOfRows. - self assert: u numberOfRows equals: m. - self assert: u numberOfColumns equals: m -] - -{ #category : #tests } -PMSingularValueDecompositionTest >> testShapeV [ - - "If A is an (m x n) matrix, then V should be an (n x n) matrix" - - | v n | - v := matrix decomposeSV rightSingularMatrix. - n := matrix numberOfColumns. - self assert: v numberOfRows equals: n. - self assert: v numberOfColumns equals: n -] - -{ #category : #tests } -PMSingularValueDecompositionTest >> testValueS [ - - "Comparing S to its known value" - - | s | - s := matrix decomposeSV diagonalSingularValueMatrix. - self assert: s closeTo: actualS -] - -{ #category : #tests } -PMSingularValueDecompositionTest >> testValueU [ - - "Comparing U to its known value" - - | u | - u := matrix decomposeSV leftSingularMatrix. - self assert: u closeTo: actualU -] - -{ #category : #tests } -PMSingularValueDecompositionTest >> testValueV [ - - "Comparing V to its known value" - - | v | - v := matrix decomposeSV rightSingularMatrix. - self assert: v closeTo: actualV -] diff --git a/src/Math-Tests-Matrix/PMSymmetricMatrixTest.class.st b/src/Math-Tests-Matrix/PMSymmetricMatrixTest.class.st deleted file mode 100644 index d9c16c0db..000000000 --- a/src/Math-Tests-Matrix/PMSymmetricMatrixTest.class.st +++ /dev/null @@ -1,61 +0,0 @@ -Class { - #name : #PMSymmetricMatrixTest, - #superclass : #TestCase, - #category : #'Math-Tests-Matrix' -} - -{ #category : #tests } -PMSymmetricMatrixTest >> testCrlInverse [ - | m i | - m := PMSymmetricMatrix rows: #(#(2 2 3) #(2 4 5) #(3 5 6)). - i := m crlInverse. - self assert: m * i equals: (PMSymmetricMatrix identity: 3) - "the funny result of m*i with the bug is this matrix: -a PMVector(1 0 -24) -a PMVector(0 1 -40) -a PMVector(2 4 -51)" -] - -{ #category : #tests } -PMSymmetricMatrixTest >> testEqual [ - "= should work like in a SequenceableCollection eg a PMVector and a Array can be equal" - - | a b | - a := PMMatrix rows: #(#(2 2 3) #(2 4 5) #(3 5 6)). - b := a asSymmetricMatrix. - self assert: a equals: b. - self assert: b equals: a. - self assert: a hash equals: b hash. - a := PMMatrix rows: #(#(1 2 3) #(2 4 5) #(3 5 6)). - self assert: a ~= b. - self assert: b ~= a. - self assert: a hash ~= b hash. - a := a asSymmetricMatrix. - self assert: a ~= b. - a := 2. - self assert: b ~= a. - a := 's'. - self assert: b ~= a -] - -{ #category : #tests } -PMSymmetricMatrixTest >> testIdentityMatrix [ - |expectedIdentityMatrix identityMatrix| - - identityMatrix := PMSymmetricMatrix identity: 3. - expectedIdentityMatrix := PMSymmetricMatrix rows: #(#(1 0 0) #(0 1 0) #(0 0 1)). - - self assert: identityMatrix equals: expectedIdentityMatrix. -] - -{ #category : #tests } -PMSymmetricMatrixTest >> testInversePureLUP [ - | m i | - m := PMSymmetricMatrix rows: #(#(2 2 3) #(2 4 5) #(3 5 6)). - "this raises an error" - i := m inversePureLUP. - self assert: m * i equals: (PMSymmetricMatrix identity: 3). - "there is no(!) bug in inversePureCRL, but it is nowhere tested i think, hence i just added this here for the sake of simplicity (and because i simplified inversePureCRL)" - i := m inversePureCRL. - self assert: m * i equals: (PMSymmetricMatrix identity: 3) -] diff --git a/src/Math-Tests-Matrix/package.st b/src/Math-Tests-Matrix/package.st deleted file mode 100644 index 57c1dd73a..000000000 --- a/src/Math-Tests-Matrix/package.st +++ /dev/null @@ -1 +0,0 @@ -Package { #name : #'Math-Tests-Matrix' }