207 lines
8.7 KiB
Plaintext
207 lines
8.7 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "clustertree_intro_md"
|
|
},
|
|
"source": [
|
|
"# ClusterTree"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "clustertree_desc_md"
|
|
},
|
|
"source": [
|
|
"A `ClusterTree` is a more general structure than an `EliminationTree` or `JunctionTree`. It represents a tree where each node (a 'Cluster') contains a subset of factors from an original factor graph. The key property is that the tree must be 'family preserving', meaning each original factor must belong entirely within a single cluster.\n",
|
|
"\n",
|
|
"`ClusterTree` itself is a base class. `EliminatableClusterTree` adds the ability to perform elimination, and `JunctionTree` is a specific type of `EliminatableClusterTree` derived from an `EliminationTree`.\n",
|
|
"\n",
|
|
"Direct use of `ClusterTree` in typical Python applications is less common than `JunctionTree` or `BayesTree`, as it's often an intermediate representation."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "clustertree_colab_md"
|
|
},
|
|
"source": [
|
|
"<a href=\"https://colab.research.google.com/github/borglab/gtsam/blob/develop/gtsam/inference/doc/ClusterTree.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"metadata": {
|
|
"id": "clustertree_pip_code"
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Requirement already satisfied: gtsam in c:\\users\\porte\\miniconda3\\envs\\gtsam\\lib\\site-packages (4.3a0)Note: you may need to restart the kernel to use updated packages.\n",
|
|
"\n",
|
|
"Requirement already satisfied: numpy>=1.11.0 in c:\\users\\porte\\miniconda3\\envs\\gtsam\\lib\\site-packages (from gtsam) (2.2.1)\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%pip install gtsam"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"metadata": {
|
|
"id": "clustertree_import_code"
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"import gtsam\n",
|
|
"import numpy as np\n",
|
|
"\n",
|
|
"# Note: ClusterTree itself might not be directly exposed or used.\n",
|
|
"# We typically interact with JunctionTree or BayesTree which build upon it.\n",
|
|
"# We'll demonstrate concepts using JunctionTree which inherits Cluster features.\n",
|
|
"from gtsam import GaussianFactorGraph, Ordering, VariableIndex, GaussianBayesTree\n",
|
|
"from gtsam import symbol_shorthand\n",
|
|
"\n",
|
|
"X = symbol_shorthand.X\n",
|
|
"L = symbol_shorthand.L"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "clustertree_concept_md"
|
|
},
|
|
"source": [
|
|
"## Concept and Relation to JunctionTree\n",
|
|
"\n",
|
|
"A `JunctionTree` *is a* `ClusterTree` (specifically, an `EliminatableClusterTree`). It's constructed during multifrontal elimination. Each node in the `JunctionTree` is a `Cluster` containing factors that will be eliminated together to form a clique in the resulting `BayesTree`.\n",
|
|
"\n",
|
|
"We will create a `JunctionTree` and examine its properties, which include those inherited from `ClusterTree`."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"metadata": {
|
|
"colab": {
|
|
"base_uri": "https://localhost:8080/"
|
|
},
|
|
"id": "clustertree_jt_code",
|
|
"outputId": "ef012345-6789-abcd-ef01-23456789abcd"
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Junction Tree (as ClusterTree): \n",
|
|
": cliques: 2, variables: 5\n",
|
|
"- p(x1 l2 x2 )\n",
|
|
" R = [ 1.61245 -0.620174 -0.620174 ]\n",
|
|
" [ 0 1.27098 -1.08941 ]\n",
|
|
" [ 0 0 0.654654 ]\n",
|
|
" d = [ 0 0 0 ]\n",
|
|
" mean: 3 elements\n",
|
|
" l2: 0\n",
|
|
" x1: 0\n",
|
|
" x2: 0\n",
|
|
" logNormalizationConstant: -2.46292\n",
|
|
" No noise model\n",
|
|
"| - p(l1 x0 | x1)\n",
|
|
" R = [ 1.41421 -0.707107 ]\n",
|
|
" [ 0 1.58114 ]\n",
|
|
" S[x1] = [ -0.707107 ]\n",
|
|
" [ -0.948683 ]\n",
|
|
" d = [ 0 0 ]\n",
|
|
" logNormalizationConstant: -1.03316\n",
|
|
" No noise model\n"
|
|
]
|
|
},
|
|
{
|
|
"ename": "AttributeError",
|
|
"evalue": "'gtsam.gtsam.GaussianBayesTree' object has no attribute 'roots'",
|
|
"output_type": "error",
|
|
"traceback": [
|
|
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
|
|
"\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)",
|
|
"Cell \u001b[1;32mIn[8], line 28\u001b[0m\n\u001b[0;32m 25\u001b[0m bayes_tree\u001b[38;5;241m.\u001b[39mprint() \u001b[38;5;66;03m# Printing BayesTree shows clique structure\u001b[39;00m\n\u001b[0;32m 27\u001b[0m \u001b[38;5;66;03m# Access root cluster(s)\u001b[39;00m\n\u001b[1;32m---> 28\u001b[0m roots \u001b[38;5;241m=\u001b[39m \u001b[43mbayes_tree\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mroots\u001b[49m()\n\u001b[0;32m 29\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m roots:\n\u001b[0;32m 30\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124mAccessing a root cluster (node):\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n",
|
|
"\u001b[1;31mAttributeError\u001b[0m: 'gtsam.gtsam.GaussianBayesTree' object has no attribute 'roots'"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Create a graph (same as BayesTree example)\n",
|
|
"graph = GaussianFactorGraph()\n",
|
|
"model = gtsam.noiseModel.Isotropic.Sigma(1, 1.0)\n",
|
|
"graph.add(X(0), -np.eye(1), np.zeros(1), model)\n",
|
|
"graph.add(X(0), -np.eye(1), X(1), np.eye(1), np.zeros(1), model)\n",
|
|
"graph.add(X(1), -np.eye(1), X(2), np.eye(1), np.zeros(1), model)\n",
|
|
"graph.add(L(1), -np.eye(1), X(0), np.eye(1), np.zeros(1), model)\n",
|
|
"graph.add(L(1), -np.eye(1), X(1), np.eye(1), np.zeros(1), model)\n",
|
|
"graph.add(L(2), -np.eye(1), X(1), np.eye(1), np.zeros(1), model)\n",
|
|
"graph.add(L(2), -np.eye(1), X(2), np.eye(1), np.zeros(1), model)\n",
|
|
"\n",
|
|
"ordering = Ordering.Colamd(VariableIndex(graph))\n",
|
|
"\n",
|
|
"# Create a Junction Tree (implicitly uses ClusterTree structure)\n",
|
|
"# Note: JunctionTree constructor might not be directly exposed.\n",
|
|
"# It's usually an intermediate in eliminateMultifrontal.\n",
|
|
"# We might need to construct it indirectly or focus on BayesTree access.\n",
|
|
"\n",
|
|
"# Let's get the BayesTree first, as JunctionTree creation is internal.\n",
|
|
"bayes_tree = graph.eliminateMultifrontal(ordering)\n",
|
|
"\n",
|
|
"# We can print the BayesTree, which shows the cluster structure\n",
|
|
"# (Cliques in BayesTree correspond to Clusters in JunctionTree)\n",
|
|
"print(\"Junction Tree (as ClusterTree): \")\n",
|
|
"bayes_tree.print() # Printing BayesTree shows clique structure\n",
|
|
"\n",
|
|
"# Access root cluster(s)\n",
|
|
"roots = bayes_tree.roots()\n",
|
|
"if roots:\n",
|
|
" print(\"\\nAccessing a root cluster (node):\")\n",
|
|
" root_clique = roots[0]\n",
|
|
" # In the JunctionTree, this node would contain the factors that *produced*\n",
|
|
" # the conditional in the BayesTree clique. We can see the involved keys.\n",
|
|
" root_clique.print(\"\", gtsam.DefaultKeyFormatter) # Print clique details\n",
|
|
"\n",
|
|
"print(f\"\\nNumber of roots: {len(roots)}\")\n",
|
|
"\n",
|
|
"# Direct instantiation or manipulation of Cluster/JunctionTree nodes\n",
|
|
"# is less common in Python than using the results (BayesTree)."
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"colab": {
|
|
"provenance": []
|
|
},
|
|
"kernelspec": {
|
|
"display_name": "gtsam",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.13.1"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 0
|
|
}
|