Decompositions

Haskell implementation of the Overview/Decompositions

Sections

Definition

Conversion to transform

Conversion to fud

Substrate decompositions

Example - a weather forecast

Definition

A functional definition set decomposition is a model that consists of a tree of fuds that are contingent on components.

The set of functional definition set decompositions $\mathcal{D}_{\mathrm{F}}$ is a subset of the trees of pairs of (i) states, $\mathcal{S}$, and (ii) functional definition sets, $\mathcal{F}$, \[ \begin{eqnarray} \mathcal{D}_{\mathrm{F}} &\subset& \mathrm{trees}(\mathcal{S} \times \mathcal{F}) \end{eqnarray} \] The Tree a generic type is described in Notation. The DecompFud type is defined as a Tree of pairs of State and Fud,

newtype DecompFud = DecompFud (Tree (State,Fud))

A fud decomposition is constructed from a tree of pairs of states and fuds,

treePairStateFudsDecompFud :: Tree (State,Fud) -> Maybe DecompFud

Consider the deck of cards example,

let lluu ll = fromJust $ listsSystem [(v,Set.fromList ww) | (v,ww) <- ll]

let [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"]

let uu = lluu [
      (suit, [hearts, clubs, diamonds, spades]),
      (rank, [jack,queen,king,ace] ++ map ValInt [2..10])]

let vv = Set.fromList [suit, rank]

rp uu
"{(rank,{A,J,K,Q,2,3,4,5,6,7,8,9,10}),(suit,{clubs,diamonds,hearts,spades})}"

rp vv
"{rank,suit}"

let 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 $T_{\mathrm{c}}$ can be constructed relating the suit to the colour,

let lltt kk ww qq = trans (unit (Set.fromList [llss (zip (kk ++ ww) ll) | ll <- qq])) (Set.fromList ww)

let colour = VarStr "colour"
    red = ValStr "red"; black = ValStr "black"

let ttc = lltt [suit] [colour] [
      [hearts, red], 
      [clubs, black], 
      [diamonds, red], 
      [spades, black]]

Another transform $T_{\mathrm{t}}$ can be constructed relating the rank to whether it is a pip card or a face card,

let pip_or_face = VarStr "pip_or_face"
    pip = ValStr "pip"; face = ValStr "face"

let ttt = lltt [rank] [pip_or_face] ([
      [ace, pip], 
      [king, face], 
      [queen, face], 
      [jack, face]] ++ 
      [[ValInt i, pip] | i <- [2..10]])

Let another transform $T_{\mathrm{op}}$ with a derived variable odd_pip have value yes for odd pip cards, and value no otherwise,

let odd_pip = VarStr "odd_pip"
    yes = ValStr "yes"; no = ValStr "no"

let ttop = lltt [rank] [odd_pip] ([
      [ace, yes], 
      [king, no], 
      [queen, no], 
      [jack, no]] ++ 
      [[ValInt i, no] | i <- [2,4..10]] ++ 
      [[ValInt i, yes] | i <- [3,5..9]])

Let $D$ be a fud decomposition, $D \in \mathcal{D}_{\mathrm{F}}$, be constructed from a list of paths,

let lldf zz = fromJust $ treePairStateFudsDecompFud $ pathsTree $ Set.fromList [[(llss ss, llff ff) | (ss,ff) <- ll] | ll <- zz]

let df = lldf [
      [([], [ttop]), ([(odd_pip, no)],  [ttc, ttt])],
      [([], [ttop]), ([(odd_pip, yes)], [ttc])]]

The set of fuds is $\mathrm{fuds}(D) := \{F : ((\cdot,F),\cdot) \in \mathrm{nodes}(D)\}$,

decompFudsSetFud :: DecompFud -> Set.Set Fud 

For example,

let dfqq = decompFudsSetFud

dfqq df == Set.fromList [llff [ttop], llff [ttc], llff [ttc, ttt]]
True

The underlying is $\mathrm{und}(D) := \bigcup \{\mathrm{und}(F) : F \in \mathrm{fuds}(D)\}$,

decompFudsUnderlying :: DecompFud -> Set.Set Variable

For example,

let dfund = decompFudsUnderlying

rp $ dfund df
"{rank,suit}"

Fud decompositions are constrained such that each of the states in child pairs are states in the derived variables of the parent fud, \[ \forall D \in \mathcal{D}_{\mathrm{F}}~\forall ((\cdot,F),E) \in \mathrm{nodes}(D)~\forall ((S,\cdot),\cdot) \in E~(S \in \mathrm{dom}((F^{\mathrm{T}})^{-1})) \]

fder (llff [ttop]) == Set.singleton odd_pip
True

The root nodes have no parent and so their states are constrained to be null, $\forall D \in \mathcal{D}_{\mathrm{F}}~\forall ((S,\cdot),\cdot) \in D~(S = \emptyset)$,

decompFudsTreePairStateFud :: DecompFud -> Tree (State,Fud)

For example,

let dfzz = decompFudsTreePairStateFud

let (ss,_) = Set.findMax (treesRoots (dfzz df))

ss == stateEmpty
True

The fud decomposition, $D$, can be converted to a list of paths,

let dfll = Set.toList . treesPaths . dfzz 

:t dfll df
dfll df :: [[(State, Fud)]]

rpln $ map (fst . unzip) $ dfll df
"[{},{(odd_pip,no)}]"
"[{},{(odd_pip,yes)}]"

dfll df !! 0 !! 0 == (llss [],  llff [ttop])
True

dfll df !! 0 !! 1 == (llss [(odd_pip, no)],  llff [ttc, ttt])
True

dfll df !! 1 !! 1 == (llss [(odd_pip, yes)],  llff [ttc])
True

Given a fud decomposition $D \in \mathcal{D}_{\mathrm{F}}$ having underlying variables $V = \mathrm{und}(D)$, each fud $F \in \mathrm{fuds}(D)$ is contingent on the component $C \in \mathrm{B}(V^{\mathrm{C}})$ implied by the union of the ancestor derived states in the derived variables of the union of the ancestor fuds. Let $L$ be a path in the fud decomposition, $L \in \mathrm{paths}(D)$. Then for each child fud $(\cdot,F) = L_i$, where $i \in \{2 \ldots |L|\}$, the union of the ancestor derived states is $R = \bigcup \{S : j \in \{2 \ldots i\},~(S,\cdot) = L_j\}$, the union of the ancestor fuds is $G = \bigcup \{H : j \in \{1 \ldots i-1\},~(\cdot,H) = L_j\}$, and so the contingent component is $(G^{\mathrm{T}})^{-1}(R)$. In the case where the underlying of the ancestor fud, $G$, is the whole substrate, $\mathrm{und}(G)=V$, then the component is $C = (G^{\mathrm{T}})^{-1}(R) \subseteq V^{\mathrm{C}}$. In the deck of cards example, the second path of the decomposition, $D$, is where odd_pip equals yes,

let ll = dfll df !! 1

length ll
2

rp $ fst $ unzip ll
"[{},{(odd_pip,yes)}]"

let rr = foldl1 sunion [ss | (ss,_) <- take 2 ll]

rp rr
"{(odd_pip,yes)}"

let gg = foldl1 funion [ff | (_,ff) <- take 1 ll]

gg == llff [ttop]
True

The expanded component contains all of the odd pip cards,

let vvc = unit (cart uu vv)

let inv = transformsInverse

let cc = (inv (fftt gg) Map.! rr) `mul` vvc

rpln $ aall cc
"({(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,3),(suit,clubs)},1 % 1)"
"({(rank,3),(suit,diamonds)},1 % 1)"
"({(rank,3),(suit,hearts)},1 % 1)"
"({(rank,3),(suit,spades)},1 % 1)"
"({(rank,5),(suit,clubs)},1 % 1)"
"({(rank,5),(suit,diamonds)},1 % 1)"
"({(rank,5),(suit,hearts)},1 % 1)"
"({(rank,5),(suit,spades)},1 % 1)"
"({(rank,7),(suit,clubs)},1 % 1)"
"({(rank,7),(suit,diamonds)},1 % 1)"
"({(rank,7),(suit,hearts)},1 % 1)"
"({(rank,7),(suit,spades)},1 % 1)"
"({(rank,9),(suit,clubs)},1 % 1)"
"({(rank,9),(suit,diamonds)},1 % 1)"
"({(rank,9),(suit,hearts)},1 % 1)"
"({(rank,9),(suit,spades)},1 % 1)"

The function $\mathrm{cont} \in \mathcal{D}_{\mathrm{F}} \to \mathrm{P}(\mathcal{A} \times \mathcal{F})$ returns the set of component-fud pairs of the fud decomposition. When the fud decomposition, $D$, is applied to a histogram $A \in \mathcal{A}$ in variables $\mathrm{vars}(A) = V$, each fud transform is applied to the contingent slice, $A * C * F^{\mathrm{T}}$ where $(C,F) \in \mathrm{cont}(D)$. Two fuds on the same path $(\cdot,F_1) \in L_j$ and $(\cdot,F_2) \in L_i$ where $L \in \mathrm{paths}(D)$ and $j<i$, are such that the fud $(C_1,F_1) \in \mathrm{cont}(D)$ nearer the root has a component which is a superset of the component of the fud $(C_2,F_2) \in \mathrm{cont}(D)$ nearer the leaves, $C_1 \supset C_2$. So the slice nearer the root is greater than or equal to the slice nearer the leaves, $A * C_1 \geq A * C_2$. That is, the fuds are more and more selectively contingent along the fud decomposition’s paths, and so are applied to smaller and smaller slices. In the case of the deck of cards example, the component, $C$, which consists of the odd pip cards, is a subset of the decomposition root component, which is the cartesian, $V^{\mathrm{C}}$,

cc `leq` vvc
True

(aa `mul` cc) `leq` (aa `mul` vvc)
True

In the case where each of the slice derived are diagonalised, $\forall (C,F) \in \mathrm{cont}(D)~(\mathrm{diagonal}(A * C * F^{\mathrm{T}}))$, the fud decomposition, $D$, is a contingent, layered, redundant model of the sample histogram, $A$.

Conversion to transform

A fud decomposition is a model, so it can be converted to a functional transform, $D^{\mathrm{T}} \in \mathcal{T}_{\mathrm{f}}$. The partition of the fud decomposition transform is equal to the set of components corresponding to those fud derived states that are not parent derived states in the decomposition tree, $\bigcup \{\mathrm{dom}((F^{\mathrm{T}})^{-1}) \setminus \{S : ((S,\cdot),\cdot) \in E\} : ((\cdot,F),E) \in \mathrm{nodes}(D)\}$. The resultant transform has the same underlying variables as the fud decomposition, $\mathrm{und}(D^{\mathrm{T}}) = \mathrm{und}(D)$.

Decompositions are rarely converted to transforms in practice. Useful decompositions generally have large substrates and so the components of a partition of the cartesian are very large. This is because volume varies exponentially with dimension, $v = d^n$. In practice, rather than applying decomposition transforms to sample histograms to obtain the derived histogram, $A * D^{\mathrm{T}}$, decompositions are applied directly to sample histograms to obtain a tree of pairs of derived state $S$ and derived slice histogram $A * C * F^{\mathrm{T}}$,

decompFudsHistogramsApply :: DecompFud -> Histogram -> Tree (State,Histogram)

For example,

let dfapplyll aa df = Set.toList $ treesPaths $ decompFudsHistogramsApply df aa

:t aa `dfapplyll` df
aa `dfapplyll` df :: [[(State, Histogram)]]

rpln $ map (map (\(ss,bb) -> (ss, vars bb, size bb))) $ aa `dfapplyll` df
"[({},{odd_pip},52 % 1),({(odd_pip,no)},{colour,pip_or_face},32 % 1)]"
"[({},{odd_pip},52 % 1),({(odd_pip,yes)},{colour},20 % 1)]"

rpln $ map (fst . unzip) $ aa `dfapplyll` df
"[{},{(odd_pip,no)}]"
"[{},{(odd_pip,yes)}]"

rpln $ aall $ snd $ aa `dfapplyll` df !! 0 !! 0
"({(odd_pip,no)},32 % 1)"
"({(odd_pip,yes)},20 % 1)"

rpln $ aall $ snd $ aa `dfapplyll` df !! 0 !! 1
"({(colour,black),(pip_or_face,face)},6 % 1)"
"({(colour,black),(pip_or_face,pip)},10 % 1)"
"({(colour,red),(pip_or_face,face)},6 % 1)"
"({(colour,red),(pip_or_face,pip)},10 % 1)"

rpln $ aall $ snd $ aa `dfapplyll` df !! 1 !! 1
"({(colour,black)},10 % 1)"
"({(colour,red)},10 % 1)"

A similar function preserves the underlying variables, $A * C * \mathrm{his}(F^{\mathrm{T}})~\%~(\mathrm{und}(F) \cup \mathrm{der}(F))$,

decompFudsHistogramsMultiply :: DecompFud -> Histogram -> Tree (State,Histogram)

For example,

let dfmulll aa df = Set.toList $ treesPaths $ decompFudsHistogramsMultiply df aa

:t aa `dfmulll` df
aa `dfmulll` df :: [[(State, Histogram)]]

rpln $ map (map (\(ss,bb) -> (ss, vars bb, size bb))) $ aa `dfmulll` df
"[({},{odd_pip,rank,suit},52 % 1),({(odd_pip,no)},{colour,pip_or_face,rank,suit},32 % 1)]"
"[({},{odd_pip,rank,suit},52 % 1),({(odd_pip,yes)},{colour,rank,suit},20 % 1)]"

rpln $ map (fst . unzip) $ aa `dfmulll` df
"[{},{(odd_pip,no)}]"
"[{},{(odd_pip,yes)}]"

rpln $ aall $ snd $ aa `dfmulll` df !! 0 !! 0
"({(odd_pip,no),(rank,J),(suit,clubs)},1 % 1)"
"({(odd_pip,no),(rank,J),(suit,diamonds)},1 % 1)"
"({(odd_pip,no),(rank,J),(suit,hearts)},1 % 1)"
"({(odd_pip,no),(rank,J),(suit,spades)},1 % 1)"
"({(odd_pip,no),(rank,K),(suit,clubs)},1 % 1)"
"({(odd_pip,no),(rank,K),(suit,diamonds)},1 % 1)"
...
"({(odd_pip,yes),(rank,7),(suit,hearts)},1 % 1)"
"({(odd_pip,yes),(rank,7),(suit,spades)},1 % 1)"
"({(odd_pip,yes),(rank,9),(suit,clubs)},1 % 1)"
"({(odd_pip,yes),(rank,9),(suit,diamonds)},1 % 1)"
"({(odd_pip,yes),(rank,9),(suit,hearts)},1 % 1)"
"({(odd_pip,yes),(rank,9),(suit,spades)},1 % 1)"

rpln $ aall $ snd $ aa `dfmulll` df !! 0 !! 1
"({(colour,black),(pip_or_face,face),(rank,J),(suit,clubs)},1 % 1)"
"({(colour,black),(pip_or_face,face),(rank,J),(suit,spades)},1 % 1)"
"({(colour,black),(pip_or_face,face),(rank,K),(suit,clubs)},1 % 1)"
"({(colour,black),(pip_or_face,face),(rank,K),(suit,spades)},1 % 1)"
"({(colour,black),(pip_or_face,face),(rank,Q),(suit,clubs)},1 % 1)"
"({(colour,black),(pip_or_face,face),(rank,Q),(suit,spades)},1 % 1)"
...
"({(colour,red),(pip_or_face,pip),(rank,6),(suit,diamonds)},1 % 1)"
"({(colour,red),(pip_or_face,pip),(rank,6),(suit,hearts)},1 % 1)"
"({(colour,red),(pip_or_face,pip),(rank,8),(suit,diamonds)},1 % 1)"
"({(colour,red),(pip_or_face,pip),(rank,8),(suit,hearts)},1 % 1)"
"({(colour,red),(pip_or_face,pip),(rank,10),(suit,diamonds)},1 % 1)"
"({(colour,red),(pip_or_face,pip),(rank,10),(suit,hearts)},1 % 1)"

rpln $ aall $ snd $ aa `dfmulll` df !! 1 !! 1
"({(colour,black),(rank,A),(suit,clubs)},1 % 1)"
"({(colour,black),(rank,A),(suit,spades)},1 % 1)"
"({(colour,black),(rank,3),(suit,clubs)},1 % 1)"
"({(colour,black),(rank,3),(suit,spades)},1 % 1)"
"({(colour,black),(rank,5),(suit,clubs)},1 % 1)"
"({(colour,black),(rank,5),(suit,spades)},1 % 1)"
...
"({(colour,red),(rank,5),(suit,diamonds)},1 % 1)"
"({(colour,red),(rank,5),(suit,hearts)},1 % 1)"
"({(colour,red),(rank,7),(suit,diamonds)},1 % 1)"
"({(colour,red),(rank,7),(suit,hearts)},1 % 1)"
"({(colour,red),(rank,9),(suit,diamonds)},1 % 1)"
"({(colour,red),(rank,9),(suit,hearts)},1 % 1)"

Queries may be made too. In this case, however, the model underlying equals the entire substrate, $\mathrm{und}(D) = K = V$, so there are no label variables. The query is merely classified by the model, $D$,

decompFudsHistogramsHistogramsQuery :: DecompFud -> Histogram -> Histogram -> Tree (State,Histogram)

For example,

let red aa ll = setVarsHistogramsReduce (Set.fromList ll) aa
    queryll qq df aa ll = map (map (\(ss,bb) -> (ss, norm (bb `red` ll)))) $ Set.toList $ treesPaths $ decompFudsHistogramsHistogramsQuery df aa qq

let qq = single (llss [(rank,ace),(suit,spades)]) 1

:t queryll qq df aa []
queryll qq df aa [] :: [[(State, Histogram)]]

rpln $ map (fst . unzip) $ queryll qq df aa []
"[{},{(odd_pip,yes)}]"

rpln $ aarr $ snd $ queryll qq df aa [] !! 0 !! 1
"({},1.0)"

let qq = single (llss [(rank,queen),(suit,hearts)]) 1

rpln $ map (fst. unzip) $ queryll qq df aa []
"[{},{(odd_pip,no)}]"

Conversion to fud

The tree of a fud decomposition is sometimes unwieldy, so consider the fud decomposition fud, $D^{\mathrm{F}} \in \mathcal{F}$, which is the intermediate fud used in the construction of the fud decomposition transform, $D^{\mathrm{T}}$. The decomposition fud is defined as the union of the decomposition fuds and the nullable fud, $D^{\mathrm{F}} := \bigcup \mathrm{fuds}(D) \cup \mathrm{nullable}(U)(D^{\mathrm{D}})$. The nullable fud, $\mathrm{nullable}(U)(D^{\mathrm{D}})$, is defined in section ‘Decompositions’ of the paper. It consists of a layer of transforms which is added on top of the union of the decomposition fuds, $\bigcup \mathrm{fuds}(D)$. Each derived variable in the fud union, $w \in \mathrm{der}(F)$ where $F \in \mathrm{fuds}(D)$, is in the underlying of a corresponding transform, $w \in \mathrm{und}(T_w)$, in the nullable layer. The transform derived consists of a nullable variable $\{w’\} = \mathrm{der}(T_w)$. This nullable variable, $w’$, has the same values as its underlying variable, $w$, but with an additional $\mathrm{null}$ value, $U_{w’} = U_w \cup \{\mathrm{null}\}$. If the fud, $F$, is not the root fud, there is also a contingent variable $c$ with values corresponding to the fud’s in-slice and out-slice states, $U_c = \{\mathrm{in},\mathrm{out}\}$. That is, given contingent state $S \in C^{\mathrm{S}}$, where $(C,F) \in \mathrm{cont}(D)$, the derived state, $R$, is such that $(c,\mathrm{in}) \in R$. Similarly, if $S \in V^{\mathrm{CS}} \setminus C^{\mathrm{S}}$, then $(c,\mathrm{out}) \in R$. The underlying of nullable variable’s transform will also contain the contingent variable, $\{c,w\} = \mathrm{und}(T_w)$. The nullable variable, $w’$, is constrained by the transform, $T_w$, to be in the $\mathrm{null}$ value whenever the contingent variable, $c$, is in the $\mathrm{out}$ value, and to be in the value of the underlying variable, $w$, otherwise. That is, $(c,\mathrm{out}) \in R \implies (w’,\mathrm{null}) \in R$, and $(c,\mathrm{in}) \in R \implies (w’,R_w) \in R$. In this way, there is no need to navigate the slices of the decomposition. The fud decomposition fud, $D^{\mathrm{F}}$, can be analysed by examining the effective states of reductions to its nullable derived variables, $\mathrm{der}(D^{\mathrm{F}})$.

Substrate decompositions

Given a set of substrate variables $V$, the set of substrate fud decompositions $\mathcal{D}_{\mathrm{F},U,V}$ is a subset of fud decompositions, $\mathcal{D}_{\mathrm{F},U,V} \subset \mathcal{D}_{\mathrm{F}}$, that contain only substrate fuds, $\forall D \in \mathcal{D}_{\mathrm{F},U,V}~\forall F \in \mathrm{fuds}(D)~(F \in \mathcal{F}_{U,V})$. In addition, each fud is unique in a path, $\forall D \in \mathcal{D}_{\mathrm{F},U,V}~\forall L \in \mathrm{paths}(D)~(|\{F : (\cdot,(\cdot,F)) \in L\}| = |L|)$.

systemsSetVarsSetDecompFudSubstrate :: System -> Set.Set Variable -> Maybe (Set.Set DecompFud)

For example,

let dfvv uu = fromJust $ systemsSetVarsSetDecompFudSubstrate uu (uvars uu)

Set.size $ dfvv $ systemEmpty
2

rpln $ Set.toList $ dfvv $ systemEmpty
"{(({},{}),{(({},{({({({ { {} } },{ {} })},1 % 1)},{ { { {} } } })}),{})})}"
"{(({},{({({({ { {} } },{ {} })},1 % 1)},{ { { {} } } })}),{(({({ { {} } },{ {} })},{}),{})})}"

Similarly, the infinite-layer substrate fud decompositions $\mathcal{D}_{\mathrm{F},\infty,U,V}$ is the superset of the substrate fud decompositions, $\mathcal{D}_{\mathrm{F},\infty,U,V} \supset \mathcal{D}_{\mathrm{F},U,V}$, that contain only infinite-layer substrate fuds, $\forall D \in \mathcal{D}_{\mathrm{F},\infty,U,V}~\forall F \in \mathrm{fuds}(D)~(F \in \mathcal{F}_{\infty,U,V})$. The cardinality of the infinite-layer substrate fud decomposition set is infinite, $|\mathcal{D}_{\mathrm{F},\infty,U,V}| = \infty$.

Example - a weather forecast

Some of the concepts above regarding functional definition set decompositions can be demonstrated with the sample of some weather measurements created in States, histories and histograms, Transforms and Functional definition sets. Here we add an additional pressure variable pressureb with the same values as pressure. We also add an additional history of stormy weather,

let lluu ll = fromJust $ listsSystem [(v,Set.fromList ww) | (v,ww) <- ll]
    llhh vv ev = fromJust $ listsHistory [(IdInt i, llss (zip vv ll)) | (i,ll) <- ev]
    hadd hh gg = fromJust $ pairHistoriesAdd hh gg
    ared aa vv = setVarsHistogramsReduce vv aa
    red aa ll = setVarsHistogramsReduce (Set.fromList ll) aa
    ssplit ll aa = Set.toList (setVarsSetStatesSplit (Set.fromList ll) (states aa))
    lltt kk ww qq = trans (unit (Set.fromList [llss (zip (kk ++ ww) ll) | ll <- qq])) (Set.fromList ww)
    lldf zz = fromJust $ treePairStateFudsDecompFud $ pathsTree $ Set.fromList [[(llss ss, llff ff) | (ss,ff) <- ll] | ll <- zz]
    query qq tt aa ll = norm (qq `tmul` tt `mul` ttaa tt `mul` aa `red` ll)
    ent = histogramsEntropy
    cent = transformsHistogramsEntropyComponent
    rent aa bb = let a = fromRational (size aa); b = fromRational (size bb) in (a+b) * ent (aa `add` bb) - a * ent aa - b * ent bb
    tlent tt aa ll = setVarsTransformsHistogramsEntropyLabel (vars aa `Set.difference` (Set.fromList ll)) tt aa
    tlalgn tt aa ll = algn (aa `mul` ttaa tt `ared` (der tt `Set.union` Set.fromList ll))
    layer ff v = fudsSetVarsLayer ff (Set.singleton v)
    dfmulll aa df = Set.toList $ treesPaths $ decompFudsHistogramsMultiply df aa
    queryll qq df aa ll = map (map (\(ss,bb) -> (ss, norm (bb `red` ll)))) $ Set.toList $ treesPaths $ decompFudsHistogramsHistogramsQuery df aa qq

let [pressure,pressureb,cloud,wind,rain] = map VarStr ["pressure","pressureb","cloud","wind","rain"]

let [low,medium,high,none,light,heavy,strong] = map ValStr ["low","medium","high","none","light","heavy","strong"]


let uu = lluu [
      (pressure, [low,medium,high]),
      (pressureb, [low,medium,high]),
      (cloud,    [none,light,heavy]),
      (wind,     [none,light,strong]),
      (rain,     [none,light,heavy])]

let vv = uvars uu

let hh1 = llhh [pressure,pressureb,cloud,wind,rain] [
      (1,[high,high,none,none,none]),
      (2,[medium,high,light,none,light]),
      (3,[high,medium,none,light,none]),
      (4,[low,medium,heavy,strong,heavy]),
      (5,[low,low,none,light,light]),
      (6,[medium,medium,none,light,light]),
      (7,[low,medium,heavy,light,heavy]),
      (8,[high,medium,none,light,none]),
      (9,[medium,low,light,strong,heavy]),
      (10,[medium,medium,light,light,light]),
      (11,[high,high,light,light,heavy]),
      (12,[medium,high,none,none,none]),
      (13,[medium,low,light,none,none]),
      (14,[high,medium,light,strong,light]),
      (15,[medium,medium,none,light,light]),
      (16,[low,medium,heavy,strong,heavy]),
      (17,[low,low,heavy,light,heavy]),
      (18,[high,medium,none,none,none]),
      (19,[low,low,light,none,light]),
      (20,[high,high,none,none,none])]

let hh2 = llhh [pressure,pressureb,cloud,wind,rain] [
      (1,[high,low,none,none,light]),
      (2,[low,high,light,none,light]),
      (3,[low,high,heavy,strong,heavy]),
      (4,[low,high,heavy,light,heavy]),
      (5,[high,low,light,strong,heavy]),
      (6,[low,high,light,light,light]),
      (7,[low,high,light,light,heavy]),
      (8,[low,high,heavy,strong,heavy]),
      (9,[high,low,heavy,light,heavy]),
      (10,[high,low,light,none,light])]

let aa = hhaa (hh1 `hadd` hh2)

let vvc = unit (cart uu vv)

rp uu
"{(cloud,{heavy,light,none}),(pressure,{high,low,medium}),(pressureb,{high,low,medium}),(rain,{heavy,light,none}),(wind,{light,none,strong})}"

rp vv
"{cloud,pressure,pressureb,rain,wind}"

rpln $ aall aa
"({(cloud,heavy),(pressure,high),(pressureb,low),(rain,heavy),(wind,light)},1 % 1)"
"({(cloud,heavy),(pressure,low),(pressureb,high),(rain,heavy),(wind,light)},1 % 1)"
"({(cloud,heavy),(pressure,low),(pressureb,high),(rain,heavy),(wind,strong)},2 % 1)"
"({(cloud,heavy),(pressure,low),(pressureb,low),(rain,heavy),(wind,light)},1 % 1)"
"({(cloud,heavy),(pressure,low),(pressureb,medium),(rain,heavy),(wind,light)},1 % 1)"
"({(cloud,heavy),(pressure,low),(pressureb,medium),(rain,heavy),(wind,strong)},2 % 1)"
"({(cloud,light),(pressure,high),(pressureb,high),(rain,heavy),(wind,light)},1 % 1)"
"({(cloud,light),(pressure,high),(pressureb,low),(rain,heavy),(wind,strong)},1 % 1)"
"({(cloud,light),(pressure,high),(pressureb,low),(rain,light),(wind,none)},1 % 1)"
"({(cloud,light),(pressure,high),(pressureb,medium),(rain,light),(wind,strong)},1 % 1)"
"({(cloud,light),(pressure,low),(pressureb,high),(rain,heavy),(wind,light)},1 % 1)"
"({(cloud,light),(pressure,low),(pressureb,high),(rain,light),(wind,light)},1 % 1)"
"({(cloud,light),(pressure,low),(pressureb,high),(rain,light),(wind,none)},1 % 1)"
"({(cloud,light),(pressure,low),(pressureb,low),(rain,light),(wind,none)},1 % 1)"
"({(cloud,light),(pressure,medium),(pressureb,high),(rain,light),(wind,none)},1 % 1)"
"({(cloud,light),(pressure,medium),(pressureb,low),(rain,heavy),(wind,strong)},1 % 1)"
"({(cloud,light),(pressure,medium),(pressureb,low),(rain,none),(wind,none)},1 % 1)"
"({(cloud,light),(pressure,medium),(pressureb,medium),(rain,light),(wind,light)},1 % 1)"
"({(cloud,none),(pressure,high),(pressureb,high),(rain,none),(wind,none)},2 % 1)"
"({(cloud,none),(pressure,high),(pressureb,low),(rain,light),(wind,none)},1 % 1)"
"({(cloud,none),(pressure,high),(pressureb,medium),(rain,none),(wind,light)},2 % 1)"
"({(cloud,none),(pressure,high),(pressureb,medium),(rain,none),(wind,none)},1 % 1)"
"({(cloud,none),(pressure,low),(pressureb,low),(rain,light),(wind,light)},1 % 1)"
"({(cloud,none),(pressure,medium),(pressureb,high),(rain,none),(wind,none)},1 % 1)"
"({(cloud,none),(pressure,medium),(pressureb,medium),(rain,light),(wind,light)},2 % 1)"

size aa
30 % 1

Create a transform $T_{\mathrm{cw}}$ which relates cloud and wind,

let cloud_and_wind = VarStr "cloud_and_wind"

let ttcw = 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]]

