Framework
Haskell implementation of fast Practicable Inducers/Framework
Sections
Histogram and HistogramRepa
Histograms are defined in the overview in section ‘States, histories and histograms’ P8 and in the paper in section ‘Histograms’ P94. The discussion of the Haskell implementation of Histograms is in the Haskell implementation of the Overview.
The set of all histograms $\mathcal{A}$ is a subset of the positive rational valued functions of states, $\mathcal{A} \subset \mathcal{S} \to \mathbf{Q}_{\geq 0}$.
The Histogram
type is defined in module Alignment
with a Map.Map
from State
to Rational
,
newtype Histogram = Histogram (Map.Map State Rational)
This set-theoretic implementation is a poset binary map representation discussed in the paper in section ‘Computation of histograms’ P405. The definition of binary maps is in appendix ‘Binary maps’ P1164.
In the case where the histogram $A \in \mathcal{A}$ is complete, $A^{\mathrm{S}} = V^{\mathrm{CS}}$ where $V = \mathrm{vars}(A)$, the binary map histogram representation has accessor time complexity of $\ln v$ where volume $v = |V^{\mathrm{C}}|$. In the case of a regular histogram of valency $\{d\} = \{|U_w| : w \in V\}$, the time complexity is $n \ln d$, where dimension $n = |V|$.
An array histogram representation (P402) is implemented as an array of counts, $\mathbf{Q}_{\geq 0}^v$, of size $v$. If indexing is implemented with an ordered list state representation the accessor time complexity is $n$. The array histogram representation may require less time, but the array must be of cardinality equal to the volume, and so its space complexity is $v$, which may be greater than that of the effective binary map histogram representation, $|A^{\mathrm{F}}| \ln |A^{\mathrm{F}}|$.
For the cases where the volume is practicable, the module AlignmentRepa
defines type HistogramRepa
in terms of the multi-dimensional shape polymorphic parallel array which is defined in the repa library,
data HistogramRepa = HistogramRepa {
histogramRepasVectorVar :: !(V.Vector Variable),
histogramRepasMapVarInt :: Map.Map Variable Int,
histogramRepasArray :: !(Array U VShape Double)}
A HistogramRepa
can be constructed from a Histogram
,
systemsHistogramsHistogramRepa :: System -> Histogram -> Maybe HistogramRepa
systemsHistogramRepasHistogram :: System -> HistogramRepa -> Maybe Histogram
For example,
let aaar uu aa = fromJust $ systemsHistogramsHistogramRepa uu aa
let araa uu rr = fromJust $ systemsHistogramRepasHistogram uu rr
let aa = regdiag 2 2
rp $ aa
"{({(1,1),(2,1)},1 % 1),({(1,2),(2,2)},1 % 1)}"
aa
Histogram (fromList [(State (fromList [(VarInt 1,ValInt 1),(VarInt 2,ValInt 1)]),1 % 1),(State (fromList [(VarInt 1,ValInt 2),(VarInt 2,ValInt 2)]),1 % 1)])
let ar = aaar (sys aa) aa
ar
HistogramRepa {histogramRepasVectorVar = [VarInt 1,VarInt 2], histogramRepasMapVarInt = fromList [(VarInt 1,0),(VarInt 2,1)], histogramRepasArray = AUnboxed [2,2] [1.0,0.0,0.0,1.0]}
rp $ araa (sys aa) ar
"{({(1,1),(2,1)},1 % 1),({(1,1),(2,2)},0 % 1),({(1,2),(2,1)},0 % 1),({(1,2),(2,2)},1 % 1)}"
trim (araa (sys aa) ar) == aa
True
A HistogramRepa
consists of (i) a bijective map between tuple position and variable, histogramRepasVectorVar
, implemented as a vector, (ii) the lazy inverse of this map, histogramRepasMapVarInt
, and (iii) the multi-dimensional unboxed array of Double
, histogramRepasArray
. For example
:t histogramRepasVectorVar ar
histogramRepasVectorVar ar :: V.Vector Variable
histogramRepasVectorVar ar
[VarInt 1,VarInt 2]
:t histogramRepasMapVarInt ar
histogramRepasMapVarInt ar :: Map.Map Variable Int
histogramRepasMapVarInt ar
fromList [(VarInt 1,0),(VarInt 2,1)]
:t histogramRepasArray ar
histogramRepasArray ar :: RB.Array R.U VShape Double
histogramRepasArray ar
AUnboxed [2,2] [1.0,0.0,0.0,1.0]
The VShape
type is defined in module AlignmentRepaVShape
as an unboxed vector of integers,
type VShape = Vector Int
VShape
is an instance of typeclass Shape
,
instance Shape VShape where
...
toIndex !vv1 !vv2
...
fromIndex !vv !n
...
VShape
defines the multi-dimensional shape polymorphism in functions toIndex
and fromIndex
which convert to and from index integers given a tuple of valencies and a tuple of integal values. The shape of the histogram is obtained
R.extent $ histogramRepasArray ar
[2,2]
The array can be indexed
histogramRepasArray ar R.! UV.fromList [0,0]
1.0
histogramRepasArray ar R.! UV.fromList [0,1]
0.0
Like Histogram
, HistogramRepa
can be reduced,
setVarsHistogramRepasReduce :: Set.Set Variable -> HistogramRepa -> HistogramRepa
For example,
let arred aa vv = setVarsHistogramRepasReduce vv aa
ar `arred` Set.singleton (VarInt 2)
HistogramRepa {histogramRepasVectorVar = [VarInt 2], histogramRepasMapVarInt = fromList [(VarInt 2,0)], histogramRepasArray = AUnboxed [2] [1.0,1.0]}
ar `arred` Set.empty
HistogramRepa {histogramRepasVectorVar = [], histogramRepasMapVarInt = fromList [], histogramRepasArray = AUnboxed [] [2.0]}
The independent, $A^{\mathrm{X}}$, has an intermediate representation in terms of a vector of its normalised perimeters, $\{\hat{A}\%\{w\} : w \in V\}$. Module AlignmentRepa
defines type HistogramRepaRed
,
data HistogramRepaRed = HistogramRepaRed {
histogramRepaRedsVectorVar :: !(V.Vector Variable),
histogramRepaRedsMapVarInt :: Map.Map Variable Int,
histogramRepaRedsShape :: !VShape,
histogramRepaRedsVectorArray :: !(V.Vector (UV.Vector Double))}
Instead of an array, histogramRepasArray
, the HistogramRepaRed
has a vector of unboxed vectors of Double
representing the normalised reductions to each of the variables, histogramRepaRedsVectorArray
,
histogramRepasRed_u :: Double -> HistogramRepa -> HistogramRepaRed
For example,
let arpr = histogramRepasRed_u
histogramRepaRedsVectorArray $ arpr 2 ar
[[0.5,0.5],[0.5,0.5]]
Given the HistogramRepaRed
the independent may be calculated,
histogramRepaRedsIndependent :: Double -> HistogramRepaRed -> HistogramRepa
For example,
let prind = histogramRepaRedsIndependent
araa (sys aa) (prind 2 (arpr 2 ar)) == ind aa
True
Often a histogram and its shuffle are processed together, so module AlignmentRepa
also defines type HistogramRepaVec
which implements a vector of congruent histograms each in array histogram representation. That is, the size and set of variables are the shared by all of the histograms,
data HistogramRepaVec = HistogramRepaVec {
histogramRepaVecsVectorVar :: !(V.Vector Variable),
histogramRepaVecsMapVarInt :: Map.Map Variable Int,
histogramRepaVecsSize :: !Double,
histogramRepaVecsShape :: !VShape,
histogramRepaVecsArray :: !(V.Vector (UV.Vector Double))}
Similarly, module AlignmentRepa
also defines a vector of perimeters, type HistogramRepaRedVec
,
data HistogramRepaRedVec = HistogramRepaRedVec {
histogramRepaRedVecsVectorVar :: !(V.Vector Variable),
histogramRepaRedVecsMapVarInt :: Map.Map Variable Int,
histogramRepaRedVecsSize :: !Double,
histogramRepaRedVecsShape :: !VShape,
histogramRepaRedVecsVectorArray :: !(V.Vector (V.Vector (UV.Vector Double)))}
History and HistoryRepa
Histories are defined in the overview in section ‘States, histories and histograms’ P8 and in the paper in section ‘Histories’ P92. The discussion of the Haskell implementation of Histories is in the Haskell implementation of the Overview.
The set of histories is a subset of the state valued functions of event identifiers, $\mathcal{H} \subset \mathcal{X} \to \mathcal{S}$.
The History
type is defined in module Alignment
with a Map.Map
from Id
to State
,
newtype History = History (Map.Map Id State)
This set-theoretic implementation is a poset binary map representation.
Section ‘Computation of histograms’ P406 of the paper discusses the list representation of histograms. Here the histogram, $A \in \mathcal{S} \to \mathbf{Q}_{\geq 0}$, is represented as a vector of pairs of the state and count, $\mathcal{L}(\mathbf{N}^n \times \mathbf{Q}_{\geq 0})$, where a state $S \in A^{\mathrm{S}}$ is represented in terms of a vector of length $n$ consisting of integral values, $\{u : (w,u) \in S\}^n \subset \mathcal{L}(\mathbf{N})$.
Similarly, a history $H \in \mathcal{H}$ can be represented as a list of the states, $\mathrm{ran}(H) \subset \mathcal{S}$, in a two dimensional array of integral values, $\mathbf{N}^{zn}$, of size $zn$, where $z = |H|$. The literal event identifiers, $\mathrm{dom}(H) \subset \mathcal{X}$, are dropped and are encoded instead by the order of the states in the vector.
The module AlignmentRepa
defines type HistoryRepa
in terms of the two-dimensional array,
data HistoryRepa = HistoryRepa {
historyRepasVectorVar :: !(V.Vector Variable),
historyRepasMapVarInt :: Map.Map Variable Int,
historyRepasShape :: !VShape,
historyRepasArray :: !(Array U DIM2 Int)}
A HistoryRepa
can be constructed from a History
,
systemsHistoriesHistoryRepa :: System -> History -> Maybe HistoryRepa
For example,
let hhhr uu hh = fromJust $ systemsHistoriesHistoryRepa uu hh
let hrhh uu hr = fromJust $ systemsHistoryRepasHistory_u uu hr
let aahr aa = hhhr (sys aa) $ aahh aa
let aa = regdiag 2 2
rp $ aa
"{({(1,1),(2,1)},1 % 1),({(1,2),(2,2)},1 % 1)}"
let hr = aahr aa
hr
HistoryRepa {historyRepasVectorVar = [VarInt 1,VarInt 2], historyRepasMapVarInt = fromList [(VarInt 1,0),(VarInt 2,1)], historyRepasShape = [2,2], historyRepasArray = AUnboxed ((Z :. 2) :. 2) [0,1,0,1]}
A HistoryRepa
consists of (i) a bijective map between tuple position and variable, historyRepasVectorVar
, (ii) the lazy inverse of this map, historyRepasMapVarInt
, (iii) the shape, historyRepasShape
, and (iv) the two-dimensional unboxed array of Int
, historyRepasArray
. For example
historyRepasVectorVar hr
[VarInt 1,VarInt 2]
historyRepasMapVarInt hr
fromList [(VarInt 1,0),(VarInt 2,1)]
historyRepasShape hr
[2,2]
historyRepasArray hr
AUnboxed ((Z :. 2) :. 2) [0,1,0,1]
A HistoryRepa
can also be constructed from lists of lists of integers,
systemsListVariablesListsListsHistoryRepa :: System -> [Variable] -> [[Int]] -> Maybe HistoryRepa
historyRepasListsList :: HistoryRepa -> [[Int]]
For example,
let aa = regcart 3 2
rpln $ aall $ aa
"({(1,1),(2,1)},1 % 1)"
"({(1,1),(2,2)},1 % 1)"
"({(1,1),(2,3)},1 % 1)"
"({(1,2),(2,1)},1 % 1)"
"({(1,2),(2,2)},1 % 1)"
"({(1,2),(2,3)},1 % 1)"
"({(1,3),(2,1)},1 % 1)"
"({(1,3),(2,2)},1 % 1)"
"({(1,3),(2,3)},1 % 1)"
let hr = aahr aa
historyRepasVectorVar hr
[VarInt 1,VarInt 2]
historyRepasArray hr
AUnboxed ((Z :. 2) :. 9) [0,0,0,1,1,1,2,2,2,0,1,2,0,1,2,0,1,2]
historyRepasListsList hr
[[0,0],[0,1],[0,2],[1,0],[1,1],[1,2],[2,0],[2,1],[2,2]]
let uu = sys aa
let hr' = fromJust $ systemsListVariablesListsListsHistoryRepa uu [VarInt 1,VarInt 2] [[0,0],[0,1],[0,2],[1,0],[1,1],[1,2],[2,0],[2,1],[2,2]]
hr' == hr
True
rpln $ aall $ hhaa $ hrhh uu $ hr'
"({(1,1),(2,1)},1 % 1)"
"({(1,1),(2,2)},1 % 1)"
"({(1,1),(2,3)},1 % 1)"
"({(1,2),(2,1)},1 % 1)"
"({(1,2),(2,2)},1 % 1)"
"({(1,2),(2,3)},1 % 1)"
"({(1,3),(2,1)},1 % 1)"
"({(1,3),(2,2)},1 % 1)"
"({(1,3),(2,3)},1 % 1)"
Given a list of event identifier positions, a subset of events or a slice of a HistoryRepa
may be selected,
eventsHistoryRepasHistoryRepaSelection :: [Int] -> HistoryRepa -> HistoryRepa
For example,
rpln $ aall $ hhaa $ hrhh uu $ eventsHistoryRepasHistoryRepaSelection [0] hr
"({(1,1),(2,1)},1 % 1)"
rpln $ aall $ hhaa $ hrhh uu $ eventsHistoryRepasHistoryRepaSelection [0,4,8] hr
"({(1,1),(2,1)},1 % 1)"
"({(1,2),(2,2)},1 % 1)"
"({(1,3),(2,3)},1 % 1)"
rpln $ aall $ hhaa $ hrhh uu $ eventsHistoryRepasHistoryRepaSelection [0..8] hr
"({(1,1),(2,1)},1 % 1)"
"({(1,1),(2,2)},1 % 1)"
"({(1,1),(2,3)},1 % 1)"
"({(1,2),(2,1)},1 % 1)"
"({(1,2),(2,2)},1 % 1)"
"({(1,2),(2,3)},1 % 1)"
"({(1,3),(2,1)},1 % 1)"
"({(1,3),(2,2)},1 % 1)"
"({(1,3),(2,3)},1 % 1)"
A HistoryRepa
can be reduced to another HistoryRepa
,
setVarsHistoryRepasHistoryRepaReduced :: Set.Set Variable -> HistoryRepa -> HistoryRepa
For example,
let hrredhr hh vv = setVarsHistoryRepasHistoryRepaReduced (Set.fromList vv) hh
rpln $ aall $ hhaa $ hrhh uu $ hr `hrredhr` [VarInt 1, VarInt 2]
"({(1,1),(2,1)},1 % 1)"
"({(1,1),(2,2)},1 % 1)"
"({(1,1),(2,3)},1 % 1)"
"({(1,2),(2,1)},1 % 1)"
"({(1,2),(2,2)},1 % 1)"
"({(1,2),(2,3)},1 % 1)"
"({(1,3),(2,1)},1 % 1)"
"({(1,3),(2,2)},1 % 1)"
"({(1,3),(2,3)},1 % 1)"
rpln $ aall $ hhaa $ hrhh uu $ hr `hrredhr` [VarInt 1]
"({(1,1)},3 % 1)"
"({(1,2)},3 % 1)"
"({(1,3)},3 % 1)"
rpln $ aall $ hhaa $ hrhh uu $ hr `hrredhr` [VarInt 2]
"({(2,1)},3 % 1)"
"({(2,2)},3 % 1)"
"({(2,3)},3 % 1)"
rpln $ aall $ hhaa $ hrhh uu $ hr `hrredhr` []
"({},9 % 1)"
A HistoryRepa
can be reduced to a HistogramRepa
,
setVarsHistoryRepasReduce :: Double -> Set.Set Variable -> HistoryRepa -> HistogramRepa
For example,
let hrred hh vv = setVarsHistoryRepasReduce 1 (Set.fromList vv) hh
rpln $ aall $ araa uu $ hr `hrred` [VarInt 1, VarInt 2]
"({(1,1),(2,1)},1 % 1)"
"({(1,1),(2,2)},1 % 1)"
"({(1,1),(2,3)},1 % 1)"
"({(1,2),(2,1)},1 % 1)"
"({(1,2),(2,2)},1 % 1)"
"({(1,2),(2,3)},1 % 1)"
"({(1,3),(2,1)},1 % 1)"
"({(1,3),(2,2)},1 % 1)"
"({(1,3),(2,3)},1 % 1)"
rpln $ aall $ araa uu $ hr `hrred` [VarInt 1]
"({(1,1)},3 % 1)"
"({(1,2)},3 % 1)"
"({(1,3)},3 % 1)"
rpln $ aall $ araa uu $ hr `hrred` [VarInt 2]
"({(2,1)},3 % 1)"
"({(2,2)},3 % 1)"
"({(2,3)},3 % 1)"
rpln $ aall $ araa uu $ hr `hrred` []
"({},9 % 1)"
The vector of its normalised perimeters may be obtained from the HistoryRepa
,
historyRepasRed :: HistoryRepa -> HistogramRepaRed
For example,
let hrhx = historyRepasRed
histogramRepaRedsVectorArray $ hrhx $ hr
[[0.3333333333333333,0.3333333333333333,0.3333333333333333],[0.3333333333333333,0.3333333333333333,0.3333333333333333]]
histogramRepaRedsVectorArray $ hrhx $ hr `hrredhr` [VarInt 1]
[[0.3333333333333333,0.3333333333333333,0.3333333333333333]]
histogramRepaRedsVectorArray $ hrhx $ hr `hrredhr` []
[]
The vector of its normalised perimeters may be obtained from the HistoryRepa
for a subset of the variables,
setVarsHistoryRepasRed :: Set.Set Variable -> HistoryRepa -> HistogramRepaRed
For example,
let hrredhx hh vv = setVarsHistoryRepasRed (Set.fromList vv) hh
histogramRepaRedsVectorArray $ hr `hrredhx` [VarInt 1, VarInt 2]
[[0.3333333333333333,0.3333333333333333,0.3333333333333333],[0.3333333333333333,0.3333333333333333,0.3333333333333333]]
histogramRepaRedsVectorArray $ hr `hrredhx` [VarInt 1]
[[0.3333333333333333,0.3333333333333333,0.3333333333333333]]
histogramRepaRedsVectorArray $ hr `hrredhx` []
[]
Transform and TransformRepa
Transforms are defined in the overview in section ‘Transforms’ P35 and in the paper in section ‘Transforms’ P111. The discussion of the Haskell implementation of Transforms is in the Haskell implementation of the Overview.
The set of all transforms is $\mathcal{T} := \{(X,W) : X \in \mathcal{A},~W \subseteq \mathrm{vars}(X)\}$.
Given a histogram $X \in \mathcal{A}$ and a subset of its variables $W \subseteq \mathrm{vars}(X)$, the pair $T = (X,W)$ forms a transform.
The Transform
type is defined in module Alignment
with a pair of a Histogram
and a Variable
set,
newtype Transform = Transform (Histogram, (Set.Set Variable))
The implementation of the Histogram
is a poset binary map representation.
Given a histogram $A \in \mathcal{A}$, the multiplication of the histogram, $A$, by the transform $T \in \mathcal{T}$ equals the multiplication of the histogram, $A$, by the transform histogram $X = \mathrm{his}(T)$ followed by the reduction to the derived variables $W = \mathrm{der}(T)$, $A * T := A * X~\%~W$. Section ‘Computation of histograms’ P407 discusses the reduction and multiplication of histograms. Then the discussion goes on (P408) to consider the multiplication to two histograms $A * B$ where the second histogram, $B$, is the histogram of some one functional transform $T \in \mathcal{T}_{U,\mathrm{f},1}$. This multiplication can be thought of as adding variables to $A$ without changing the cardinality or the counts. The computation of the application need only remap the states without modifying the counts however they are represented. No multiplications nor additions are computed. See section ‘Computation of the application of a transform’ P409.
Consider the case where the one functional transform, $T$, has a single derived variable $\{w\} = \mathrm{der}(T)$. The histogram, $X$, may then be represented as an array of the derived values, $U_w^v$, of size equal to the underlying volume, $v$.
The module AlignmentRepa
defines type TransformRepa
in terms of a multi-dimensional array of the integral values of the derived variable,
data TransformRepa = TransformRepa {
transformRepasVectorVar :: !(V.Vector Variable),
transformRepasMapVarInt :: Map.Map Variable Int,
transformRepasVarDerived :: !Variable,
transformRepasValency :: !Int,
transformRepasArray :: !(Array U VShape Int)}
A TransformRepa
can be constructed from a Transform
,
systemsTransformsTransformRepa :: System -> Transform -> Maybe TransformRepa
For example,
let cdtt pp ll = trans (cdaa ll `cdtp` pp) (Set.singleton (VarInt (last pp)))
let tt = cdtt [1,2,3] [[1,1,1],[1,2,1],[1,3,1],[2,1,2],[2,2,2],[2,3,2],[3,1,2],[3,2,2],[3,3,1]]
rpln $ aall $ ttaa tt
"({(1,1),(2,1),(3,1)},1 % 1)"
"({(1,1),(2,2),(3,1)},1 % 1)"
"({(1,1),(2,3),(3,1)},1 % 1)"
"({(1,2),(2,1),(3,2)},1 % 1)"
"({(1,2),(2,2),(3,2)},1 % 1)"
"({(1,2),(2,3),(3,2)},1 % 1)"
"({(1,3),(2,1),(3,2)},1 % 1)"
"({(1,3),(2,2),(3,2)},1 % 1)"
"({(1,3),(2,3),(3,1)},1 % 1)"
let tttr tt = fromJust $ systemsTransformsTransformRepa (sys (ttaa tt)) tt
let tr = tttr tt
tr
TransformRepa {transformRepasVectorVar = [VarInt 1,VarInt 2], transformRepasMapVarInt = fromList [(VarInt 1,0),(VarInt 2,1)], transformRepasVarDerived = VarInt 3, transformRepasValency = 2, transformRepasArray = AUnboxed [3,3] [0,0,0,1,1,1,1,1,0]}
A TransformRepa
consists of (i) a bijective map between tuple position and variable, transformRepasVectorVar
, (ii) the lazy inverse of this map, transformRepasMapVarInt
, (iii) the derived variable, transformRepasVarDerived
, (iv) the derived valency, transformRepasValency
and (v) the multi-dimensional unboxed array of Int
, transformRepasArray
. For example
transformRepasVectorVar tr
[VarInt 1,VarInt 2]
transformRepasMapVarInt tr
fromList [(VarInt 1,0),(VarInt 2,1)]
transformRepasVarDerived tr
VarInt 3
transformRepasValency tr
2
transformRepasArray tr
AUnboxed [3,3] [0,0,0,1,1,1,1,1,0]
A TransformRepa
may be applied to a HistoryRepa
to generate a HistoryRepa
reduced to the derived variable,
historyRepasTransformRepasApply_u :: HistoryRepa -> TransformRepa -> HistoryRepa
For example,
let aa = regcart 3 2
rpln $ aall $ aa
"({(1,1),(2,1)},1 % 1)"
"({(1,1),(2,2)},1 % 1)"
"({(1,1),(2,3)},1 % 1)"
"({(1,2),(2,1)},1 % 1)"
"({(1,2),(2,2)},1 % 1)"
"({(1,2),(2,3)},1 % 1)"
"({(1,3),(2,1)},1 % 1)"
"({(1,3),(2,2)},1 % 1)"
"({(1,3),(2,3)},1 % 1)"
let hr = aahr aa
let trmul = historyRepasTransformRepasApply_u
rpln $ aall $ hhaa $ hrhh (sysreg 3 3) $ hr `trmul` tr
"({(3,1)},4 % 1)"
"({(3,2)},5 % 1)"
let aa = regdiag 3 2
rpln $ aall $ aa
"({(1,1),(2,1)},1 % 1)"
"({(1,2),(2,2)},1 % 1)"
"({(1,3),(2,3)},1 % 1)"
let hr = aahr aa
rpln $ aall $ hhaa $ hrhh (sysreg 3 3) $ hr `trmul` tr
"({(3,1)},2 % 1)"
"({(3,2)},1 % 1)"
Section ‘Computation of functional definition sets’ P408 discusses the application of a one functional definition set $F \in \mathcal{F}_{U,1}$ of one functional transforms to a histogram, $A * F$. The sequence of the application of the transforms can be ordered by layer so that the cardinality of the intermediate histogram remains that of the given histogram, $|A|$.
A vector of TransformRepa
can be ordered by layer,
listVariablesListTransformRepasSort :: V.Vector Variable -> V.Vector TransformRepa -> V.Vector TransformRepa
This sort followed by the application in sequence allows the application of a fud consisting of an arbitrary vector of TransformRepa
to a HistoryRepa
. Note that the application is really a multiply because the resultant HistoryRepa
is not reduced to the fud derived variables,
historyRepasListTransformRepasApply :: HistoryRepa -> V.Vector TransformRepa -> HistoryRepa
For example,
let tt1 = cdtt [1,3] [[1,1],[2,1],[3,2]]
let tt2 = cdtt [1,4] [[1,1],[2,2],[3,2]]
let tt3 = cdtt [3,4,5] [[1,1,1],[1,2,1],[2,1,1],[2,2,2]]
let ltrmul hr ll = historyRepasListTransformRepasApply hr (V.fromList ll)
rpln $ aall $ hhaa $ hrhh (sysreg 3 5) $ hr `ltrmul` [tttr tt3,tttr tt1,tttr tt2]
"({(1,1),(2,1),(3,1),(4,1),(5,1)},1 % 1)"
"({(1,2),(2,2),(3,1),(4,2),(5,1)},1 % 1)"
"({(1,3),(2,3),(3,2),(4,2),(5,2)},1 % 1)"
Given a fud, the construction of the vector of TransformRepa
and its application to a HistoryRepa
is wrapped up as
systemsFudsHistoryRepasMultiply :: System -> Fud -> HistoryRepa -> Maybe HistoryRepa
For example,
let frmul hr ff = fromJust $ systemsFudsHistoryRepasMultiply (fsys ff) ff hr
let ff = llff [tt3,tt1,tt2]
rpln $ aall $ hhaa $ hrhh (sysreg 3 5) $ hr `frmul` ff
"({(1,1),(2,1),(3,1),(4,1),(5,1)},1 % 1)"
"({(1,2),(2,2),(3,1),(4,2),(5,1)},1 % 1)"
"({(1,3),(2,3),(3,2),(4,2),(5,2)},1 % 1)"
Similarly, given a fud decomposition the application to a HistoryRepa
results in a tree of HistoryRepa
reduced to node fud derived variables,
systemsDecompFudsHistoryRepasMultiply :: System -> DecompFud -> HistoryRepa -> Tree ((State,Fud),HistoryRepa)