55abstract type AbstractStateType{N} end
66const StateType = AbstractStateType
77
8- # #==============================================================================
9- # # StoredBelief
10- # #==============================================================================
11- abstract type AbstractDensityKind end
8+ # ==============================================================================
9+ # StoredHomotopyBelief
10+ # ==============================================================================
11+ """
12+ AbstractHomotopyTopology
13+
14+ Describes the physical layout of the nodes within a `StoredHomotopyBelief`.
15+
16+ Since all beliefs in the Caesar ecosystem are fundamentally Homotopy densities,
17+ this trait acts as a lightweight dispatch hint (a "Lens Selector"). It indicates
18+ which parts of the tree (Roots vs. Leaves) are currently populated and how they
19+ are wired, without requiring downstream packages to inspect the underlying vectors.
20+
21+ **Role of the Topology Trait:**
22+ - **DFG:** Determines how to serialize and spatial-index the belief in the database.
23+ - **Visualizers:** Decides how to render the data (e.g., drawing ellipses for roots vs. a point cloud for leaves).
24+ - **IIF/AMP:** Selects the correct mathematical view to construct (e.g., `MvNormal` vs. `ManifoldKernelDensity` vs. a full `HomotopyDensity`).
25+
26+ !!! note "State, not Strategy"
27+ The trait purely describes the *current physical shape* of the data (e.g., "I currently only have Roots populated").
28+ It does *not* dictate the solver strategy (e.g., "You must use a parametric solver").
29+ The math engine is always free to convert or expand the data based on the graph's needs.
30+
31+ **Extending:**
32+ If the standard tree-based Homotopy model does not fit your specific data layout
33+ or solver requirements, you are encouraged to extend this abstract type with your
34+ own custom topology struct. Alternatively, if you believe your use case represents
35+ a missing core layout, please open an issue to discuss adding it to the
36+ foundational ecosystem.
37+ """
38+ abstract type AbstractHomotopyTopology end
39+
40+ # --- 1. The Roots ---
41+ " L1 structural nodes only. No L2 samples. (Schema: `means`, `weights`, `shapes` populated. `points` empty.)"
42+ struct RootsOnlyTopology <: AbstractHomotopyTopology end
1243
13- """ Single Gaussian (mean + covariance)."""
14- struct GaussianDensityKind <: AbstractDensityKind end
44+ # --- 2. The Leaves ---
45+ " L2 raw samples only. No L1 structure. (Schema: `points`, `bandwidths` populated. `means` empty.)"
46+ struct LeavesOnlyTopology <: AbstractHomotopyTopology end
1547
16- """ Kernel density / particle-based (points + shared bandwidth)."""
17- struct NonparametricDensityKind <: AbstractDensityKind end
48+ # --- 3. The Full Trees ---
49+ " Tree packed in arrays using 2i, 2i+1 math.(Schema: L1 and L2 populated. Parent arrays empty.)"
50+ struct ImplicitTreeTopology <: AbstractHomotopyTopology end
1851
19- """ Homotopy between particles and Gaussian. "" "
20- struct HomotopyDensityKind <: AbstractDensityKind end
52+ " Full tree using adjacency lists. (Schema: L1, L2, and Parent arrays fully populated.) "
53+ struct ExplicitTreeTopology <: AbstractHomotopyTopology end
2154
22- function StructUtils. lower (:: StructUtils.StructStyle , p:: AbstractDensityKind )
55+ function StructUtils. lower (:: StructUtils.StructStyle , p:: AbstractHomotopyTopology )
2356 return StructUtils. lower (Packed (p))
2457end
25- @choosetype AbstractDensityKind resolvePackedType
26-
27- # TODO naming? Density, DensityRepresentation, StoredBelief, BeliefState, etc?
28- # TODO flatten in State? likeley not for easier serialization of points.
29- @kwdef struct StoredBelief{T <: StateType , P}
30- statekind:: T = T ()# NOTE duplication for serialization, TODO maybe only in State and therefore belief cannot deserialize separately.
31- """ Discriminator for which representation is active."""
32- densitykind:: AbstractDensityKind = NonparametricDensityKind ()
33-
34- # --- Parametric fields (Gaussian / GMM / Homotopy leading modes) ---
35- """ On-manifold component means.
36- Gaussian: length 1. Homotopy: leading (tree_kernel) means."""
37- means:: Vector{P} = P[] # previously `val[1]` for Gaussian
38- """ Component covariances, matching `means`."""
39- covariances:: Vector{Matrix{Float64}} = Matrix{Float64}[] # previously `covar` existed but was stored in `bw` (hacky)
40- " Component weights, matching `means`."
58+ @choosetype AbstractHomotopyTopology resolvePackedType
59+
60+ """
61+ StoredHomotopyBelief{T <: StateType, P}
62+
63+ A multi-resolution "Grove of Trees" representing a manifold belief.
64+ Each tree can be as deep (ExplicitTreeTopology) or as shallow (RootsOnlyTopology)
65+ as the evidence requires, but they all speak the same language of Nodes and Parents.
66+
67+ These are the internal raw beliefs and need to be viewed through a lens such as
68+ provided by AMP for features like pdf evaluation. Organized into structural
69+ Tree/Branch layers (L1) and empirical Leaf layers (L2).
70+
71+ !!! warning "Raw Data Container"
72+ `StoredHomotopyBelief` is the raw data schema used for database storage and serialization.
73+ Mutating this structure in-place is discouraged. Rather, construct a new `State` object
74+ and call `addState!` or `mergeState!`.
75+ """
76+ @kwdef struct StoredHomotopyBelief{T <: StateType , P}
77+ statekind:: T = T ()# NOTE duplication for serialization and self description.
78+ """ A hint for downstream solvers on how to interpret this data (The 'How')"""
79+ topologykind:: AbstractHomotopyTopology = LeavesOnlyTopology ()
80+
81+ # L1 Nodes
82+ """
83+ [Order 0] The relative importance or probability of each node in L1.
84+ """
4185 weights:: Vector{Float64} = Float64[]
86+ """
87+ [Order 1] The location/center of each node, stored directly on the manifold.
88+ """
89+ means:: Vector{P} = P[] # previously `val[1]` for Gaussian
90+ """
91+ [Order 2] The spread/curvature of each node (e.g., Covariance or Precision matrix).
92+ """
93+ shapes:: Vector{Matrix{Float64}} = Matrix{Float64}[] # previously `covar` existed but was stored in `bw` (hacky)
4294
43- # --- Non-parametric / Homotopy leaves ---
44- """ On-manifold sample points. For KDE/HomotopyDensity, these are the leaf kernel means."""
95+ # L2 Nodes
96+ """
97+ The raw empirical samples on the manifold. Used for KDE and particle representations.
98+ """
4599 points:: Vector{P} = P[] # previously `val`
46- """ Shared kernel bandwidth matrix used with ManifoldKernelDensity, see field `covar` for the parametric covariance"""
47- bandwidth:: Union{Nothing, Matrix{Float64}} = zeros (getDimension (T), getDimension (T)) # previously `bw` ---
48- # bandwidth::Matrix{Float64} = zeros(getDimension(T), getDimension(T))
49- # TODO is bandwidth[s] matrix or vector or ::Vector{Matrix{Float64} or ::Vector{Vector{Float64}?
50- # JSON.parse(JSON.json(zeros(0, 0)), Matrix{Float64}) errors, so trying with nothing union
51- end
100+ """
101+ The second-order bandwidths for the non-parametric points, supports variable bandwidth kernels.
102+ """
103+ bandwidths:: Vector{Matrix{Float64}} = Matrix{Float64}[] # previously `bw` ---
52104
53- # FIXME remove old name before v0.29
54- const BeliefRepresentation = StoredBelief
105+ # --- Topology (The Hierarchy) ---
106+ """
107+ L1 Internal Topology: mean_parents[i] = j means means[i] is a child of means[j]. A value of 0 indicates a Root node.
108+ """
109+ mean_parents:: Vector{Int} = Int[]
110+ """
111+ L2-to-L1 Bridge: point_parents[i] = j means points[i] is governed by means[j]. Points are leaves.
112+ """
113+ point_parents:: Vector{Int} = Int[]
114+ end
55115
56- JSON. omit_empty (:: Type{<:StoredBelief } ) = true
116+ JSON. omit_empty (:: Type{<:StoredHomotopyBelief } ) = true
57117
58- function StoredBelief (T:: AbstractStateType )
59- return StoredBelief {typeof(T), getPointType(T)} (; statekind = T)
118+ function StoredHomotopyBelief (T:: AbstractStateType )
119+ return StoredHomotopyBelief {typeof(T), getPointType(T)} (; statekind = T)
60120end
61121
62- function StoredBelief (:: NonparametricDensityKind , T:: AbstractStateType ; kwargs... )
63- return StoredBelief {typeof(T), getPointType(T)} (;
122+ function StoredHomotopyBelief (:: LeavesOnlyTopology , T:: AbstractStateType ; kwargs... )
123+ return StoredHomotopyBelief {typeof(T), getPointType(T)} (;
64124 statekind = T,
65- densitykind = NonparametricDensityKind (),
66- bandwidth = zeros (getDimension (T), getDimension (T)),
125+ topologykind = LeavesOnlyTopology (),
126+ bandwidths = [ zeros (getDimension (T), getDimension (T))] ,
67127 kwargs... ,
68128 )
69129end
70130
71- function StoredBelief (:: GaussianDensityKind , T:: AbstractStateType ; kwargs... )
72- return StoredBelief {typeof(T), getPointType(T)} (;
131+ function StoredHomotopyBelief (:: RootsOnlyTopology , T:: AbstractStateType ; kwargs... )
132+ return StoredHomotopyBelief {typeof(T), getPointType(T)} (;
73133 statekind = T,
74- densitykind = GaussianDensityKind (),
75- bandwidth = nothing ,
134+ topologykind = RootsOnlyTopology (),
76135 kwargs... ,
77136 )
78137end
79138
80139function StructUtils. fielddefaults (
81140 :: StructUtils.StructStyle ,
82- :: Type{StoredBelief {T, P}} ,
141+ :: Type{StoredHomotopyBelief {T, P}} ,
83142) where {T, P}
84143 return (
85144 statekind = T (),
86- densitykind = NonparametricDensityKind (),
145+ topologykind = LeavesOnlyTopology (),
87146 means = P[],
88- covariances = Matrix{Float64}[],
147+ shapes = Matrix{Float64}[],
89148 weights = Float64[],
90149 points = P[],
91- bandwidth = nothing ,
150+ bandwidths = Matrix{Float64}[],
151+ mean_parents = Int[],
152+ point_parents = Int[],
92153 )
93154end
94155
95156function resolveStoredBeliefType (lazyobj)
96157 statekind = liftStateKind (lazyobj. statekind[])
97- return StoredBelief {typeof (statekind), getPointType (statekind)}
158+ return StoredHomotopyBelief {typeof (statekind), getPointType (statekind)}
98159end
99160
100- @choosetype StoredBelief resolveStoredBeliefType
161+ @choosetype StoredHomotopyBelief resolveStoredBeliefType
101162
102163# #==============================================================================
103164# # State
@@ -121,7 +182,7 @@ $(TYPEDFIELDS)
121182 """
122183 Generic stored belief for this state.
123184 """
124- belief:: StoredBelief {T, P} = StoredBelief {T, P} ()# ; statekind = T())
185+ belief:: StoredHomotopyBelief {T, P} = StoredHomotopyBelief {T, P} ()# ; statekind = T())
125186 """ List of symbols for separator variables for this state, used in variable elimination and inference computations."""
126187 separator:: Vector{Symbol} = Symbol[]
127188 """ False if initial numerical values are not yet available or stored values are not ready for further processing yet."""
@@ -132,16 +193,7 @@ $(TYPEDFIELDS)
132193 marginalized:: Bool = false # TODO renamed from ismargin v0.29
133194 """ How many times has a solver updated this state estimate."""
134195 solves:: Int = 0 # TODO renamed from solvedCount v0.29
135-
136- # TODO belief container that can be used for active solver beliefs such as a HomotopyDensity
137- # The type is defined by a trait saved in the StoredBelief and
138- # verbs such as `hydrate!(state)` `persist!(state)` can be used at data at checkpoints.
139- # Forcing an explicit `persist!` acts as a state checkpoint,
140- # ensuring the graph only ever stores fully committed solver results rather than half-computed intermediate math.
141- # abstract type AbstractActiveBelief end
142- # active_belief::Base.RefValue{<:AbstractActiveBelief} = Ref{AbstractActiveBelief}() & (ignore = true,)
143196end
144-
145197# OLD deprecated fields, removed in v0.29, kept here for reference during transition
146198# val::Vector{P} = Vector{P}()
147199# bw::Matrix{Float64} = zeros(0, 0)
153205# events::Dict{Symbol, Threads.Condition} = Dict{Symbol, Threads.Condition}()
154206# dontmargin::Bool = false
155207
208+ # ==============================================================================
209+ # FUTURE VIEW WRAPPER (Internal DFG Placeholder)
210+ # ==============================================================================
211+ # NOTE: The `StoredHomotopyBelief` is currently expressive and fast enough that
212+ # DFG does not need to store a resolved view next to it in memory.
213+ #
214+ # If future profiling requires it, DFG will introduce a verbose View wrapper
215+ # to hold the raw data alongside the instantiated read-only math object.
216+ #
217+ # abstract type AbstractHomotopyBeliefView end
218+ #
219+ # struct HomotopyBeliefView{T, P, M} <: AbstractHomotopyBeliefView
220+ # stored::StoredHomotopyBelief{T, P}
221+ # math_engine::M # Read-only instantiated solver object (e.g., AMP.HomotopyDensity)
222+ # end
223+
156224# #------------------------------------------------------------------------------
157225# # Constructors
158226function State {T} (; kwargs... ) where {T <: StateType }
@@ -178,7 +246,7 @@ function StructUtils.fielddefaults(
178246 :: Type{State{T, P}} ,
179247) where {T, P}
180248 return (
181- belief = StoredBelief {T, P} (; statekind = T ()),
249+ belief = StoredHomotopyBelief {T, P} (; statekind = T ()),
182250 separator = Symbol[],
183251 initialized = false ,
184252 observability = Float64[],
@@ -189,12 +257,12 @@ function StructUtils.fielddefaults(
189257end
190258
191259refMeans (state:: State ) = state. belief. means
192- refCovariances (state:: State ) = state. belief. covariances
260+ refCovariances (state:: State ) = state. belief. shapes
193261refWeights (state:: State ) = state. belief. weights
194262refPoints (state:: State ) = state. belief. points
195- refBandwidth (state:: State ) = state. belief. bandwidth
196-
197- getDensityKind (state:: State ) = state. belief. densitykind
263+ refBandwidth (state:: State ) = state. belief. bandwidths[ 1 ]
264+ refBandwidths (state :: State ) = state . belief . bandwidths
265+ getTopologyKind (state:: State ) = state. belief. topologykind
198266
199267# we can also do somthing like this:
200268function getComponent (state:: State , i)
0 commit comments