Create a transform $T_{\mathrm{cp}}$ that relates cloud and pressure,

let cloud_and_pressure = VarStr "cloud_and_pressure"

let ttcp = lltt [cloud,pressure] [cloud_and_pressure] [
      [none, high, none],
      [none, medium, light],
      [none, low, light],
      [light, high, light],
      [light, medium, light],
      [light, low, light],
      [heavy, high, strong],
      [heavy, medium, strong],
      [heavy, low, strong]]

Create a transform $T_{\mathrm{sc}}$ which rolls together the none and light values of the cloud variable,

let storm_cloud = VarStr "storm_cloud"

let ttsc = lltt [cloud] [storm_cloud] [
      [none, light],
      [light, light],
      [heavy, heavy]]

Now create a transform $T_{\mathrm{s}}$ that relates pressure and pressureb to detect stormy weather,

let storm = VarStr "storm"
    yes = ValStr "yes"; no = ValStr "no"

let tts = lltt [pressure,pressureb] [storm] [
      [low, low, no],
      [low, medium, no],
      [low, high, yes],
      [medium, low, no],
      [medium, medium, no],
      [medium, high, no],
      [high, low, yes],
      [high, medium, no],
      [high, high, no]]

That is, a storm is where the two pressure variables are at opposite extremes.

