gtsam/gtsam/inference/doc/ClusterTree.ipynb

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
}