Transforms
Python implementation of the Overview/Transforms
Sections
Definition
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 with a pair of a Histogram
and a Variable
set,
newtype Transform = Transform (Histogram, (Set.Set Variable))
A Transform
is constructed from a Histogram
and a set of Variable
,
histogramsSetVarsTransform :: Histogram -> Set.Set Variable -> Maybe Transform
Consider the deck of cards example,
def lluu(ll):
return listsSystem([(v,sset(ww)) for (v,ww) in ll])
[suit,rank] = map(VarStr, ["suit","rank"])
[hearts,clubs,diamonds,spades] = map(ValStr, ["hearts","clubs","diamonds","spades"])
[jack,queen,king,ace] = map(ValStr, ["J","Q","K","A"])
uu = lluu([
(suit, [hearts,clubs,diamonds,spades]),
(rank, [jack,queen,king,ace] + list(map(ValInt,range(2,10+1))))])
vv = sset([suit, rank])
uu
# {(rank, {A, J, K, Q, 2, 3, 4, 5, 6, 7, 8, 9, 10}), (suit, {clubs, diamonds, hearts, spades})}
vv
# {rank, suit}
aa = unit(cart(uu,vv))
rpln(aall(aa))
# ({(rank, A), (suit, clubs)}, 1 % 1)
# ({(rank, A), (suit, diamonds)}, 1 % 1)
# ({(rank, A), (suit, hearts)}, 1 % 1)
# ({(rank, A), (suit, spades)}, 1 % 1)
# ({(rank, J), (suit, clubs)}, 1 % 1)
# ({(rank, J), (suit, diamonds)}, 1 % 1)
# ...
# ({(rank, 9), (suit, hearts)}, 1 % 1)
# ({(rank, 9), (suit, spades)}, 1 % 1)
# ({(rank, 10), (suit, clubs)}, 1 % 1)
# ({(rank, 10), (suit, diamonds)}, 1 % 1)
# ({(rank, 10), (suit, hearts)}, 1 % 1)
# ({(rank, 10), (suit, spades)}, 1 % 1)
A transform can be constructed from a histogram $X$ relating the suit to the colour,
colour = VarStr("colour")
red = ValStr("red")
black = ValStr("black")
xx = llaa([(llss([(suit, u),(colour, w)]),1) for (u,w) in [(hearts, red), (clubs, black), (diamonds, red), (spades, black)]])
rpln(aall(xx))
# ({(colour, black), (suit, clubs)}, 1 % 1)
# ({(colour, black), (suit, spades)}, 1 % 1)
# ({(colour, red), (suit, diamonds)}, 1 % 1)
# ({(colour, red), (suit, hearts)}, 1 % 1)
ww = sset([colour])
trans = histogramsSetVarsTransform
trans(xx,ww)
# ({({(colour, black), (suit, clubs)}, 1 % 1), ({(colour, black), (suit, spades)}, 1 % 1), ({(colour, red), (suit, diamonds)}, 1 % 1), ({(colour, red), (suit, hearts)}, 1 % 1)}, {colour})
The variables, $W$, are the derived variables. The complement $K = \mathrm{vars}(X) \setminus W$ are the underlying variables,
ww
# {colour}
kk = vars(xx) - ww
kk
# {suit}
The set of all transforms is \[ \begin{eqnarray} \mathcal{T} &:=& \{(X,W) : X \in \mathcal{A},~W \subseteq \mathrm{vars}(X)\} \end{eqnarray} \] The transform histogram is $X = \mathrm{his}(T)$. The transform derived is $W = \mathrm{der}(T)$. The transform underlying is $K = \mathrm{und}(T)$,
transformsHistogram :: Transform -> Histogram
transformsUnderlying :: Transform -> Set.Set Variable
transformsDerived :: Transform -> Set.Set Variable
For example,
ttaa = transformsHistogram
und = transformsUnderlying
der = transformsDerived
tt = trans(xx,ww)
ttaa(tt) == xx
# True
und(tt) == kk
# True
der(tt) == ww
# True
The null transform is $(X,\emptyset)$,
histogramsTransformNull :: Histogram -> Transform
For example,
null = histogramsTransformNull
ttaa(null(aa)) == aa
# True
und(null(aa)) == vars(aa)
# True
der(null(aa)) == sset()
# True
The full transform is $(X,\mathrm{vars}(X))$,
histogramsTransformDisjoint :: Histogram -> Transform
For example,
full = histogramsTransformDisjoint
ttaa(full(aa)) == aa
# True
und(full(aa)) == sset()
# True
der(full(aa)) == vars(aa)
# True
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)$, \[ \begin{eqnarray} A * T~=~A * (X,W) &:=& A * X~\%~W \end{eqnarray} \]
transformsHistogramsApply :: Transform -> Histogram -> Histogram
For example,
def tmul(aa,tt):
return transformsHistogramsApply(tt,aa)
rpln(aall(tmul(aa,tt)))
# ({(colour, black)}, 26 % 1)
# ({(colour, red)}, 26 % 1)
tmul(aa,tt) == ared(mul(aa,xx),ww)
# True
If the histogram variables are a superset of the underlying variables, $\mathrm{und}(T) \subseteq \mathrm{vars}(A)$,
und(tt).issubset(vars(aa))
# True
then the histogram, $A$, is called the underlying histogram and the multiplication, $A * T$, is called the derived histogram. The derived histogram variables equals the derived variables, $\mathrm{vars}(A*T) = \mathrm{der}(T)$.
If the set of underlying variables of a transform is a proper subset of the set of histogram variables, $K \subset V$, the transform can be expanded by multiplying its histogram by the cartesian histogram of the set of remaining variables, $V \setminus K$. In the deck of cards example, the set of underlying variables, $K$, is a singleton consisting of the suit,
und(tt)
# {suit}
The transform is expanded to the histogram variables, $V$, by multiplying by the cartesian histogram for the rank,
vk = vv - kk
vk
# {rank}
ttv = trans(mul(ttaa(tt),unit(cart(uu,vk))), der(tt))
und(ttv)
# {rank, suit}
und(ttv) == vv
# True
The set of derived variables of the expanded transform is unchanged, so the derived histogram is unchanged,
der(ttv) == der(tt)
# True
tmul(aa,ttv) == tmul(aa,tt)
# True
The application of the null transform of the cartesian is the scalar, $A * (V^{\mathrm{C}},\emptyset) = A \% \emptyset = \mathrm{scalar}(\mathrm{size}(A))$, where $V = \mathrm{vars}(A)$,
vvc = unit(cart(uu,vv))
tmul(aa,null(vvc)) == ared(aa,sset())
# True
The application of the full transform of the cartesian is the histogram, $A * (V^{\mathrm{C}},V) = A \% V = A$,
tmul(aa,full(vvc)) == aa
# True
Formal and Abstract
Given a histogram $A \in \mathcal{A}$ and a transform $T \in \mathcal{T}$, the formal histogram is defined as the independent derived, $A^{\mathrm{X}} * T$. In the case of the deck of cards example, the histogram, $A$, is just the cartesian and is already independent. So the formal histogram equals the derived histogram,
rpln(aall(tmul(ind(aa),tt)))
# ({(colour, black)}, 26 % 1)
# ({(colour, red)}, 26 % 1)
tmul(ind(aa),tt) == tmul(aa,tt)
# True
Consider a transform $T’$ with two derived variables constructed on two underlying variables as follows,
tt1 = trans(cdaa([[1,1,1,2],[1,2,1,1],[1,3,1,1],[2,1,2,1],[2,2,2,2],[2,3,2,1],[3,1,2,1],[3,2,2,1],[3,3,1,2]]), sset([VarInt(3), VarInt(4)]))
rpln(aall(ttaa(tt1)))
# ({(1, 1), (2, 1), (3, 1), (4, 2)}, 1 % 1)
# ({(1, 1), (2, 2), (3, 1), (4, 1)}, 1 % 1)
# ({(1, 1), (2, 3), (3, 1), (4, 1)}, 1 % 1)
# ({(1, 2), (2, 1), (3, 2), (4, 1)}, 1 % 1)
# ({(1, 2), (2, 2), (3, 2), (4, 2)}, 1 % 1)
# ({(1, 2), (2, 3), (3, 2), (4, 1)}, 1 % 1)
# ({(1, 3), (2, 1), (3, 2), (4, 1)}, 1 % 1)
# ({(1, 3), (2, 2), (3, 2), (4, 1)}, 1 % 1)
# ({(1, 3), (2, 3), (3, 1), (4, 2)}, 1 % 1)
und(tt1)
# {1, 2}
der(tt1)
# {3, 4}
rpln(aall(tmul(regcart(3,2),tt1)))
# ({(3, 1), (4, 1)}, 2 % 1)
# ({(3, 1), (4, 2)}, 2 % 1)
# ({(3, 2), (4, 1)}, 4 % 1)
# ({(3, 2), (4, 2)}, 1 % 1)
rpln(aall(tmul(regdiag(3,2),tt1)))
# ({(3, 1), (4, 2)}, 2 % 1)
# ({(3, 2), (4, 2)}, 1 % 1)
Now the formal histogram of a regular diagonal underlying differs from the derived histogram,
rpln(aall(tmul(ind(regdiag(3,2)),tt1)))
# ({(3, 1), (4, 1)}, 2 % 3)
# ({(3, 1), (4, 2)}, 2 % 3)
# ({(3, 2), (4, 1)}, 4 % 3)
# ({(3, 2), (4, 2)}, 1 % 3)
tmul(ind(regdiag(3,2)),tt1) == tmul(regdiag(3,2),tt1)
# False
tmul(ind(regcart(3,2)),tt1) == tmul(regcart(3,2),tt1)
# True
The abstract histogram is defined as the derived independent, $(A * T)^{\mathrm{X}}$. In the case of the deck of cards example, the transform, $T$, has only one derived variable and so the derived histogram is already independent,
rpln(aall(ind(tmul(aa,tt))))
# ({(colour, black)}, 26 % 1)
# ({(colour, red)}, 26 % 1)
ind(tmul(aa,tt)) == tmul(aa,tt)
# True
In the case of transform $T’$, however, the abstract histogram of a regular cartesian underlying differs from the derived histogram,
rpln(aall(ind(tmul(regcart(3,2),tt1))))
# ({(3, 1), (4, 1)}, 8 % 3)
# ({(3, 1), (4, 2)}, 4 % 3)
# ({(3, 2), (4, 1)}, 10 % 3)
# ({(3, 2), (4, 2)}, 5 % 3)
ind(tmul(regcart(3,2),tt1)) == tmul(regcart(3,2),tt1)
# False
ind(tmul(regdiag(3,2),tt1)) == tmul(regdiag(3,2),tt1)
# True
In the case where the formal and abstract are equal, $A^{\mathrm{X}} * T = (A * T)^{\mathrm{X}}$, the abstract equals the independent abstract, $(A * T)^{\mathrm{X}} = A^{\mathrm{X}} * T = (A^{\mathrm{X}} * T)^{\mathrm{X}}$, and so only depends on the independent, $A^{\mathrm{X}}$, not on the histogram, $A$. The formal equals the formal independent, $A^{\mathrm{X}} * T = (A * T)^{\mathrm{X}} = (A^{\mathrm{X}} * T)^{\mathrm{X}}$, and so is itself independent. For example, when the transform $T’$ has only one derived variable and varies with only one of the underlying variables,
tt1 = trans(cdaa([[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,2]]), sset([VarInt(3)]))
rpln(aall(ttaa(tt1)))
# ({(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, 2)}, 1 % 1)
rpln(aall(tmul(regcart(3,2),tt1)))
# ({(3, 1)}, 3 % 1)
# ({(3, 2)}, 6 % 1)
tmul(ind(regcart(3,2)),tt1) == ind(tmul(regcart(3,2),tt1))
# True
rpln(aall(tmul(regdiag(3,2),tt1)))
# ({(3, 1)}, 1 % 1)
# ({(3, 2)}, 2 % 1)
tmul(ind(regdiag(3,2)),tt1) == ind(tmul(regdiag(3,2),tt1))
# True
In the case where $T’$ varies with both of the underlying variables, formal-abstract equivalence holds only for the cartesian,
tt1 = trans(cdaa([[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]]), sset([VarInt(3)]))
rpln(aall(ttaa(tt1)))
# ({(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)
tmul(ind(regcart(3,2)),tt1) == ind(tmul(regcart(3,2),tt1))
# True
tmul(ind(regdiag(3,2)),tt1) == ind(tmul(regdiag(3,2),tt1))
# False
Functional transforms
A transform $T \in \mathcal{T}$ is functional if there is a causal relation between the underlying variables $K = \mathrm{und}(T)$ and the derived variables $W = \mathrm{der}(T)$, \[ \begin{eqnarray} \mathrm{split}(K,X^{\mathrm{FS}}) &\in& K^{\mathrm{CS}} \to W^{\mathrm{CS}} \end{eqnarray} \] where $X=\mathrm{his}(T)$. In the deck of cards example,
xx == ttaa(tt)
# True
rpln(aall(xx))
# ({(colour, black), (suit, clubs)}, 1 % 1)
# ({(colour, black), (suit, spades)}, 1 % 1)
# ({(colour, red), (suit, diamonds)}, 1 % 1)
# ({(colour, red), (suit, hearts)}, 1 % 1)
kk
# {suit}
ww
# {colour}
ssplit = setVarsSetStatesSplit
rpln(ssplit(kk,(states(xx))))
# ({(suit, clubs)}, {(colour, black)})
# ({(suit, diamonds)}, {(colour, red)})
# ({(suit, hearts)}, {(colour, red)})
# ({(suit, spades)}, {(colour, black)})
iscausal = histogramsIsCausal
iscausal(xx)
# True
The expanded transform is still causal,
rpln(ssplit(vv,(states(ttaa(ttv)))))
# ({(rank, A), (suit, clubs)}, {(colour, black)})
# ({(rank, A), (suit, diamonds)}, {(colour, red)})
# ({(rank, A), (suit, hearts)}, {(colour, red)})
# ({(rank, A), (suit, spades)}, {(colour, black)})
# ({(rank, J), (suit, clubs)}, {(colour, black)})
# ({(rank, J), (suit, diamonds)}, {(colour, red)})
# ...
# ({(rank, 9), (suit, hearts)}, {(colour, red)})
# ({(rank, 9), (suit, spades)}, {(colour, black)})
# ({(rank, 10), (suit, clubs)}, {(colour, black)})
# ({(rank, 10), (suit, diamonds)}, {(colour, red)})
# ({(rank, 10), (suit, hearts)}, {(colour, red)})
# ({(rank, 10), (suit, spades)}, {(colour, black)})
iscausal(ttaa(ttv))
# True
The set of functional transforms $\mathcal{T}_{\mathrm{f}} \subset \mathcal{T}$ is the subset of all transforms that are causal.
A functional transform $T \in \mathcal{T}_{\mathrm{f}}$ has an inverse, \[ \begin{eqnarray} T^{-1} &:=& \{((S\%K,c), S\%W) : (S,c) \in X\}^{-1} \end{eqnarray} \]
transformsInverse :: Transform -> Map.Map State Histogram
For example,
inv = transformsInverse
rpln(inv(tt))
# ({(colour, black)}, {({(suit, clubs)}, 1 % 1), ({(suit, spades)}, 1 % 1)})
# ({(colour, red)}, {({(suit, diamonds)}, 1 % 1), ({(suit, hearts)}, 1 % 1)})
rpln(inv(ttv))
# ({(colour, black)}, {({(rank, A), (suit, clubs)}, 1 % 1), ..., ({(rank, 10), (suit, spades)}, 1 % 1)})
# ({(colour, red)}, {({(rank, A), (suit, diamonds)}, 1 % 1), ..., ({(rank, 10), (suit, hearts)}, 1 % 1)})
A transform $T$ is one functional in system $U$ if the reduction of the transform histogram to the underlying variables equals the cartesian histogram, $X\%K = K^{\mathrm{C}}$,
ared(xx,kk) == unit(cart(uu,kk))
# True
ared(ttaa(ttv),vv) == unit(cart(uu,vv))
# True
So the causal relation is a derived state valued left total function of underlying state, $\mathrm{split}(K,X^{\mathrm{S}}) \in K^{\mathrm{CS}} :\to W^{\mathrm{CS}}$. The set of one functional transforms $\mathcal{T}_{U,\mathrm{f},1} \subset \mathcal{T}_{\mathrm{f}}$ is \[ \begin{eqnarray} \mathcal{T}_{U,\mathrm{f},1} &=& \{ (\{(S \cup R,1) : (S,R) \in Q\},W) : \\ &&\hspace{5em}K,W \subseteq \mathrm{vars}(U),~K \cap W = \emptyset, ~Q \in K^{\mathrm{CS}} :\to W^{\mathrm{CS}}\} \end{eqnarray} \] The application of a one functional transform to an underlying histogram preserves the size, $\mathrm{size}(A * T) = \mathrm{size}(A)$,
size(tmul(aa,tt)) == size(aa)
# True
size(tmul(aa,ttv)) == size(aa)
# True
The one functional transform inverse is a unit component valued function of derived state, $T^{-1} \in W^{\mathrm{CS}} \to \mathrm{P}(K^{\mathrm{C}})$. That is, the range of the inverse corresponds to a partition of the cartesian states into components, $\mathrm{ran}(T^{-1}) \in \mathrm{B}(K^{\mathrm{C}})$,
[(ss,cc),(rr,dd)] = list(inv(tt).items())
rpln(aall(cc))
# ({(suit, clubs)}, 1 % 1)
# ({(suit, spades)}, 1 % 1)
rpln(aall(dd))
# ({(suit, diamonds)}, 1 % 1)
# ({(suit, hearts)}, 1 % 1)
add(cc,dd) == unit(cart(uu,kk))
# True
and
[(ss,cc),(rr,dd)] = list(inv(ttv).items())
rpln(aall(cc))
# ({(rank, A), (suit, clubs)}, 1 % 1)
# ({(rank, A), (suit, spades)}, 1 % 1)
# ({(rank, J), (suit, clubs)}, 1 % 1)
# ...
# ({(rank, 9), (suit, spades)}, 1 % 1)
# ({(rank, 10), (suit, clubs)}, 1 % 1)
# ({(rank, 10), (suit, spades)}, 1 % 1)
rpln(aall(dd))
# ({(rank, A), (suit, diamonds)}, 1 % 1)
# ({(rank, A), (suit, hearts)}, 1 % 1)
# ({(rank, J), (suit, diamonds)}, 1 % 1)
# ...
# ({(rank, 9), (suit, hearts)}, 1 % 1)
# ({(rank, 10), (suit, diamonds)}, 1 % 1)
# ({(rank, 10), (suit, hearts)}, 1 % 1)
add(cc,dd) == unit(cart(uu,vv))
# True
The application of a one functional transform $T$ to its underlying cartesian $K^{\mathrm{C}}$ is the component cardinality histogram, $K^{\mathrm{C}} * T = \{(R,|C|) : (R,C) \in T^{-1}\}$,
rpln(aall(tmul(unit(cart(uu,kk)),tt)))
# ({(colour, black)}, 2 % 1)
# ({(colour, red)}, 2 % 1)
rpln(aall(tmul(unit(cart(uu,vv)),ttv)))
# ({(colour, black)}, 26 % 1)
# ({(colour, red)}, 26 % 1)
The effective cartesian derived volume is less than or equal to the derived volume, $|(K^{\mathrm{C}} * T)^{\mathrm{F}}| = |T^{-1}| \leq |W^{\mathrm{C}}|$,
len(states(eff(tmul(unit(cart(uu,kk)),tt))))
# 2
len(states(eff(tmul(unit(cart(uu,vv)),ttv))))
# 2
Application to history
A one functional transform $T \in \mathcal{T}_{U,\mathrm{f},1}$ may be applied to a history $H \in \mathcal{H}$ in the underlying variables of the transform, $\mathrm{vars}(H) \supseteq \mathrm{und}(T)$, to construct a derived history, \[ \begin{eqnarray} H * T &:=& \{(x,R) : (x,S) \in H,~\{R\} = (\{S\}^{\mathrm{U}} * T)^{\mathrm{FS}}\} \end{eqnarray} \] The size is unchanged, $|H * T| = |H|$, and the event identifiers are conserved, $\mathrm{dom}(H * T) = \mathrm{dom}(H)$.
transformsHistoriesApply :: Transform -> History -> History
For example,
llhh = listsHistory
hhll = historyToList
hh = llhh([(IdInt(i+1),ss) for (i,ss) in enumerate(cart(uu, vv))])
rpln(hhll(hh))
# (1, {(rank, A), (suit, clubs)})
# (2, {(rank, A), (suit, diamonds)})
# (3, {(rank, A), (suit, hearts)})
# (4, {(rank, A), (suit, spades)})
# (5, {(rank, J), (suit, clubs)})
# (6, {(rank, J), (suit, diamonds)})
# ...
# (47, {(rank, 9), (suit, hearts)})
# (48, {(rank, 9), (suit, spades)})
# (49, {(rank, 10), (suit, clubs)})
# (50, {(rank, 10), (suit, diamonds)})
# (51, {(rank, 10), (suit, hearts)})
# (52, {(rank, 10), (suit, spades)})
def htmul(hh,tt):
return transformsHistoriesApply(tt,hh)
rpln(hhll(htmul(hh,tt)))
# (1, {(colour, black)})
# (2, {(colour, red)})
# (3, {(colour, red)})
# (4, {(colour, black)})
# (5, {(colour, black)})
# (6, {(colour, red)})
# ...
# (47, {(colour, red)})
# (48, {(colour, black)})
# (49, {(colour, black)})
# (50, {(colour, red)})
# (51, {(colour, red)})
# (52, {(colour, black)})
Partition transforms
Given a partition $P \in \mathrm{B}(V^{\mathrm{CS}})$ of the cartesian states of variables $V$, a one functional transform can be constructed. The partition transform is \[ \begin{eqnarray} P^{\mathrm{T}} &:=& (\{(S \cup \{(P,C)\}, 1) : C \in P,~S \in C \}, \{P\}) \end{eqnarray} \]
partitionsTransformVarPartition :: Partition -> Transform
The set of derived variables of the partition transform is a singleton of the partition variable, $\mathrm{der}(P^{\mathrm{T}}) = \{P\}$. The derived volume is the component cardinality, $|\{P\}^{\mathrm{C}}| = |P|$. The underlying variables are the given variables, $\mathrm{und}(P^{\mathrm{T}}) = V$. For example, consider a partition of the deck of cards,
qqpp = setComponentsPartition
ppqq = partitionsSetComponent
c = sset(list(states(vvc))[0:13])
d = sset(list(states(vvc))[13:])
pp = qqpp(sset([c,d]))
len(ppqq(pp))
# 2
[len(ee) for ee in ppqq(pp)]
# [13, 39]
pptt = partitionsTransformVarPartition
und(pptt(pp))
# {rank, suit}
rpln(aall(ared(ttaa(pptt(pp)),und(pptt(pp)))))
# ({(rank, A), (suit, clubs)}, 1 % 1)
# ({(rank, A), (suit, diamonds)}, 1 % 1)
# ({(rank, A), (suit, hearts)}, 1 % 1)
# ({(rank, A), (suit, spades)}, 1 % 1)
# ({(rank, J), (suit, clubs)}, 1 % 1)
# ({(rank, J), (suit, diamonds)}, 1 % 1)
# ...
# ({(rank, 9), (suit, hearts)}, 1 % 1)
# ({(rank, 9), (suit, spades)}, 1 % 1)
# ({(rank, 10), (suit, clubs)}, 1 % 1)
# ({(rank, 10), (suit, diamonds)}, 1 % 1)
# ({(rank, 10), (suit, hearts)}, 1 % 1)
# ({(rank, 10), (suit, spades)}, 1 % 1)
der(pptt(pp)) == sset([VarPartition(pp)])
# True
[q for (ss,q) in aall(tmul(aa,pptt(pp)))]
# [13 % 1, 39 % 1]
The expanded transform in the deck of cards example partitions the cartesian set of states,
[(ss,cc),(rr,dd)] = list(inv(ttv).items())
pp = qqpp(sset([states(cc),states(dd)]))
len(ppqq(pp))
# 2
[len(ee) for ee in ppqq(pp)]
# [26, 26]
und(pptt(pp))
# {rank, suit}
rpln(aall(ared(ttaa(pptt(pp)),und(pptt(pp)))))
# ({(rank, A), (suit, clubs)}, 1 % 1)
# ({(rank, A), (suit, diamonds)}, 1 % 1)
# ({(rank, A), (suit, hearts)}, 1 % 1)
# ({(rank, A), (suit, spades)}, 1 % 1)
# ({(rank, J), (suit, clubs)}, 1 % 1)
# ({(rank, J), (suit, diamonds)}, 1 % 1)
# ...
# ({(rank, 9), (suit, hearts)}, 1 % 1)
# ({(rank, 9), (suit, spades)}, 1 % 1)
# ({(rank, 10), (suit, clubs)}, 1 % 1)
# ({(rank, 10), (suit, diamonds)}, 1 % 1)
# ({(rank, 10), (suit, hearts)}, 1 % 1)
# ({(rank, 10), (suit, spades)}, 1 % 1)
der(pptt(pp)) == sset([VarPartition(pp)])
# True
[q for (ss,q) in aall(tmul(aa,pptt(pp)))]
# [26 % 1, 26 % 1]
The unary partition transform is $T_{\mathrm{u}} = \{V^{\mathrm{CS}}\}^{\mathrm{T}}$,
unary = systemsSetVarsPartitionUnary
uu1 = sysreg(2,2)
pp = unary(uu1,uvars(uu1))
len(ppqq(pp))
# 1
[len(ee) for ee in ppqq(pp)]
# [4]
und(pptt(pp))
# {1, 2}
der(pptt(pp))
# { { { {(1, 1), (2, 1)}, {(1, 1), (2, 2)}, {(1, 2), (2, 1)}, {(1, 2), (2, 2)} } } }
rpln(aall(ared(ttaa(pptt(pp)),und(pptt(pp)))))
# ({(1, 1), (2, 1)}, 1 % 1)
# ({(1, 1), (2, 2)}, 1 % 1)
# ({(1, 2), (2, 1)}, 1 % 1)
# ({(1, 2), (2, 2)}, 1 % 1)
rpln(aall(ttaa(pptt(pp))))
# ({(1, 1), (2, 1), ({ { {(1, 1), (2, 1)}, {(1, 1), (2, 2)}, {(1, 2), (2, 1)}, {(1, 2), (2, 2)} } }, { {(1, 1), (2, 1)}, {(1, 1), (2, 2)}, {(1, 2), (2, 1)}, {(1, 2), (2, 2)} })}, 1 % 1)
# ({(1, 1), (2, 2), ({ { {(1, 1), (2, 1)}, {(1, 1), (2, 2)}, {(1, 2), (2, 1)}, {(1, 2), (2, 2)} } }, { {(1, 1), (2, 1)}, {(1, 1), (2, 2)}, {(1, 2), (2, 1)}, {(1, 2), (2, 2)} })}, 1 % 1)
# ({(1, 2), (2, 1), ({ { {(1, 1), (2, 1)}, {(1, 1), (2, 2)}, {(1, 2), (2, 1)}, {(1, 2), (2, 2)} } }, { {(1, 1), (2, 1)}, {(1, 1), (2, 2)}, {(1, 2), (2, 1)}, {(1, 2), (2, 2)} })}, 1 % 1)
# ({(1, 2), (2, 2), ({ { {(1, 1), (2, 1)}, {(1, 1), (2, 2)}, {(1, 2), (2, 1)}, {(1, 2), (2, 2)} } }, { {(1, 1), (2, 1)}, {(1, 1), (2, 2)}, {(1, 2), (2, 1)}, {(1, 2), (2, 2)} })}, 1 % 1)
The self partition transform is $T_{\mathrm{s}} = V^{\mathrm{CS}\{\}\mathrm{T}}$,
self = systemsSetVarsPartitionSelf
uu1 = sysreg(2,2)
pp = self(uu1,uvars(uu1))
len(ppqq(pp))
# 4
[len(ee) for ee in ppqq(pp)]
# [1, 1, 1, 1]
und(pptt(pp))
# {1, 2}
der(pptt(pp))
# { { { {(1, 1), (2, 1)} }, { {(1, 1), (2, 2)} }, { {(1, 2), (2, 1)} }, { {(1, 2), (2, 2)} } } }
rpln(aall(ared(ttaa(pptt(pp)),und(pptt(pp)))))
# ({(1, 1), (2, 1)}, 1 % 1)
# ({(1, 1), (2, 2)}, 1 % 1)
# ({(1, 2), (2, 1)}, 1 % 1)
# ({(1, 2), (2, 2)}, 1 % 1)
rpln(aall(ttaa(pptt(pp))))
# ({(1, 1), (2, 1), ({ { {(1, 1), (2, 1)} }, { {(1, 1), (2, 2)} }, { {(1, 2), (2, 1)} }, { {(1, 2), (2, 2)} } }, { {(1, 1), (2, 1)} })}, 1 % 1)
# ({(1, 1), (2, 2), ({ { {(1, 1), (2, 1)} }, { {(1, 1), (2, 2)} }, { {(1, 2), (2, 1)} }, { {(1, 2), (2, 2)} } }, { {(1, 1), (2, 2)} })}, 1 % 1)
# ({(1, 2), (2, 1), ({ { {(1, 1), (2, 1)} }, { {(1, 1), (2, 2)} }, { {(1, 2), (2, 1)} }, { {(1, 2), (2, 2)} } }, { {(1, 2), (2, 1)} })}, 1 % 1)
# ({(1, 2), (2, 2), ({ { {(1, 1), (2, 1)} }, { {(1, 1), (2, 2)} }, { {(1, 2), (2, 1)} }, { {(1, 2), (2, 2)} } }, { {(1, 2), (2, 2)} })}, 1 % 1)
Natural converse
Given a one functional transform $T \in \mathcal{T}_{U,\mathrm{f},1}$, the natural converse is \[ \begin{eqnarray} T^{\dagger} &:=& (X/(X\%W),V) \end{eqnarray} \] where $(X,W) = T$ and $V = \mathrm{und}(T)$,
transformsConverseNatural :: Transform -> Transform
In the deck of cards example, the natural converse of the expanded suit-colour transform is
nat = transformsConverseNatural
rpln(aall(ttaa(ttv)))
# ({(colour, black), (rank, A), (suit, clubs)}, 1 % 1)
# ({(colour, black), (rank, A), (suit, spades)}, 1 % 1)
# ({(colour, black), (rank, J), (suit, clubs)}, 1 % 1)
# ...
# ({(colour, red), (rank, 9), (suit, hearts)}, 1 % 1)
# ({(colour, red), (rank, 10), (suit, diamonds)}, 1 % 1)
# ({(colour, red), (rank, 10), (suit, hearts)}, 1 % 1)
der(ttv)
# {colour}
und(ttv)
rp $ und ttv
# {rank, suit}
rpln(aall(ttaa(nat(ttv))))
# ({(colour, black), (rank, A), (suit, clubs)}, 1 % 26)
# ({(colour, black), (rank, A), (suit, spades)}, 1 % 26)
# ({(colour, black), (rank, J), (suit, clubs)}, 1 % 26)
# ...
# ({(colour, red), (rank, 9), (suit, hearts)}, 1 % 26)
# ({(colour, red), (rank, 10), (suit, diamonds)}, 1 % 26)
# ({(colour, red), (rank, 10), (suit, hearts)}, 1 % 26)
der(nat(ttv))
# {rank, suit}
und(nat(ttv))
# {colour}
Another example is $T’$,
def cdtt(pp,ll):
return trans(cdtp(cdaa(ll),pp), sset([VarInt(pp[-1])]))
tt1 = 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(tt1)))
# ({(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)
der(tt1)
# {3}
rpln(aall(ttaa(nat(tt1))))
# ({(1, 1), (2, 1), (3, 1)}, 1 % 4)
# ({(1, 1), (2, 2), (3, 1)}, 1 % 4)
# ({(1, 1), (2, 3), (3, 1)}, 1 % 4)
# ({(1, 2), (2, 1), (3, 2)}, 1 % 5)
# ({(1, 2), (2, 2), (3, 2)}, 1 % 5)
# ({(1, 2), (2, 3), (3, 2)}, 1 % 5)
# ({(1, 3), (2, 1), (3, 2)}, 1 % 5)
# ({(1, 3), (2, 2), (3, 2)}, 1 % 5)
# ({(1, 3), (2, 3), (3, 1)}, 1 % 4)
der(nat(tt1))
# {1, 2}
The natural converse may be expressed in terms of components, \[ T^{\dagger}~:=~(\sum_{(R,C) \in T^{-1}} \{R\}^{\mathrm{U}} * \hat{C},~V) \]
def inv(tt):
return list(transformsInverse(tt).items())
def sunit(ss):
return setStatesHistogramUnit(sset([ss]))
rpln(inv(ttv))
# ({(colour, black)}, {({(rank, A), (suit, clubs)}, 1 % 1), ..., ({(rank, 10), (suit, spades)}, 1 % 1)})
# ({(colour, red)}, {({(rank, A), (suit, diamonds)}, 1 % 1), ..., ({(rank, 10), (suit, hearts)}, 1 % 1)})
ee = histogramEmpty()
for (rr,cc) in inv(ttv):
ee = add(ee,mul(sunit(rr),norm(cc)))
rpln(aall(ee))
# ({(colour, black), (rank, A), (suit, clubs)}, 1 % 26)
# ({(colour, black), (rank, A), (suit, spades)}, 1 % 26)
# ({(colour, black), (rank, J), (suit, clubs)}, 1 % 26)
# ...
# ({(colour, red), (rank, 9), (suit, hearts)}, 1 % 26)
# ({(colour, red), (rank, 10), (suit, diamonds)}, 1 % 26)
# ({(colour, red), (rank, 10), (suit, hearts)}, 1 % 26)
rpln(inv(tt1))
# ({(3, 1)}, {({(1, 1), (2, 1)}, 1 % 1), ({(1, 1), (2, 2)}, 1 % 1), ({(1, 1), (2, 3)}, 1 % 1), ({(1, 3), (2, 3)}, 1 % 1)})
# ({(3, 2)}, {({(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)})
ee = histogramEmpty()
for (rr,cc) in inv(tt1):
ee = add(ee,mul(sunit(rr),norm(cc)))
rpln(aall(ee))
# ({(1, 1), (2, 1), (3, 1)}, 1 % 4)
# ({(1, 1), (2, 2), (3, 1)}, 1 % 4)
# ({(1, 1), (2, 3), (3, 1)}, 1 % 4)
# ({(1, 2), (2, 1), (3, 2)}, 1 % 5)
# ({(1, 2), (2, 2), (3, 2)}, 1 % 5)
# ({(1, 2), (2, 3), (3, 2)}, 1 % 5)
# ({(1, 3), (2, 1), (3, 2)}, 1 % 5)
# ({(1, 3), (2, 2), (3, 2)}, 1 % 5)
# ({(1, 3), (2, 3), (3, 1)}, 1 % 4)
Given a histogram $A \in \mathcal{A}$ in the underlying variables, $\mathrm{vars}(A) = V$, the naturalisation is the application of the natural converse transform to the derived histogram, $A * T * T^{\dagger}$,
rpln(aall(tmul(tmul(aa,ttv),nat(ttv))))
# ({(rank, A), (suit, clubs)}, 1 % 1)
# ({(rank, A), (suit, diamonds)}, 1 % 1)
# ({(rank, A), (suit, hearts)}, 1 % 1)
# ({(rank, A), (suit, spades)}, 1 % 1)
# ({(rank, J), (suit, clubs)}, 1 % 1)
# ({(rank, J), (suit, diamonds)}, 1 % 1)
# ...
# ({(rank, 9), (suit, hearts)}, 1 % 1)
# ({(rank, 9), (suit, spades)}, 1 % 1)
# ({(rank, 10), (suit, clubs)}, 1 % 1)
# ({(rank, 10), (suit, diamonds)}, 1 % 1)
# ({(rank, 10), (suit, hearts)}, 1 % 1)
# ({(rank, 10), (suit, spades)}, 1 % 1)
A histogram is natural when it equals its naturalisation, $A = A * T * T^{\dagger}$, so the deck of cards histogram is natural,
tmul(tmul(aa,ttv),nat(ttv)) == aa
# True
The cartesian is always natural, $V^{\mathrm{C}} = V^{\mathrm{C}} * T * T^{\dagger}$, so $T’$ applied to the cartesian is natural,
rpln(aall(tmul(tmul(regcart(3,2),tt1),nat(tt1))))
# ({(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)
tmul(tmul(regcart(3,2),tt1),nat(tt1)) == regcart(3,2)
# True
but $T’$ applied to the diagonal is not,
rpln(aall(tmul(tmul(regdiag(3,2),tt1),nat(tt1))))
# ({(1, 1), (2, 1)}, 1 % 2)
# ({(1, 1), (2, 2)}, 1 % 2)
# ({(1, 1), (2, 3)}, 1 % 2)
# ({(1, 2), (2, 1)}, 1 % 5)
# ({(1, 2), (2, 2)}, 1 % 5)
# ({(1, 2), (2, 3)}, 1 % 5)
# ({(1, 3), (2, 1)}, 1 % 5)
# ({(1, 3), (2, 2)}, 1 % 5)
# ({(1, 3), (2, 3)}, 1 % 2)
tmul(tmul(regdiag(3,2),tt1),nat(tt1)) == regdiag(3,2)
# False
The naturalisation can be rewritten $A * X~\%~W * X~/~(X\%W)~\%~V$,
ared(divide(mul(ared(mul(aa,ttaa(ttv)),der(ttv)),ttaa(ttv)),ared(ttaa(ttv),der(ttv))),vv) == tmul(tmul(aa,ttv),nat(ttv))
# True
The naturalisation is in the underlying variables, $\mathrm{vars}(A * T * T^{\dagger}) = V$,
vars(tmul(tmul(aa,ttv),nat(ttv)))
# {rank, suit}
The size is conserved, $\mathrm{size}(A * T * T^{\dagger}) = \mathrm{size}(A)$,
size(tmul(tmul(aa,ttv),nat(ttv))) == size(aa)
# True
The naturalisation derived equals the derived, $A * T * T^{\dagger} * T = A * T$,
tmul(tmul(tmul(aa,ttv),nat(ttv)),ttv) == tmul(aa,ttv)
# True
The naturalisation equals the sum of the scaled components, \[ \begin{eqnarray} A * T * T^{\dagger} &=& \sum_{(R,C) \in T^{-1}} \mathrm{scalar}( (A * T)_R) * \hat{C} \\ &=& \sum_{(R,C) \in T^{-1}} A * T * \{R\}^{\mathrm{U}} * \hat{C}~\%~V \end{eqnarray} \]
ee = histogramEmpty()
for (rr,cc) in inv(ttv):
ee = add(ee,mul(scalar(aat(tmul(aa,ttv),rr)),norm(cc)))
tmul(tmul(aa,ttv),nat(ttv)) == ee
# True
ee = histogramEmpty()
for (rr,cc) in inv(ttv):
ee = add(ee,ared(mul(mul(tmul(aa,ttv),sunit(rr)),norm(cc)),vv))
tmul(tmul(aa,ttv),nat(ttv)) == ee
# True
So each component is uniform, \[ \forall (R,C) \in T^{-1}~(|\mathrm{ran}(A * T * T^{\dagger} * C)| ~=~ 1) \]
isunif = histogramsIsUniform
[isunif(mul(tmul(tmul(aa,ttv),nat(ttv)),cc)) for (rr,cc) in inv(ttv)]
# [True, True]
The naturalisation of the unary partition transform, $T_{\mathrm{u}} = \{V^{\mathrm{CS}}\}^{\mathrm{T}}$, is the sized cartesian, $A * T_{\mathrm{u}} * T_{\mathrm{u}}^{\dagger} = V_z^{\mathrm{C}}$, where $z=\mathrm{size}(A)$,
pptt = partitionsTransformVarPartition
def unary(uu,vv):
return pptt(systemsSetVarsPartitionUnary(uu,vv))
tmul(tmul(aa,unary(uu,vv)),nat(unary(uu,vv))) == resize(size(aa),unit(cart(uu,vv)))
# True
The naturalisation of the self partition transform, $T_{\mathrm{s}} = V^{\mathrm{CS}\{\}\mathrm{T}}$, is the histogram, $A * T_{\mathrm{s}} * T_{\mathrm{s}}^{\dagger} = A$,
def self(uu,vv):
return pptt(systemsSetVarsPartitionSelf(uu,vv))
tmul(tmul(aa,self(uu,vv)),nat(self(uu,vv))) == aa
# True
Sample converse
Given a one functional transform $T \in \mathcal{T}_{U,\mathrm{f},1}$ with underlying variables $V = \mathrm{und}(T)$, and a histogram $A \in \mathcal{A}$ in the same variables, $\mathrm{vars}(A) = V$, the sample converse is \[ \begin{eqnarray} (\hat{A} * X,V) \end{eqnarray} \] where $X = \mathrm{his}(T)$. The sample converse for the deck of cards example is
tta = trans(mul(norm(aa),ttaa(ttv)),vars(aa))
rpln(aall(ttaa(tta)))
rpln $ aall $ ttaa tta
# ({(colour, black), (rank, A), (suit, clubs)}, 1 % 52)
# ({(colour, black), (rank, A), (suit, spades)}, 1 % 52)
# ({(colour, black), (rank, J), (suit, clubs)}, 1 % 52)
# ({(colour, black), (rank, J), (suit, spades)}, 1 % 52)
# ({(colour, black), (rank, K), (suit, clubs)}, 1 % 52)
# ({(colour, black), (rank, K), (suit, spades)}, 1 % 52)
# ...
# ({(colour, red), (rank, 8), (suit, diamonds)}, 1 % 52)
# ({(colour, red), (rank, 8), (suit, hearts)}, 1 % 52)
# ({(colour, red), (rank, 9), (suit, diamonds)}, 1 % 52)
# ({(colour, red), (rank, 9), (suit, hearts)}, 1 % 52)
# ({(colour, red), (rank, 10), (suit, diamonds)}, 1 % 52)
# ({(colour, red), (rank, 10), (suit, hearts)}, 1 % 52)
der(tta)
# {rank, suit}
und(tta)
# {colour}
Actual converse
Related to the sample converse, the actual converse is defined as the summed normalised application of the components to the sample histogram, \[ \begin{eqnarray} T^{\odot A} &:=& (\sum_{(R,C) \in T^{-1}} {R}^{\mathrm{U}} * (A * C)^{\wedge},~V) \end{eqnarray} \]
histogramsTransformsConverseActual :: Histogram -> Transform -> Maybe Transform
In the deck of cards example, the actual converse of the expanded suit-colour transform is
def act(tt,aa):
return histogramsTransformsConverseActual(aa,tt)
rpln(aall(ttaa(act(ttv,aa))))
# ({(colour, black), (rank, A), (suit, clubs)}, 1 % 26)
# ({(colour, black), (rank, A), (suit, spades)}, 1 % 26)
# ({(colour, black), (rank, J), (suit, clubs)}, 1 % 26)
# ...
# ({(colour, red), (rank, 9), (suit, hearts)}, 1 % 26)
# ({(colour, red), (rank, 10), (suit, diamonds)}, 1 % 26)
# ({(colour, red), (rank, 10), (suit, hearts)}, 1 % 26)
der(act(ttv,aa))
# {rank, suit}
und(act(ttv,aa))
# {colour}
Another example is $T’$,
tt1 = 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(act(tt1,regcart(3,2)))))
# ({(1, 1), (2, 1), (3, 1)}, 1 % 4)
# ({(1, 1), (2, 2), (3, 1)}, 1 % 4)
# ({(1, 1), (2, 3), (3, 1)}, 1 % 4)
# ({(1, 2), (2, 1), (3, 2)}, 1 % 5)
# ({(1, 2), (2, 2), (3, 2)}, 1 % 5)
# ({(1, 2), (2, 3), (3, 2)}, 1 % 5)
# ({(1, 3), (2, 1), (3, 2)}, 1 % 5)
# ({(1, 3), (2, 2), (3, 2)}, 1 % 5)
# ({(1, 3), (2, 3), (3, 1)}, 1 % 4)
der(act(tt1,regcart(3,2)))
# {1, 2}
rpln(aall(ttaa(act(tt1,regdiag(3,2)))))
# ({(1, 1), (2, 1), (3, 1)}, 1 % 2)
# ({(1, 2), (2, 2), (3, 2)}, 1 % 1)
# ({(1, 3), (2, 3), (3, 1)}, 1 % 2)
der(act(tt1,regdiag(3,2)))
# {1, 2}
The actual converse may be expressed in terms of components,
ee = histogramEmpty()
for (rr,cc) in inv(ttv):
ee = add(ee,mul(sunit(rr),norm(mul(aa,cc))))
rpln(aall(ee))
# ({(colour, black), (rank, A), (suit, clubs)}, 1 % 26)
# ({(colour, black), (rank, A), (suit, spades)}, 1 % 26)
# ({(colour, black), (rank, J), (suit, clubs)}, 1 % 26)
# ...
# ({(colour, red), (rank, 9), (suit, hearts)}, 1 % 26)
# ({(colour, red), (rank, 10), (suit, diamonds)}, 1 % 26)
# ({(colour, red), (rank, 10), (suit, hearts)}, 1 % 26)
ee = histogramEmpty()
for (rr,cc) in inv(tt1):
ee = add(ee,mul(sunit(rr),norm(mul(regcart(3,2),cc))))
rpln(aall(ee))
# ({(1, 1), (2, 1), (3, 1)}, 1 % 4)
# ({(1, 1), (2, 2), (3, 1)}, 1 % 4)
# ({(1, 1), (2, 3), (3, 1)}, 1 % 4)
# ({(1, 2), (2, 1), (3, 2)}, 1 % 5)
# ({(1, 2), (2, 2), (3, 2)}, 1 % 5)
# ({(1, 2), (2, 3), (3, 2)}, 1 % 5)
# ({(1, 3), (2, 1), (3, 2)}, 1 % 5)
# ({(1, 3), (2, 2), (3, 2)}, 1 % 5)
# ({(1, 3), (2, 3), (3, 1)}, 1 % 4)
ee = histogramEmpty()
for (rr,cc) in inv(tt1):
ee = add(ee,mul(sunit(rr),norm(mul(regdiag(3,2),cc))))
rpln(aall(ee))
# ({(1, 1), (2, 1), (3, 1)}, 1 % 2)
# ({(1, 2), (2, 2), (3, 2)}, 1 % 1)
# ({(1, 3), (2, 3), (3, 1)}, 1 % 2)
The application of the actual converse transform to the derived histogram equals the histogram, $A * T * T^{\odot A} = A$,
tmul(tmul(aa,ttv),act(ttv,aa)) == aa
# True
tmul(tmul(regcart(3,2),tt1),act(tt1,regcart(3,2))) == regcart(3,2)
# True
tmul(tmul(regdiag(3,2),tt1),act(tt1,regdiag(3,2))) == regdiag(3,2)
# True
Independent converse
Given a one functional transform $T \in \mathcal{T}_{U,\mathrm{f},1}$ with underlying variables $V = \mathrm{und}(T)$, and a histogram $A \in \mathcal{A}$ in the same variables, $\mathrm{vars}(A) = V$, the independent converse is defined as the summed normalised independent application of the components to the sample histogram, \[ \begin{eqnarray} T^{\dagger A} &:=& (\sum_{(R,C) \in T^{-1}} \{R\}^{\mathrm{U}} * (A * C)^{\wedge\mathrm{X}},~V) \end{eqnarray} \]
histogramsTransformsConverseIndependent :: Histogram -> Transform -> Maybe Transform
In the deck of cards example, the independent converse of the expanded suit-colour transform is
def idl(tt,aa):
return histogramsTransformsConverseIndependent(aa,tt)
rpln(aall(ttaa(idl(ttv,aa))))
# ({(colour, black), (rank, A), (suit, clubs)}, 1 % 26)
# ({(colour, black), (rank, A), (suit, spades)}, 1 % 26)
# ({(colour, black), (rank, J), (suit, clubs)}, 1 % 26)
# ...
# ({(colour, red), (rank, 9), (suit, hearts)}, 1 % 26)
# ({(colour, red), (rank, 10), (suit, diamonds)}, 1 % 26)
# ({(colour, red), (rank, 10), (suit, hearts)}, 1 % 26)
der(idl(ttv,aa))
# {rank, suit}
und(idl(ttv,aa))
# {colour}
Another example is $T’$,
tt1 = 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(idl(tt1,regcart(3,2)))))
# ({(1, 1), (2, 1), (3, 1)}, 3 % 16)
# ({(1, 1), (2, 2), (3, 1)}, 3 % 16)
# ({(1, 1), (2, 3), (3, 1)}, 3 % 8)
# ({(1, 2), (2, 1), (3, 2)}, 6 % 25)
# ({(1, 2), (2, 2), (3, 2)}, 6 % 25)
# ({(1, 2), (2, 3), (3, 2)}, 3 % 25)
# ({(1, 3), (2, 1), (3, 1)}, 1 % 16)
# ({(1, 3), (2, 1), (3, 2)}, 4 % 25)
# ({(1, 3), (2, 2), (3, 1)}, 1 % 16)
# ({(1, 3), (2, 2), (3, 2)}, 4 % 25)
# ({(1, 3), (2, 3), (3, 1)}, 1 % 8)
# ({(1, 3), (2, 3), (3, 2)}, 2 % 25)
der(idl(tt1,regcart(3,2)))
# {1, 2}
rpln(aall(ttaa(idl(tt1,regdiag(3,2)))))
# ({(1, 1), (2, 1), (3, 1)}, 1 % 4)
# ({(1, 1), (2, 3), (3, 1)}, 1 % 4)
# ({(1, 2), (2, 2), (3, 2)}, 1 % 1)
# ({(1, 3), (2, 1), (3, 1)}, 1 % 4)
# ({(1, 3), (2, 3), (3, 1)}, 1 % 4)
der(idl(tt1,regdiag(3,2)))
# {1, 2}
The independent converse may be expressed in terms of components,
ee = histogramEmpty()
for (rr,cc) in inv(ttv):
ee = add(ee,mul(sunit(rr),ind(norm(mul(aa,cc)))))
rpln(aall(ee))
# ({(colour, black), (rank, A), (suit, clubs)}, 1 % 26)
# ({(colour, black), (rank, A), (suit, spades)}, 1 % 26)
# ({(colour, black), (rank, J), (suit, clubs)}, 1 % 26)
# ...
# ({(colour, red), (rank, 9), (suit, hearts)}, 1 % 26)
# ({(colour, red), (rank, 10), (suit, diamonds)}, 1 % 26)
# ({(colour, red), (rank, 10), (suit, hearts)}, 1 % 26)
ee = histogramEmpty()
for (rr,cc) in inv(tt1):
ee = add(ee,mul(sunit(rr),ind(norm(mul(regcart(3,2),cc)))))
rpln(aall(ee))
# ({(1, 1), (2, 1), (3, 1)}, 3 % 16)
# ({(1, 1), (2, 2), (3, 1)}, 3 % 16)
# ({(1, 1), (2, 3), (3, 1)}, 3 % 8)
# ({(1, 2), (2, 1), (3, 2)}, 6 % 25)
# ({(1, 2), (2, 2), (3, 2)}, 6 % 25)
# ({(1, 2), (2, 3), (3, 2)}, 3 % 25)
# ({(1, 3), (2, 1), (3, 1)}, 1 % 16)
# ({(1, 3), (2, 1), (3, 2)}, 4 % 25)
# ({(1, 3), (2, 2), (3, 1)}, 1 % 16)
# ({(1, 3), (2, 2), (3, 2)}, 4 % 25)
# ({(1, 3), (2, 3), (3, 1)}, 1 % 8)
# ({(1, 3), (2, 3), (3, 2)}, 2 % 25)
ee = histogramEmpty()
for (rr,cc) in inv(tt1):
ee = add(ee,mul(sunit(rr),ind(norm(mul(regdiag(3,2),cc)))))
rpln(aall(ee))
# ({(1, 1), (2, 1), (3, 1)}, 1 % 4)
# ({(1, 1), (2, 3), (3, 1)}, 1 % 4)
# ({(1, 2), (2, 2), (3, 2)}, 1 % 1)
# ({(1, 3), (2, 1), (3, 1)}, 1 % 4)
# ({(1, 3), (2, 3), (3, 1)}, 1 % 4)
The idealisation is the application of the independent converse transform to the derived histogram, $A * T * T^{\dagger A}$,
rpln(aall(tmul(tmul(aa,ttv),idl(ttv,aa))))
# ({(rank, A), (suit, clubs)}, 1 % 1)
# ({(rank, A), (suit, diamonds)}, 1 % 1)
# ({(rank, A), (suit, hearts)}, 1 % 1)
# ({(rank, A), (suit, spades)}, 1 % 1)
# ({(rank, J), (suit, clubs)}, 1 % 1)
# ({(rank, J), (suit, diamonds)}, 1 % 1)
# ...
# ({(rank, 9), (suit, hearts)}, 1 % 1)
# ({(rank, 9), (suit, spades)}, 1 % 1)
# ({(rank, 10), (suit, clubs)}, 1 % 1)
# ({(rank, 10), (suit, diamonds)}, 1 % 1)
# ({(rank, 10), (suit, hearts)}, 1 % 1)
# ({(rank, 10), (suit, spades)}, 1 % 1)
rpln(aall(tmul(tmul(regcart(3,2),tt1),idl(tt1,regcart(3,2)))))
# ({(1, 1), (2, 1)}, 3 % 4)
# ({(1, 1), (2, 2)}, 3 % 4)
# ({(1, 1), (2, 3)}, 3 % 2)
# ({(1, 2), (2, 1)}, 6 % 5)
# ({(1, 2), (2, 2)}, 6 % 5)
# ({(1, 2), (2, 3)}, 3 % 5)
# ({(1, 3), (2, 1)}, 21 % 20)
# ({(1, 3), (2, 2)}, 21 % 20)
# ({(1, 3), (2, 3)}, 9 % 10)
rpln(aall(tmul(tmul(regdiag(3,2),tt1),idl(tt1,regdiag(3,2)))))
# ({(1, 1), (2, 1)}, 1 % 2)
# ({(1, 1), (2, 3)}, 1 % 2)
# ({(1, 2), (2, 2)}, 1 % 1)
# ({(1, 3), (2, 1)}, 1 % 2)
# ({(1, 3), (2, 3)}, 1 % 2)
A histogram is ideal when it equals its idealisation, $A = A * T * T^{\dagger A}$, so the deck of cards histogram is ideal,
tmul(tmul(aa,ttv),idl(ttv,aa)) == aa
# True
$T’$ applied to the cartesian is not ideal,
tmul(tmul(regcart(3,2),tt1),idl(tt1,regcart(3,2))) == regcart(3,2)
# False
nor is the application to the diagonal,
tmul(tmul(regdiag(3,2),tt1),idl(tt1,regdiag(3,2))) == regdiag(3,2)
# False
The idealisation is in the underlying variables, $\mathrm{vars}(A * T * T^{\dagger A}) = V$,
vars(tmul(tmul(aa,ttv),idl(ttv,aa))) == vv
# True
The size is conserved, $\mathrm{size}(A * T * T^{\dagger A}) = \mathrm{size}(A)$,
size(tmul(tmul(aa,ttv),idl(ttv,aa))) == size(aa)
# True
The idealisation derived equals the derived, $A * T * T^{\dagger A} * T = A * T$,
tmul(tmul(tmul(aa,ttv),idl(ttv,aa)),ttv) == tmul(aa,ttv)
# True
The idealisation equals the sum of the independent components, \[ \begin{eqnarray} A * T * T^{\dagger A} &=& \sum_{(R,C) \in T^{-1}} (A * C)^{\mathrm{X}} \\ &=& \sum_{(R,C) \in T^{-1}} A * T * \{R\}^{\mathrm{U}} * (A * C)^{\wedge\mathrm{X}}~\%~V \end{eqnarray} \]
ee = histogramEmpty()
for (rr,cc) in inv(ttv):
ee = add(ee,ind(mul(aa,cc)))
tmul(tmul(aa,ttv),idl(ttv,aa)) == ee
# True
ee = histogramEmpty()
for (rr,cc) in inv(ttv):
ee = add(ee,ared(mul(mul(tmul(aa,ttv),sunit(rr)),norm(ind(mul(aa,cc)))),vv))
tmul(tmul(aa,ttv),idl(ttv,aa)) == ee
# True
So each component is independent, \[ \forall (R,C) \in T^{-1}~(A * T * T^{\dagger A} * C = (A * T * T^{\dagger A} * C)^{\mathrm{X}} = (A * C)^{\mathrm{X}}) \]
[mul(tmul(tmul(aa,ttv),idl(ttv,aa)),cc) == ind(mul(aa,cc)) for (rr,cc) in inv(ttv)]
# [True, True]
The idealisation of the unary partition transform, $T_{\mathrm{u}} = \{V^{\mathrm{CS}}\}^{\mathrm{T}}$, is the sized cartesian, $A * T_{\mathrm{u}} * T_{\mathrm{u}}^{\dagger A} = V_z^{\mathrm{C}}$,
pptt = partitionsTransformVarPartition
def unary(uu,vv):
return pptt(systemsSetVarsPartitionUnary(uu,vv))
tmul(tmul(aa,unary(uu,vv)),idl(unary(uu,vv),aa)) == resize(size(aa),unit(cart(uu,vv)))
# True
The idealisation of the self partition transform, $T_{\mathrm{s}} = V^{\mathrm{CS}\{\}\mathrm{T}}$, is the histogram, $A * T_{\mathrm{s}} * T_{\mathrm{s}}^{\dagger A} = A$,
def self(uu,vv):
return pptt(systemsSetVarsPartitionSelf(uu,vv))
tmul(tmul(aa,self(uu,vv)),idl(self(uu,vv),aa)) == aa
# True
The idealisation independent equals the independent, $(A * T * T^{\dagger A})^{\mathrm{X}} = A^{\mathrm{X}}$,
ind(tmul(tmul(aa,ttv),idl(ttv,aa))) == ind(aa)
# True
ind(tmul(tmul(regcart(3,2),tt1),idl(tt1,regcart(3,2)))) == ind(regcart(3,2))
# True
ind(tmul(tmul(regdiag(3,2),tt1),idl(tt1,regdiag(3,2)))) == ind(regdiag(3,2))
# True
The idealisation formal equals the formal, $(A * T * T^{\dagger A})^{\mathrm{X}} * T = A^{\mathrm{X}} * T$,
tmul(ind(tmul(tmul(aa,ttv),idl(ttv,aa))),ttv) == tmul(ind(aa),ttv)
# True
tmul(ind(tmul(tmul(regcart(3,2),tt1),idl(tt1,regcart(3,2)))),tt1) == tmul(ind(regcart(3,2)),tt1)
# True
tmul(ind(tmul(tmul(regdiag(3,2),tt1),idl(tt1,regdiag(3,2)))),tt1) == tmul(ind(regdiag(3,2)),tt1)
# True
Transforms as models
The sense in which a transform is a simple model can be seen by considering queries on a sample histogram. Let histogram $A$ have a set of variables $V = \mathrm{vars}(A)$ which is partitioned into query variables $K \subset V$ and label variables $V \setminus K$. Let $T = (X,W)$ be a one functional transform having underlying variables equal to the query variables, $\mathrm{und}(T) = K$. Given a query state $Q \in K^{\mathrm{CS}}$ that may be ineffective in the sample, $Q \notin (A\%K)^{\mathrm{FS}}$, but is effective in the sample derived, $R \in (A * T)^{\mathrm{FS}}$ where $\{R\} = (\{Q\}^{\mathrm{U}} * T)^{\mathrm{FS}}$, the probability histogram for the label is \[ \begin{eqnarray} (\{Q\}^{\mathrm{U}} * T * (\hat{A} * X,V))^{\wedge}~\%~(V \setminus K) &\in& \mathcal{A} \cap \mathcal{P} \end{eqnarray} \] where the sample converse transform is $(\hat{A} * X,V)$. This can be expressed more simply in terms of the actual converse, \[ \begin{eqnarray} \{Q\}^{\mathrm{U}} * T * T^{\odot A}~\%~(V \setminus K) &\in& \mathcal{A} \cap \mathcal{P} \end{eqnarray} \] The query of the sample via model can also be written without the transforms, $(\{Q\}^{\mathrm{U}} * X~\%~W * X * A)^{\wedge}~\%~(V \setminus K)$. In the deck of cards example, the model of the colours of the suits does not tell us anything about the rank given the suit in the case where the histogram is the entire deck,
qq = unit(sset([llss([(suit,clubs)])]))
vk = sset([rank])
rpln(aall(norm(ared(mul(mul(tmul(qq,tt),xx),aa),vk))))
# ({(rank, A)}, 1 % 13)
# ({(rank, J)}, 1 % 13)
# ({(rank, K)}, 1 % 13)
# ({(rank, Q)}, 1 % 13)
# ({(rank, 2)}, 1 % 13)
# ({(rank, 3)}, 1 % 13)
# ({(rank, 4)}, 1 % 13)
# ({(rank, 5)}, 1 % 13)
# ({(rank, 6)}, 1 % 13)
# ({(rank, 7)}, 1 % 13)
# ({(rank, 8)}, 1 % 13)
# ({(rank, 9)}, 1 % 13)
# ({(rank, 10)}, 1 % 13)
If, however, we consider a game of cards which has a special deck such that spades and clubs are pip cards and hearts and diamonds are face cards, the suit and the rank are no longer independent,
bb = unit(sset(
[llss([(suit,s),(rank,r)]) for s in [spades,clubs] for r in [ace] + list(map(ValInt,range(2,10+1)))] +
[llss([(suit,s),(rank,r)]) for s in [hearts,diamonds] for r in [jack,queen,king]]))
rpln(aall(bb))
# ({(rank, A), (suit, clubs)}, 1 % 1)
# ({(rank, A), (suit, spades)}, 1 % 1)
# ({(rank, J), (suit, diamonds)}, 1 % 1)
# ({(rank, J), (suit, hearts)}, 1 % 1)
# ({(rank, K), (suit, diamonds)}, 1 % 1)
# ({(rank, K), (suit, hearts)}, 1 % 1)
# ({(rank, Q), (suit, diamonds)}, 1 % 1)
# ({(rank, Q), (suit, hearts)}, 1 % 1)
# ({(rank, 2), (suit, clubs)}, 1 % 1)
# ({(rank, 2), (suit, spades)}, 1 % 1)
# ({(rank, 3), (suit, clubs)}, 1 % 1)
# ({(rank, 3), (suit, spades)}, 1 % 1)
# ({(rank, 4), (suit, clubs)}, 1 % 1)
# ({(rank, 4), (suit, spades)}, 1 % 1)
# ({(rank, 5), (suit, clubs)}, 1 % 1)
# ({(rank, 5), (suit, spades)}, 1 % 1)
# ({(rank, 6), (suit, clubs)}, 1 % 1)
# ({(rank, 6), (suit, spades)}, 1 % 1)
# ({(rank, 7), (suit, clubs)}, 1 % 1)
# ({(rank, 7), (suit, spades)}, 1 % 1)
# ({(rank, 8), (suit, clubs)}, 1 % 1)
# ({(rank, 8), (suit, spades)}, 1 % 1)
# ({(rank, 9), (suit, clubs)}, 1 % 1)
# ({(rank, 9), (suit, spades)}, 1 % 1)
# ({(rank, 10), (suit, clubs)}, 1 % 1)
# ({(rank, 10), (suit, spades)}, 1 % 1)
algn(bb)
# 4.502579806192693
Now our model aligns the suit to the rank via colour, so a query on clubs is always a pip card,
rpln(aall(norm(ared(mul(mul(tmul(qq,tt),xx),bb),vk))))
# ({(rank, A)}, 1 % 10)
# ({(rank, 2)}, 1 % 10)
# ({(rank, 3)}, 1 % 10)
# ({(rank, 4)}, 1 % 10)
# ({(rank, 5)}, 1 % 10)
# ({(rank, 6)}, 1 % 10)
# ({(rank, 7)}, 1 % 10)
# ({(rank, 8)}, 1 % 10)
# ({(rank, 9)}, 1 % 10)
# ({(rank, 10)}, 1 % 10)
A query on hearts is always a face card,
qq = unit(sset([llss([(suit,hearts)])]))
rpln(aall(norm(ared(mul(mul(tmul(qq,tt),xx),bb),vk))))
# ({(rank, J)}, 1 % 3)
# ({(rank, K)}, 1 % 3)
# ({(rank, Q)}, 1 % 3)
Of course, in this example the model is not very interesting because we can simply query the sample directly,
rpln(aall(norm(ared(mul(qq,bb),vk))))
# ({(rank, J)}, 1 % 3)
# ({(rank, K)}, 1 % 3)
# ({(rank, Q)}, 1 % 3)
Usually models are more useful when the size of the sample is much smaller than the underlying volume, $z \ll v$, where $z = \mathrm{size}(A)$ and $v = |V^{\mathrm{C}}|$, but not the derived volume, $z \ge w$, where $w = |W^{\mathrm{C}}|$. In these cases the sample itself does not contain the query, $\{Q\}^{\mathrm{U}} * A = \emptyset$, but the sample derived does contain the query derived, $\{R\}^{\mathrm{U}} * (A * T) \neq \emptyset$, and so the resultant labels are those of the corresponding effective component, $A * C~\%~(V \setminus K)$, where $(R,C) \in T^{-1}$.
Example - a weather forecast
Some of the concepts above regarding transforms can be demonstrated with the sample of some weather measurements created in States, histories and histograms,
def lluu(ll):
return listsSystem([(v,sset(ww)) for (v,ww) in ll])
def llhh(vv,ev):
return listsHistory([(IdInt(i), llss(zip(vv,ll))) for (i,ll) in ev])
def red(aa,ll):
return setVarsHistogramsReduce(sset(ll),aa)
def ssplit(ll,aa):
return setVarsSetStatesSplit(sset(ll),states(aa))
[pressure,cloud,wind,rain] = map(VarStr,["pressure","cloud","wind","rain"])
[low,medium,high,none,light,heavy,strong] = map(ValStr,["low","medium","high","none","light","heavy","strong"])
uu = lluu([
(pressure, [low,medium,high]),
(cloud, [none,light,heavy]),
(wind, [none,light,strong]),
(rain, [none,light,heavy])])
vv = uvars(uu)
hh = llhh([pressure,cloud,wind,rain],[
(1,[high,none,none,none]),
(2,[medium,light,none,light]),
(3,[high,none,light,none]),
(4,[low,heavy,strong,heavy]),
(5,[low,none,light,light]),
(6,[medium,none,light,light]),
(7,[low,heavy,light,heavy]),
(8,[high,none,light,none]),
(9,[medium,light,strong,heavy]),
(10,[medium,light,light,light]),
(11,[high,light,light,heavy]),
(12,[medium,none,none,none]),
(13,[medium,light,none,none]),
(14,[high,light,strong,light]),
(15,[medium,none,light,light]),
(16,[low,heavy,strong,heavy]),
(17,[low,heavy,light,heavy]),
(18,[high,none,none,none]),
(19,[low,light,none,light]),
(20,[high,none,none,none])])
aa = hhaa(hh)
uu
# {(cloud, {heavy, light, none}), (pressure, {high, low, medium}), (rain, {heavy, light, none}), (wind, {light, none, strong})}
vv
# {cloud, pressure, rain, wind}
rpln(aall(aa))
# ({(cloud, heavy), (pressure, low), (rain, heavy), (wind, light)}, 2 % 1)
# ({(cloud, heavy), (pressure, low), (rain, heavy), (wind, strong)}, 2 % 1)
# ({(cloud, light), (pressure, high), (rain, heavy), (wind, light)}, 1 % 1)
# ({(cloud, light), (pressure, high), (rain, light), (wind, strong)}, 1 % 1)
# ({(cloud, light), (pressure, low), (rain, light), (wind, none)}, 1 % 1)
# ({(cloud, light), (pressure, medium), (rain, heavy), (wind, strong)}, 1 % 1)
# ({(cloud, light), (pressure, medium), (rain, light), (wind, light)}, 1 % 1)
# ({(cloud, light), (pressure, medium), (rain, light), (wind, none)}, 1 % 1)
# ({(cloud, light), (pressure, medium), (rain, none), (wind, none)}, 1 % 1)
# ({(cloud, none), (pressure, high), (rain, none), (wind, light)}, 2 % 1)
# ({(cloud, none), (pressure, high), (rain, none), (wind, none)}, 3 % 1)
# ({(cloud, none), (pressure, low), (rain, light), (wind, light)}, 1 % 1)
# ({(cloud, none), (pressure, medium), (rain, light), (wind, light)}, 2 % 1)
# ({(cloud, none), (pressure, medium), (rain, none), (wind, none)}, 1 % 1)
size(aa)
# 20 % 1
Consider the case where we know the pressure
, cloud
and wind
, and wish to predict the rain
.
That is, the singleton set of rain
is set of the label variables, $V \setminus K$, and pressure
, cloud
and wind
together form the query variables, $K$.
In Entropy and alignment the alignments of various reductions were calculated,
algn(resize(20,regdiag(3,4)))
# 31.485060233928998
algn(aa)
# 11.85085227502473
algn(red(aa,[pressure,rain]))
# 4.278766678519384
algn(red(aa,[cloud,rain]))
# 6.4150379630063465
algn(red(aa,[wind,rain]))
# 3.930131313218345
algn(red(aa,[cloud,wind,rain]))
# 8.935048311238008
We can see that pressure
and rain
are aligned but not causal,
algn(red(aa,[pressure,rain]))
# 4.278766678519384
rpln(ssplit([pressure],red(aa,[pressure,rain])))
# ({(pressure, high)}, {(rain, heavy)})
# ({(pressure, high)}, {(rain, light)})
# ({(pressure, high)}, {(rain, none)})
# ({(pressure, low)}, {(rain, heavy)})
# ({(pressure, low)}, {(rain, light)})
# ({(pressure, medium)}, {(rain, heavy)})
# ({(pressure, medium)}, {(rain, light)})
# ({(pressure, medium)}, {(rain, none)})
histogramsIsCausal(red(aa,[pressure,rain]))
# False
cloud
and rain
are more aligned,
algn(red(aa,[cloud,rain]))
# 6.4150379630063465
rpln(ssplit([cloud],red(aa,[cloud,rain])))
# ({(cloud, heavy)}, {(rain, heavy)})
# ({(cloud, light)}, {(rain, heavy)})
# ({(cloud, light)}, {(rain, light)})
# ({(cloud, light)}, {(rain, none)})
# ({(cloud, none)}, {(rain, light)})
# ({(cloud, none)}, {(rain, none)})
but cloud
, wind
and rain
are still more aligned,
algn(red(aa,[cloud,wind,rain]))
# 8.935048311238008
rpln(ssplit([cloud,wind],red(aa,[cloud,wind,rain])))
# ({(cloud, heavy), (wind, light)}, {(rain, heavy)})
# ({(cloud, heavy), (wind, strong)}, {(rain, heavy)})
# ({(cloud, light), (wind, light)}, {(rain, heavy)})
# ({(cloud, light), (wind, light)}, {(rain, light)})
# ({(cloud, light), (wind, none)}, {(rain, light)})
# ({(cloud, light), (wind, none)}, {(rain, none)})
# ({(cloud, light), (wind, strong)}, {(rain, heavy)})
# ({(cloud, light), (wind, strong)}, {(rain, light)})
# ({(cloud, none), (wind, light)}, {(rain, light)})
# ({(cloud, none), (wind, light)}, {(rain, none)})
# ({(cloud, none), (wind, none)}, {(rain, none)})
histogramsIsCausal(red(aa,[cloud,wind,rain]))
# False
So consider a simple model consisting of a one functional transform $T \in \mathcal{T}_{U,\mathrm{f},1}$ with underlying variables cloud
and wind
and a derived variable of cloud_and_wind
with this relation -
cloud | wind | cloud and wind |
---|---|---|
none | none | none |
none | light | light |
none | strong | light |
light | none | light |
light | light | light |
light | strong | light |
heavy | none | strong |
heavy | light | strong |
heavy | strong | strong |
cloud_and_wind = VarStr("cloud_and_wind")
def lltt(kk,ww,qq):
return trans(unit(sset([llss(zip(kk + ww,ll)) for ll in qq])),sset(ww))
tt = lltt([cloud,wind],[cloud_and_wind],[
[none, none, none],
[none, light, light],
[none, strong, light],
[light, none, light],
[light, light, light],
[light, strong, light],
[heavy, none, strong],
[heavy, light, strong],
[heavy, strong, strong]])
rpln(aall(ttaa(tt)))
# ({(cloud, heavy), (cloud_and_wind, strong), (wind, light)}, 1 % 1)
# ({(cloud, heavy), (cloud_and_wind, strong), (wind, none)}, 1 % 1)
# ({(cloud, heavy), (cloud_and_wind, strong), (wind, strong)}, 1 % 1)
# ({(cloud, light), (cloud_and_wind, light), (wind, light)}, 1 % 1)
# ({(cloud, light), (cloud_and_wind, light), (wind, none)}, 1 % 1)
# ({(cloud, light), (cloud_and_wind, light), (wind, strong)}, 1 % 1)
# ({(cloud, none), (cloud_and_wind, light), (wind, light)}, 1 % 1)
# ({(cloud, none), (cloud_and_wind, light), (wind, strong)}, 1 % 1)
# ({(cloud, none), (cloud_and_wind, none), (wind, none)}, 1 % 1)
rpln(ssplit([cloud,wind],ttaa(tt)))
# ({(cloud, heavy), (wind, light)}, {(cloud_and_wind, strong)})
# ({(cloud, heavy), (wind, none)}, {(cloud_and_wind, strong)})
# ({(cloud, heavy), (wind, strong)}, {(cloud_and_wind, strong)})
# ({(cloud, light), (wind, light)}, {(cloud_and_wind, light)})
# ({(cloud, light), (wind, none)}, {(cloud_and_wind, light)})
# ({(cloud, light), (wind, strong)}, {(cloud_and_wind, light)})
# ({(cloud, none), (wind, light)}, {(cloud_and_wind, light)})
# ({(cloud, none), (wind, none)}, {(cloud_and_wind, none)})
# ({(cloud, none), (wind, strong)}, {(cloud_and_wind, light)})
und(tt)
# {cloud, wind}
der(tt)
# {cloud_and_wind}
histogramsIsCausal(ttaa(tt))
# True
rpln(aall(tmul(aa,tt)))
# ({(cloud_and_wind, light)}, 12 % 1)
# ({(cloud_and_wind, none)}, 4 % 1)
# ({(cloud_and_wind, strong)}, 4 % 1)
Now we calculate the alignment between the derived variable, cloud_and_wind
, and the rain
,
algn(red(mul(aa,ttaa(tt)),[cloud_and_wind,rain]))
# 6.743705969634357
rpln(ssplit([cloud_and_wind],red(mul(aa,ttaa(tt)),[cloud_and_wind,rain])))
# ({(cloud_and_wind, light)}, {(rain, heavy)})
# ({(cloud_and_wind, light)}, {(rain, light)})
# ({(cloud_and_wind, light)}, {(rain, none)})
# ({(cloud_and_wind, none)}, {(rain, none)})
# ({(cloud_and_wind, strong)}, {(rain, heavy)})
So cloud_and_wind
is more aligned with rain
than any of cloud
, wind
or pressure
.
Now consider a query which is ineffective in the sample, $Q \notin (A\%K)^{\mathrm{FS}}$, but is effective in the sample derived, $R \in (A * T)^{\mathrm{FS}}$ where $\{R\} = (\{Q\}^{\mathrm{U}} * T)^{\mathrm{FS}}$,
qq = hhaa(llhh([pressure,cloud,wind],[(1,[medium,heavy,light])]))
leq(qq,eff(red(aa,[pressure,cloud,wind])))
# False
rpln(aall(tmul(qq,tt)))
# ({(cloud_and_wind, strong)}, 1 % 1)
rr = hhaa(llhh([cloud_and_wind],[(1,[strong])]))
leq(rr,eff(tmul(aa,tt)))
# True
The forecast for rain
is heavy
,
def aarr(aa):
return [(ss,float(q)) for (ss,q) in aall(aa)]
def query(qq,tt,aa,ll):
return norm(red(mul(mul(tmul(qq,tt),ttaa(tt)),aa),ll))
rpln(aarr(query(qq,tt,aa,[rain])))
# ({(rain, heavy)}, 1.0)
We can calculate the resultant label histogram for all $3^3 = 27$ queries,
kk = sset([pressure,cloud,wind])
rpln([(ss, query(unit(sset([ss])),tt,aa,[rain])) for ss in cart(uu,kk)])
# ({(cloud, heavy), (pressure, high), (wind, light)}, {({(rain, heavy)}, 1 % 1)})
# ({(cloud, heavy), (pressure, high), (wind, none)}, {({(rain, heavy)}, 1 % 1)})
# ({(cloud, heavy), (pressure, high), (wind, strong)}, {({(rain, heavy)}, 1 % 1)})
# ({(cloud, heavy), (pressure, low), (wind, light)}, {({(rain, heavy)}, 1 % 1)})
# ({(cloud, heavy), (pressure, low), (wind, none)}, {({(rain, heavy)}, 1 % 1)})
# ({(cloud, heavy), (pressure, low), (wind, strong)}, {({(rain, heavy)}, 1 % 1)})
# ({(cloud, heavy), (pressure, medium), (wind, light)}, {({(rain, heavy)}, 1 % 1)})
# ({(cloud, heavy), (pressure, medium), (wind, none)}, {({(rain, heavy)}, 1 % 1)})
# ({(cloud, heavy), (pressure, medium), (wind, strong)}, {({(rain, heavy)}, 1 % 1)})
# ({(cloud, light), (pressure, high), (wind, light)}, {({(rain, heavy)}, 1 % 6), ({(rain, light)}, 7 % 12), ({(rain, none)}, 1 % 4)})
# ({(cloud, light), (pressure, high), (wind, none)}, {({(rain, heavy)}, 1 % 6), ({(rain, light)}, 7 % 12), ({(rain, none)}, 1 % 4)})
# ({(cloud, light), (pressure, high), (wind, strong)}, {({(rain, heavy)}, 1 % 6), ({(rain, light)}, 7 % 12), ({(rain, none)}, 1 % 4)})
# ({(cloud, light), (pressure, low), (wind, light)}, {({(rain, heavy)}, 1 % 6), ({(rain, light)}, 7 % 12), ({(rain, none)}, 1 % 4)})
# ({(cloud, light), (pressure, low), (wind, none)}, {({(rain, heavy)}, 1 % 6), ({(rain, light)}, 7 % 12), ({(rain, none)}, 1 % 4)})
# ({(cloud, light), (pressure, low), (wind, strong)}, {({(rain, heavy)}, 1 % 6), ({(rain, light)}, 7 % 12), ({(rain, none)}, 1 % 4)})
# ({(cloud, light), (pressure, medium), (wind, light)}, {({(rain, heavy)}, 1 % 6), ({(rain, light)}, 7 % 12), ({(rain, none)}, 1 % 4)})
# ({(cloud, light), (pressure, medium), (wind, none)}, {({(rain, heavy)}, 1 % 6), ({(rain, light)}, 7 % 12), ({(rain, none)}, 1 % 4)})
# ({(cloud, light), (pressure, medium), (wind, strong)}, {({(rain, heavy)}, 1 % 6), ({(rain, light)}, 7 % 12), ({(rain, none)}, 1 % 4)})
# ({(cloud, none), (pressure, high), (wind, light)}, {({(rain, heavy)}, 1 % 6), ({(rain, light)}, 7 % 12), ({(rain, none)}, 1 % 4)})
# ({(cloud, none), (pressure, high), (wind, none)}, {({(rain, none)}, 1 % 1)})
# ({(cloud, none), (pressure, high), (wind, strong)}, {({(rain, heavy)}, 1 % 6), ({(rain, light)}, 7 % 12), ({(rain, none)}, 1 % 4)})
# ({(cloud, none), (pressure, low), (wind, light)}, {({(rain, heavy)}, 1 % 6), ({(rain, light)}, 7 % 12), ({(rain, none)}, 1 % 4)})
# ({(cloud, none), (pressure, low), (wind, none)}, {({(rain, none)}, 1 % 1)})
# ({(cloud, none), (pressure, low), (wind, strong)}, {({(rain, heavy)}, 1 % 6), ({(rain, light)}, 7 % 12), ({(rain, none)}, 1 % 4)})
# ({(cloud, none), (pressure, medium), (wind, light)}, {({(rain, heavy)}, 1 % 6), ({(rain, light)}, 7 % 12), ({(rain, none)}, 1 % 4)})
# ({(cloud, none), (pressure, medium), (wind, none)}, {({(rain, none)}, 1 % 1)})
# ({(cloud, none), (pressure, medium), (wind, strong)}, {({(rain, heavy)}, 1 % 6), ({(rain, light)}, 7 % 12), ({(rain, none)}, 1 % 4)})
For some queries the model is ambiguous. For example, when the pressure is low, but there is no cloud and winds are light, the forecast is usually for light rain, but not always,
qq2 = hhaa(llhh([pressure,cloud,wind],[(1,[low,none,light])]))
rpln(aarr(query(qq2,tt,aa,[rain])))
# ({(rain, heavy)}, 0.16666666666666666)
# ({(rain, light)}, 0.5833333333333334)
# ({(rain, none)}, 0.25)
The weather forecast example continues in Transform entropy.