Now we create a functional definition set decomposition $D$ which partitions the cartesian into stormy and normal weather. When it is stormy, the cloud is highly aligned with the rain,

let df = lldf [
      [([], [tts]), ([(storm, no)],  [ttcw, ttcp])],
      [([], [tts]), ([(storm, yes)], [ttsc])]]

Consider the multiplication of the sample histogram and the decomposition,

rpln $ map (map (\(ss,bb) -> (ss, vars bb, size bb))) $ aa `dfmulll` df
"[({},{cloud,pressure,pressureb,rain,storm,wind},30 % 1),({(storm,no)},{cloud,cloud_and_pressure,cloud_and_wind,pressure,pressureb,rain,wind},20 % 1)]"
"[({},{cloud,pressure,pressureb,rain,storm,wind},30 % 1),({(storm,yes)},{cloud,pressure,pressureb,rain,storm_cloud,wind},10 % 1)]"

The first path is the normal weather slice,

let (_,aa1) = aa `dfmulll` df !! 0 !! 1

aa1 `ared` vv == hhaa hh1
True

If a query is in this slice the fud is just the fud $F = \{T_{\mathrm{cw}},T_{\mathrm{cp}}\}$ discussed in Functional definition sets. The relative entropy and label alignment are different now because the substrate now contains the pressure2 variable,

