267 lines
8.7 KiB
Plaintext
267 lines
8.7 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "conditional_intro_md"
|
|
},
|
|
"source": [
|
|
"# Conditional"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "conditional_desc_md"
|
|
},
|
|
"source": [
|
|
"`gtsam.Conditional` is the base class for conditional probability distributions or densities that result from variable elimination.\n",
|
|
"\n",
|
|
"Let $F$ be the set of frontal variables and $S$ be the set of parent (separator) variables. A conditional represents:\n",
|
|
"\n",
|
|
"$$\n",
|
|
"P(F | S)\n",
|
|
"$$\n",
|
|
"The methods `evaluate`, `logProbability`, and `error` are related:\n",
|
|
"$$\n",
|
|
"\\text{evaluate}(F, S) = P(F | S)\n",
|
|
"$$\n",
|
|
"$$\n",
|
|
"\\text{logProbability}(F, S) = \\log P(F | S)\n",
|
|
"$$\n",
|
|
"$$\n",
|
|
"\\text{logProbability}(F, S) = -(\\text{negLogConstant} + \\text{error}(F, S))\n",
|
|
"$$\n",
|
|
"where `negLogConstant` is $-\\log k$ for the normalization constant $k$ ensuring $\\int P(F|S) dF = 1$.\n",
|
|
"\n",
|
|
"Like `gtsam.Factor`, you typically don't instantiate `gtsam.Conditional` directly. Instead, you work with derived classes obtained from elimination, such as:\n",
|
|
"* `gtsam.GaussianConditional`\n",
|
|
"* `gtsam.DiscreteConditional`\n",
|
|
"* `gtsam.HybridGaussianConditional`\n",
|
|
"* `gtsam.SymbolicConditional`\n",
|
|
"\n",
|
|
"This notebook demonstrates the common interface provided by the base class."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "conditional_colab_md"
|
|
},
|
|
"source": [
|
|
"<a href=\"https://colab.research.google.com/github/borglab/gtsam/blob/develop/gtsam/inference/doc/Conditional.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"id": "conditional_pip_code",
|
|
"tags": [
|
|
"remove-cell"
|
|
]
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"%pip install --quiet gtsam-develop"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"metadata": {
|
|
"id": "conditional_import_code"
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"import gtsam\n",
|
|
"import numpy as np\n",
|
|
"\n",
|
|
"# We need concrete graph types and elimination to get a Conditional\n",
|
|
"from gtsam import GaussianFactorGraph, Ordering\n",
|
|
"from gtsam import symbol_shorthand\n",
|
|
"\n",
|
|
"X = symbol_shorthand.X\n",
|
|
"L = symbol_shorthand.L"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "conditional_example_md"
|
|
},
|
|
"source": [
|
|
"## Example: Obtaining and Inspecting a Conditional\n",
|
|
"\n",
|
|
"We'll create a simple `GaussianFactorGraph` and eliminate one variable to get a `GaussianConditional`."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"metadata": {
|
|
"colab": {
|
|
"base_uri": "https://localhost:8080/"
|
|
},
|
|
"id": "conditional_create_code",
|
|
"outputId": "def01234-5678-9abc-def0-123456789abc"
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Eliminating x0 from graph:\n",
|
|
"\n",
|
|
"size: 2\n",
|
|
"factor 0: \n",
|
|
" A[x0] = [\n",
|
|
"\t-1\n",
|
|
"]\n",
|
|
" b = [ 0 ]\n",
|
|
" Noise model: unit (1) \n",
|
|
"factor 1: \n",
|
|
" A[x0] = [\n",
|
|
"\t-1\n",
|
|
"]\n",
|
|
" A[x1] = [\n",
|
|
"\t1\n",
|
|
"]\n",
|
|
" b = [ 0 ]\n",
|
|
" Noise model: unit (1) \n",
|
|
"\n",
|
|
"Resulting BayesNet:\n",
|
|
"\n",
|
|
"size: 1\n",
|
|
"conditional 0: p(x0 | x1)\n",
|
|
" R = [ 1.41421 ]\n",
|
|
" S[x1] = [ -0.707107 ]\n",
|
|
" d = [ 0 ]\n",
|
|
" logNormalizationConstant: -0.572365\n",
|
|
" No noise model\n",
|
|
"Conditional Keys (all): [8646911284551352320, 8646911284551352321]\n",
|
|
"First Frontal Key: 8646911284551352320 (x0)\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Create a simple Gaussian Factor Graph P(x0) P(x1|x0)\n",
|
|
"graph = GaussianFactorGraph()\n",
|
|
"model1 = gtsam.noiseModel.Isotropic.Sigma(1, 1.0)\n",
|
|
"model2 = gtsam.noiseModel.Isotropic.Sigma(1, 1.0)\n",
|
|
"\n",
|
|
"# Prior on x0\n",
|
|
"graph.add(X(0), -np.eye(1), np.zeros(1), model1)\n",
|
|
"# Factor between x0 and x1\n",
|
|
"graph.add(X(0), -np.eye(1), X(1), np.eye(1), np.zeros(1), model2)\n",
|
|
"\n",
|
|
"print(\"Eliminating x0 from graph:\")\n",
|
|
"graph.print()\n",
|
|
"\n",
|
|
"# Eliminate x0\n",
|
|
"ordering = Ordering([X(0)])\n",
|
|
"bayes_net, remaining_graph = graph.eliminatePartialSequential(ordering)\n",
|
|
"\n",
|
|
"print(\"\\nResulting BayesNet:\")\n",
|
|
"bayes_net.print()\n",
|
|
"\n",
|
|
"# Get the resulting conditional P(x0 | x1)\n",
|
|
"# In this case, it's a GaussianConditional\n",
|
|
"conditional = bayes_net.at(0) # or bayes_net[0]\n",
|
|
"\n",
|
|
"# Access methods from the Conditional base class\n",
|
|
"print(f\"Conditional Keys (all): {conditional.keys()}\")\n",
|
|
"print(f\"First Frontal Key: {conditional.firstFrontalKey()} ({gtsam.DefaultKeyFormatter(conditional.firstFrontalKey())})\")\n",
|
|
"\n",
|
|
"# Conditional objects can also be printed\n",
|
|
"# conditional.print(\"P(x0 | x1): \")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "conditional_eval_md"
|
|
},
|
|
"source": [
|
|
"## Evaluation (Derived Class Methods)\n",
|
|
"\n",
|
|
"Concrete conditional classes provide methods like `logProbability(values)` or `evaluate(values)` to compute the conditional probability (or density) given values for the parent variables. These methods are defined in the derived classes, not the `Conditional` base class itself."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"metadata": {
|
|
"id": "conditional_eval_code"
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"\n",
|
|
"Log Probability P(x0|x1=1.0): -0.8223649429247\n",
|
|
"Probability P(x0|x1=1.0): 0.43939128946772243\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"-0.8223649429247"
|
|
]
|
|
},
|
|
"execution_count": 9,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"# Example for GaussianConditional (requires VectorValues)\n",
|
|
"vector_values = gtsam.VectorValues()\n",
|
|
"vector_values.insert(X(0), np.array([0.0])) # Value for frontal variable\n",
|
|
"vector_values.insert(X(1), np.array([1.0])) # Value for parent variable\n",
|
|
"\n",
|
|
"# These methods are specific to GaussianConditional / other concrete types\n",
|
|
"try:\n",
|
|
" log_prob = conditional.logProbability(vector_values)\n",
|
|
" print(f\"\\nLog Probability P(x0|x1=1.0): {log_prob}\")\n",
|
|
" prob = conditional.evaluate(vector_values)\n",
|
|
" print(f\"Probability P(x0|x1=1.0): {prob}\")\n",
|
|
"except AttributeError:\n",
|
|
" print(\"\\nNote: logProbability/evaluate called on base Conditional pointer, needs derived type.\")\n",
|
|
" # In C++, you'd typically have a shared_ptr<GaussianConditional>.\n",
|
|
" # In Python, if you know the type, you might access methods directly,\n",
|
|
" # but the base class wrapper doesn't expose derived methods.\n",
|
|
" pass\n",
|
|
"\n",
|
|
"# To properly evaluate, you often use the BayesNet/BayesTree directly\n",
|
|
"bayes_net.logProbability(vector_values)"
|
|
]
|
|
}
|
|
],
|
|
"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
|
|
}
|