rent (aa1 `tmul` (fftt (llff [ttcw, ttcp]))) (vvc `tmul` (fftt (llff [ttcw, ttcp])))
2.4392475869399846

tlalgn (fftt (llff [ttcw, ttcp])) aa1 [rain] - tlalgn (fftt (llff [ttcw, ttcp])) (ind aa1) [rain]
14.05877382277943

algn aa1
13.993685678223834

but the the label entropy is unchanged,

tlent (fftt (llff [ttcw, ttcp])) aa1 [rain]
8.018185525433372

The second path is the stormy weather slice,

let (_,aa2) = aa `dfmulll` df !! 1 !! 1

aa2 `ared` vv == hhaa hh2
True

If a query is in this slice the fud is just the fud of the transform of a rolled cloud variable, $\{T_{\mathrm{sc}}\}$. The relative entropy is

rent (aa2 `tmul` (fftt (llff [ttsc]))) (vvc `tmul` (fftt (llff [ttsc])))
9.317574090613334e-2

tlalgn (fftt (llff [ttsc])) aa2 [rain] - tlalgn (fftt (llff [ttsc])) (ind aa2) [rain]
1.9133297116444252

algn aa2
5.656670558662346

The label entropy is

tlent (fftt (llff [ttsc])) aa2 [rain]
3.8190850097688767

In the case of normal weather with medium pressure, heavy cloud and light winds, the forecast for rain is heavy,

let qq1 = hhaa $ llhh [pressure,pressureb,cloud,wind] [(1,[medium,medium,heavy,light])]

rpln $ map (fst. unzip) $ queryll qq1 df aa [rain]
"[{},{(storm,no)}]"

rpln $ aarr $ snd $ queryll qq1 df aa [rain] !! 0 !! 1
"({(rain,heavy)},1.0)"

In the case of stormy weather with low pressure, heavy cloud and light winds, the forecast for rain is also heavy,

let qq1s = hhaa $ llhh [pressure,pressureb,cloud,wind] [(1,[low,high,heavy,light])]

rpln $ map (fst. unzip) $ queryll qq1s df aa [rain]
"[{},{(storm,yes)}]"

rpln $ aarr $ snd $ queryll qq1s df aa [rain] !! 0 !! 1
"({(rain,heavy)},1.0)"

In the case of normal weather with low pressure, but no cloud and light winds, the prediction is ambiguous,

let qq2 = hhaa $ llhh [pressure,pressureb,cloud,wind] [(1,[low,medium,none,light])]

rpln $ map (fst. unzip) $ queryll qq2 df aa [rain]
"[{},{(storm,no)}]"

rpln $ aarr $ snd $ queryll qq2 df aa [rain] !! 0 !! 1
"({(rain,heavy)},0.2)"
"({(rain,light)},0.7)"
"({(rain,none)},0.1)"

In the case of stormy weather with low pressure, but no cloud and light winds, the prediction is ambiguous but wet,

let qq2s = hhaa $ llhh [pressure,pressureb,cloud,wind] [(1,[low,high,none,light])]

rpln $ map (fst. unzip) $ queryll qq2s df aa [rain]
"[{},{(storm,yes)}]"

rpln $ aarr $ snd $ queryll qq2s df aa [rain] !! 0 !! 1
"({(rain,heavy)},0.3333333333333333)"
"({(rain,light)},0.6666666666666666)"

In the case of normal weather with high pressure, no cloud and strong winds, the prediction is for dry,

let qq3 = hhaa $ llhh [pressure,pressureb,cloud,wind] [(1,[high,medium,none,strong])]

rpln $ map (fst. unzip) $ queryll qq3 df aa [rain]
"[{},{(storm,no)}]"

rpln $ aarr $ snd $ queryll qq3 df aa [rain] !! 0 !! 1
"({(rain,none)},1.0)"

In the case of stormy weather with high pressure, no cloud and strong winds, the prediction is for wet,

let qq3s = hhaa $ llhh [pressure,pressureb,cloud,wind] [(1,[high,low,none,strong])]

rpln $ map (fst. unzip) $ queryll qq3s df aa [rain]
"[{},{(storm,yes)}]"

rpln $ aarr $ snd $ queryll qq3s df aa [rain] !! 0 !! 1
"({(rain,heavy)},0.3333333333333333)"
"({(rain,light)},0.6666666666666666)"

top