Compare commits
89 Commits
cc4a0e1804
...
f64ebfd4d8
Author | SHA1 | Date |
---|---|---|
|
f64ebfd4d8 | |
|
af5d85ae5f | |
|
ce5f93f4a0 | |
|
134f99930d | |
|
c1ec31c6f8 | |
|
01409fc409 | |
|
82decf916e | |
|
90c44de450 | |
|
618505efbc | |
|
e2d3cf585d | |
|
5b18f05656 | |
|
4b6af3deb5 | |
|
12baf54d17 | |
|
8302f2d432 | |
|
995bedb4ca | |
|
bc7646f82f | |
|
d4c9c68b58 | |
|
95af327c44 | |
|
a9a79397a9 | |
|
bdd0d3e759 | |
|
af3de7b73e | |
|
f64f094bab | |
|
7d2eea3d0f | |
|
283932ae68 | |
|
995e907e62 | |
|
64cb67ba3c | |
|
6e8952b5e8 | |
|
110086749f | |
|
62d29cf55f | |
|
4f66a491ff | |
|
1a869444bf | |
|
2f2d6546d1 | |
|
12f919dc55 | |
|
13c7dafba3 | |
|
2453c37b2b | |
|
3edde4d693 | |
|
3d979763f0 | |
|
eca51af19d | |
|
75aeca390e | |
|
10f30e1ca9 | |
|
0a24a8ac43 | |
|
9857e62a56 | |
|
3fd5c2501e | |
|
1f5e924eac | |
|
93d9ab6a2e | |
|
fa7bde7529 | |
|
c8fe2fcff2 | |
|
40e5a1a6ab | |
|
e1802814ca | |
|
6cb0fa7cd7 | |
|
febeacd686 | |
|
dafa0076ec | |
|
2714dc5625 | |
|
b5a3f11993 | |
|
a82f19131b | |
|
c57988fe55 | |
|
d6e87ec084 | |
|
b3e87360d5 | |
|
ffce28da5f | |
|
f09546f134 | |
|
0b7a2be2ea | |
|
efeafd74b0 | |
|
006a7c7752 | |
|
60ed242226 | |
|
09d5380514 | |
|
a1ed2f9866 | |
|
f2f1bbaf8c | |
|
be9b00e408 | |
|
faae928eae | |
|
a132a36ff2 | |
|
ee63a5bf6f | |
|
a7b42dc878 | |
|
88b4082be7 | |
|
d00971d2c9 | |
|
e2f69e0afe | |
|
f2fff1936b | |
|
b281f62e24 | |
|
e9e794b7cd | |
|
fdc0068c00 | |
|
c681628cd0 | |
|
ae63321d1b | |
|
9bca36fd2c | |
|
8c83e432b9 | |
|
f1dcc6bede | |
|
45e487c440 | |
|
4bfde71d8a | |
|
d920d94198 | |
|
9902ccc0a4 | |
|
77008c056e |
|
@ -1,7 +1,7 @@
|
|||
# This workflow builds the Python wheels using cibuildwheel and uploads them to TestPyPI.
|
||||
# It can be triggered on push to the develop branch or manually via Github Actions.
|
||||
|
||||
name: Build Wheels (cibuildwheel)
|
||||
name: Build Wheels for Develop
|
||||
|
||||
on:
|
||||
push:
|
||||
|
|
|
@ -0,0 +1,188 @@
|
|||
# This workflow builds the Python wheels using cibuildwheel and uploads them to TestPyPI.
|
||||
# It can be triggered on push to the develop branch or manually via Github Actions.
|
||||
|
||||
name: Build Wheels for Release
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build_wheels:
|
||||
name: Build Wheels
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# Linux x86_64
|
||||
- os: ubuntu-latest
|
||||
python_version: "3.10"
|
||||
cibw_python_version: 310
|
||||
platform_id: manylinux_x86_64
|
||||
manylinux_image: manylinux2014
|
||||
- os: ubuntu-latest
|
||||
python_version: "3.11"
|
||||
cibw_python_version: 311
|
||||
platform_id: manylinux_x86_64
|
||||
manylinux_image: manylinux2014
|
||||
- os: ubuntu-latest
|
||||
python_version: "3.12"
|
||||
cibw_python_version: 312
|
||||
platform_id: manylinux_x86_64
|
||||
manylinux_image: manylinux2014
|
||||
- os: ubuntu-latest
|
||||
python_version: "3.13"
|
||||
cibw_python_version: 313
|
||||
platform_id: manylinux_x86_64
|
||||
manylinux_image: manylinux2014
|
||||
|
||||
# Linux aarch64
|
||||
- os: ubuntu-24.04-arm
|
||||
python_version: "3.10"
|
||||
cibw_python_version: 310
|
||||
platform_id: manylinux_aarch64
|
||||
manylinux_image: manylinux2014
|
||||
- os: ubuntu-24.04-arm
|
||||
python_version: "3.11"
|
||||
cibw_python_version: 311
|
||||
platform_id: manylinux_aarch64
|
||||
manylinux_image: manylinux2014
|
||||
- os: ubuntu-24.04-arm
|
||||
python_version: "3.12"
|
||||
cibw_python_version: 312
|
||||
platform_id: manylinux_aarch64
|
||||
manylinux_image: manylinux2014
|
||||
- os: ubuntu-24.04-arm
|
||||
python_version: "3.13"
|
||||
cibw_python_version: 313
|
||||
platform_id: manylinux_aarch64
|
||||
manylinux_image: manylinux2014
|
||||
|
||||
# MacOS x86_64
|
||||
- os: macos-13
|
||||
python_version: "3.10"
|
||||
cibw_python_version: 310
|
||||
platform_id: macosx_x86_64
|
||||
- os: macos-13
|
||||
python_version: "3.11"
|
||||
cibw_python_version: 311
|
||||
platform_id: macosx_x86_64
|
||||
- os: macos-13
|
||||
python_version: "3.12"
|
||||
cibw_python_version: 312
|
||||
platform_id: macosx_x86_64
|
||||
- os: macos-13
|
||||
python_version: "3.13"
|
||||
cibw_python_version: 313
|
||||
platform_id: macosx_x86_64
|
||||
|
||||
# MacOS arm64
|
||||
- os: macos-14
|
||||
python_version: "3.10"
|
||||
cibw_python_version: 310
|
||||
platform_id: macosx_arm64
|
||||
- os: macos-14
|
||||
python_version: "3.11"
|
||||
cibw_python_version: 311
|
||||
platform_id: macosx_arm64
|
||||
- os: macos-14
|
||||
python_version: "3.12"
|
||||
cibw_python_version: 312
|
||||
platform_id: macosx_arm64
|
||||
- os: macos-14
|
||||
python_version: "3.13"
|
||||
cibw_python_version: 313
|
||||
platform_id: macosx_arm64
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.sha }}
|
||||
|
||||
- name: Set up Python ${{ matrix.python_version }}
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python_version }}
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
python3 -m pip install -r python/dev_requirements.txt
|
||||
if [ "$RUNNER_OS" == "Linux" ]; then
|
||||
sudo apt-get install -y wget libicu-dev python3-pip python3-setuptools libboost-all-dev ninja-build
|
||||
elif [ "$RUNNER_OS" == "macOS" ]; then
|
||||
brew install boost ninja python-setuptools
|
||||
else
|
||||
echo "$RUNNER_OS not supported"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# We first build the Python wrapper module on the host machine. This is done because cibuildwheel
|
||||
# expects a setup.py file to be present in the project directory.
|
||||
#
|
||||
# The Python wrapper module is then rebuilt within the cibuildwheel container before building
|
||||
# the wheels to ensure platform compatibility.
|
||||
- name: Run CMake
|
||||
run: |
|
||||
cmake . -B build -DGTSAM_BUILD_PYTHON=1 -DGTSAM_PYTHON_VERSION=${{ matrix.python_version }}
|
||||
|
||||
# If on macOS, we previously installed boost using homebrew for the first build.
|
||||
# We need to uninstall it before building the wheels with cibuildwheel, which will
|
||||
# install boost from source.
|
||||
- name: Uninstall Boost (MacOS)
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
brew uninstall boost
|
||||
|
||||
- name: Build and test wheels
|
||||
env:
|
||||
# Generate the platform identifier. See https://cibuildwheel.pypa.io/en/stable/options/#build-skip.
|
||||
CIBW_BUILD: cp${{ matrix.cibw_python_version }}-${{ matrix.platform_id }}
|
||||
CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.manylinux_image }}
|
||||
CIBW_MANYLINUX_AARCH64_IMAGE: ${{ matrix.manylinux_image }}
|
||||
CIBW_ARCHS: all
|
||||
|
||||
# Set the minimum required MacOS version for the wheels.
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.15
|
||||
|
||||
# Set DYLD_LIBRARY_PATH to REPAIR_LIBRARY_PATH, which is set in cibw_before_all.sh. REPAIR_LIBRARY_PATH
|
||||
# simply appends BOOST_LIBRARYDIR to the path, which is required during during link-time repair.
|
||||
CIBW_REPAIR_WHEEL_COMMAND_MACOS: DYLD_LIBRARY_PATH=$REPAIR_LIBRARY_PATH delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel}
|
||||
|
||||
# Use build instead of pip wheel to build the wheels. This is recommended by PyPA.
|
||||
# See https://cibuildwheel.pypa.io/en/stable/options/#build-frontend.
|
||||
CIBW_BUILD_FRONTEND: "build"
|
||||
CIBW_BEFORE_ALL: bash .github/scripts/python_wheels/cibw_before_all.sh ${{ matrix.python_version }} {project}
|
||||
|
||||
CIBW_BUILD_VERBOSITY: 1
|
||||
|
||||
run: bash .github/scripts/python_wheels/build_wheels.sh
|
||||
|
||||
- name: Store artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cibw-wheels-cp${{ matrix.cibw_python_version }}-${{ matrix.platform_id }}
|
||||
path: wheelhouse/*.whl
|
||||
|
||||
upload_all:
|
||||
name: Upload All
|
||||
needs: build_wheels
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
steps:
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: dist/
|
||||
merge-multiple: true
|
||||
|
||||
- name: Publish to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
verbose: true
|
||||
packages-dir: dist/
|
||||
repository-url: https://test.pypi.org/legacy/
|
|
@ -55,6 +55,9 @@ Optional prerequisites - used automatically if findable by CMake:
|
|||
|
||||
GTSAM 4 introduces several new features, most notably Expressions and a Python toolbox. It also introduces traits, a C++ technique that allows optimizing with non-GTSAM types. That opens the door to retiring geometric types such as Point2 and Point3 to pure Eigen types, which we also do. A significant change which will not trigger a compile error is that zero-initializing of Point2 and Point3 is deprecated, so please be aware that this might render functions using their default constructor incorrect.
|
||||
|
||||
There is a flag `GTSAM_ALLOW_DEPRECATED_SINCE_V43` for newly deprecated methods since the 4.3 release, which is on by default, allowing anyone to just pull version 4.3 and compile.
|
||||
|
||||
|
||||
## Wrappers
|
||||
|
||||
We provide support for [MATLAB](matlab/README.md) and [Python](python/README.md) wrappers for GTSAM. Please refer to the linked documents for more details.
|
||||
|
|
|
@ -6,51 +6,88 @@
|
|||
# Boost_NO_SYSTEM_PATHS: set to true to keep the find script from ignoring BOOST_ROOT
|
||||
|
||||
if(MSVC)
|
||||
# By default, boost only builds static libraries on windows
|
||||
set(Boost_USE_STATIC_LIBS ON) # only find static libs
|
||||
# If we ever reset above on windows and, ...
|
||||
# If we use Boost shared libs, disable auto linking.
|
||||
# Some libraries, at least Boost Program Options, rely on this to export DLL symbols.
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
if(NOT Boost_USE_STATIC_LIBS)
|
||||
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PUBLIC BOOST_ALL_NO_LIB BOOST_ALL_DYN_LINK)
|
||||
endif()
|
||||
# Virtual memory range for PCH exceeded on VS2015
|
||||
if(MSVC_VERSION LESS 1910) # older than VS2017
|
||||
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE -Zm295)
|
||||
if(MSVC_VERSION LESS 1910)
|
||||
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE -Zm295)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# ---- 关键修改:强制使用 FindBoost 模块模式,而不是 CONFIG 模式 ----
|
||||
set(Boost_NO_BOOST_CMAKE ON CACHE BOOL "Use FindBoost module mode" FORCE)
|
||||
|
||||
# Store these in variables so they are automatically replicated in GTSAMConfig.cmake and such.
|
||||
# 允许多线程库(照旧)
|
||||
set(Boost_USE_MULTITHREADED ON)
|
||||
|
||||
# 最低版本
|
||||
set(BOOST_FIND_MINIMUM_VERSION 1.65)
|
||||
set(BOOST_FIND_MINIMUM_COMPONENTS serialization system filesystem thread program_options date_time timer chrono regex)
|
||||
|
||||
find_package(Boost ${BOOST_FIND_MINIMUM_VERSION} COMPONENTS ${BOOST_FIND_MINIMUM_COMPONENTS} REQUIRED)
|
||||
# ---- 关键修改:按版本决定是否需要 system 组件 ----
|
||||
set(BOOST_FIND_MINIMUM_COMPONENTS
|
||||
serialization filesystem thread program_options date_time timer chrono regex
|
||||
)
|
||||
|
||||
# Required components
|
||||
if(NOT Boost_SERIALIZATION_LIBRARY OR NOT Boost_SYSTEM_LIBRARY OR NOT Boost_FILESYSTEM_LIBRARY OR
|
||||
NOT Boost_THREAD_LIBRARY OR NOT Boost_DATE_TIME_LIBRARY)
|
||||
message(FATAL_ERROR "Missing required Boost components >= v1.65, please install/upgrade Boost or configure your search paths.")
|
||||
# 只有旧版 Boost (< 1.69) 需要 system;>=1.69 为 header-only,不再要求
|
||||
# 注意:Boost_VERSION 是 find_package 之后才有的,这里用一个预探测逻辑:
|
||||
# 先尝试不带 system;失败再带上 system 尝试一次(兼容极老环境)。
|
||||
# 也可以用工具链变量提前注入 Boost_VERSION,这里采用两段式最稳妥。
|
||||
|
||||
# 第一次尝试:不含 system(适配 Boost>=1.69)
|
||||
message(STATUS "Trying Boost without 'system' component first (>=1.69 header-only)...")
|
||||
set(_boost_try_components ${BOOST_FIND_MINIMUM_COMPONENTS})
|
||||
set(_boost_found FALSE)
|
||||
find_package(Boost ${BOOST_FIND_MINIMUM_VERSION} COMPONENTS ${_boost_try_components} QUIET)
|
||||
if(Boost_FOUND)
|
||||
set(_boost_found TRUE)
|
||||
else()
|
||||
# 第二次尝试:加入 system(兼容 Boost<1.69)
|
||||
message(STATUS "Retrying Boost with 'system' component for older Boost (<1.69)...")
|
||||
list(APPEND _boost_try_components system)
|
||||
find_package(Boost ${BOOST_FIND_MINIMUM_VERSION} COMPONENTS ${_boost_try_components} REQUIRED)
|
||||
endif()
|
||||
|
||||
# 记录最终组件集合
|
||||
set(BOOST_FIND_MINIMUM_COMPONENTS ${_boost_try_components})
|
||||
|
||||
# ---- 必要组件检查(按最终集合判断),不要无条件检查 Boost_SYSTEM_LIBRARY ----
|
||||
set(_missing_required FALSE)
|
||||
foreach(_comp IN LISTS BOOST_FIND_MINIMUM_COMPONENTS)
|
||||
string(TOUPPER "${_comp}" _COMP_UP)
|
||||
if(NOT DEFINED "Boost_${_COMP_UP}_LIBRARY" AND NOT TARGET "Boost::${_comp}")
|
||||
# 某些组件(如 header-only)可能没有 *_LIBRARY 变量,但会有导入目标或仅头文件
|
||||
# 对 header-only 的 system(>=1.69)这里不会要求
|
||||
message(STATUS "Note: Boost component '${_comp}' has no explicit *_LIBRARY var; relying on imported target or headers.")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# ---- 计时接口选择,与原逻辑一致 ----
|
||||
option(GTSAM_DISABLE_NEW_TIMERS "Disables using Boost.chrono for timing" OFF)
|
||||
# Allow for not using the timer libraries on boost < 1.48 (GTSAM timing code falls back to old timer library)
|
||||
|
||||
# ---- 链接库列表(不再无条件包含 Boost::system)----
|
||||
set(GTSAM_BOOST_LIBRARIES
|
||||
Boost::serialization
|
||||
Boost::system
|
||||
Boost::filesystem
|
||||
Boost::thread
|
||||
Boost::date_time
|
||||
Boost::regex
|
||||
Boost::serialization
|
||||
Boost::filesystem
|
||||
Boost::thread
|
||||
Boost::date_time
|
||||
Boost::regex
|
||||
)
|
||||
|
||||
# 如果最终组件包含 chrono/timer,则追加
|
||||
if(TARGET Boost::chrono)
|
||||
list(APPEND GTSAM_BOOST_LIBRARIES Boost::chrono)
|
||||
endif()
|
||||
if(TARGET Boost::timer)
|
||||
list(APPEND GTSAM_BOOST_LIBRARIES Boost::timer)
|
||||
endif()
|
||||
|
||||
# 仅当真的找了 system(即老版本 Boost)时才链接 Boost::system
|
||||
if("system" IN_LIST BOOST_FIND_MINIMUM_COMPONENTS AND TARGET Boost::system)
|
||||
list(APPEND GTSAM_BOOST_LIBRARIES Boost::system)
|
||||
endif()
|
||||
|
||||
if (GTSAM_DISABLE_NEW_TIMERS)
|
||||
message("WARNING: GTSAM timing instrumentation manually disabled")
|
||||
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PUBLIC DGTSAM_DISABLE_NEW_TIMERS)
|
||||
else()
|
||||
if(Boost_TIMER_LIBRARY)
|
||||
list(APPEND GTSAM_BOOST_LIBRARIES Boost::timer Boost::chrono)
|
||||
else()
|
||||
list(APPEND GTSAM_BOOST_LIBRARIES rt) # When using the header-only boost timer library, need -lrt
|
||||
message("WARNING: GTSAM timing instrumentation will use the older, less accurate, Boost timer library because boost older than 1.48 was found.")
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <gtsam/dllexport.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* @brief Global default pseudo-random number generator object.
|
||||
* In wrappers we can access std::mt19937_64 via gtsam.MT19937
|
||||
*/
|
||||
static std::mt19937_64 kRandomNumberGenerator(42);
|
||||
|
||||
namespace gtsam {
|
||||
/**
|
||||
* For Python __str__().
|
||||
|
@ -28,7 +35,7 @@ private:
|
|||
std::streambuf* coutBuffer_;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace gtsam
|
||||
|
||||
namespace gtsam {
|
||||
// Adapted from https://stackoverflow.com/a/32223343/9151520
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <gtsam/base/Testable.h>
|
||||
#include <gtsam/base/debug.h>
|
||||
#include <gtsam/base/utilities.h>
|
||||
#include <gtsam/discrete/DiscreteConditional.h>
|
||||
#include <gtsam/discrete/Ring.h>
|
||||
#include <gtsam/discrete/Signature.h>
|
||||
|
|
|
@ -27,9 +27,6 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// In wrappers we can access std::mt19937_64 via gtsam.MT19937
|
||||
static std::mt19937_64 kRandomNumberGenerator(42);
|
||||
|
||||
namespace gtsam {
|
||||
|
||||
/**
|
||||
|
|
|
@ -127,6 +127,9 @@ class GTSAM_EXPORT DiscreteFactorGraph
|
|||
template <class DERIVED_FACTOR>
|
||||
DiscreteFactorGraph(const FactorGraph<DERIVED_FACTOR>& graph) : Base(graph) {}
|
||||
|
||||
/// Destructor
|
||||
virtual ~DiscreteFactorGraph() {}
|
||||
|
||||
/// @name Testable
|
||||
/// @{
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include <gtsam/base/Testable.h>
|
||||
#include <gtsam/base/debug.h>
|
||||
#include <gtsam/base/utilities.h>
|
||||
#include <gtsam/discrete/Ring.h>
|
||||
#include <gtsam/discrete/Signature.h>
|
||||
#include <gtsam/discrete/TableDistribution.h>
|
||||
|
|
|
@ -202,16 +202,6 @@ HybridValues HybridBayesNet::sample(std::mt19937_64 *rng) const {
|
|||
return sample(given, rng);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
HybridValues HybridBayesNet::sample(const HybridValues &given) const {
|
||||
return sample(given, &kRandomNumberGenerator);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
HybridValues HybridBayesNet::sample() const {
|
||||
return sample(&kRandomNumberGenerator);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
AlgebraicDecisionTree<Key> HybridBayesNet::errorTree(
|
||||
const VectorValues &continuousValues) const {
|
||||
|
|
|
@ -181,10 +181,11 @@ class GTSAM_EXPORT HybridBayesNet : public BayesNet<HybridConditional> {
|
|||
* auto sample = bn.sample(given, &rng);
|
||||
*
|
||||
* @param given Values of missing variables.
|
||||
* @param rng The pseudo-random number generator.
|
||||
* @param rng The optional pseudo-random number generator.
|
||||
* @return HybridValues
|
||||
*/
|
||||
HybridValues sample(const HybridValues &given, std::mt19937_64 *rng) const;
|
||||
HybridValues sample(const HybridValues &given,
|
||||
std::mt19937_64 *rng = nullptr) const;
|
||||
|
||||
/**
|
||||
* @brief Sample using ancestral sampling.
|
||||
|
@ -193,25 +194,10 @@ class GTSAM_EXPORT HybridBayesNet : public BayesNet<HybridConditional> {
|
|||
* std::mt19937_64 rng(42);
|
||||
* auto sample = bn.sample(&rng);
|
||||
*
|
||||
* @param rng The pseudo-random number generator.
|
||||
* @param rng The optional pseudo-random number generator.
|
||||
* @return HybridValues
|
||||
*/
|
||||
HybridValues sample(std::mt19937_64 *rng) const;
|
||||
|
||||
/**
|
||||
* @brief Sample from an incomplete BayesNet, use default rng.
|
||||
*
|
||||
* @param given Values of missing variables.
|
||||
* @return HybridValues
|
||||
*/
|
||||
HybridValues sample(const HybridValues &given) const;
|
||||
|
||||
/**
|
||||
* @brief Sample using ancestral sampling, use default rng.
|
||||
*
|
||||
* @return HybridValues
|
||||
*/
|
||||
HybridValues sample() const;
|
||||
HybridValues sample(std::mt19937_64 *rng = nullptr) const;
|
||||
|
||||
/**
|
||||
* @brief Prune the Bayes Net such that we have at most maxNrLeaves leaves.
|
||||
|
|
|
@ -158,10 +158,8 @@ class HybridBayesNet {
|
|||
gtsam::HybridValues optimize() const;
|
||||
gtsam::VectorValues optimize(const gtsam::DiscreteValues& assignment) const;
|
||||
|
||||
gtsam::HybridValues sample(const gtsam::HybridValues& given, std::mt19937_64@ rng) const;
|
||||
gtsam::HybridValues sample(std::mt19937_64@ rng) const;
|
||||
gtsam::HybridValues sample(const gtsam::HybridValues& given) const;
|
||||
gtsam::HybridValues sample() const;
|
||||
gtsam::HybridValues sample(const gtsam::HybridValues& given, std::mt19937_64@ rng = nullptr) const;
|
||||
gtsam::HybridValues sample(std::mt19937_64@ rng = nullptr) const;
|
||||
|
||||
void print(string s = "HybridBayesNet\n",
|
||||
const gtsam::KeyFormatter& keyFormatter =
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace gtsam {
|
|||
|
||||
/// Assign default key formatter
|
||||
KeyFormatter DefaultKeyFormatter = &_defaultKeyFormatter;
|
||||
KeyFormatter MultiRobotKeyFormatter = &_multirobotKeyFormatter;
|
||||
|
||||
/* ************************************************************************* */
|
||||
string _defaultKeyFormatter(Key key) {
|
||||
|
|
|
@ -57,8 +57,7 @@ GTSAM_EXPORT std::string _multirobotKeyFormatter(gtsam::Key key);
|
|||
/// formatter in print functions.
|
||||
///
|
||||
/// Checks for LabeledSymbol, Symbol and then plain keys, in order.
|
||||
static const gtsam::KeyFormatter MultiRobotKeyFormatter =
|
||||
&_multirobotKeyFormatter;
|
||||
extern GTSAM_EXPORT KeyFormatter MultiRobotKeyFormatter;
|
||||
|
||||
/// To use the key_formatter on Keys, they must be wrapped in a StreamedKey.
|
||||
struct StreamedKey {
|
||||
|
|
|
@ -26,9 +26,6 @@
|
|||
using namespace std;
|
||||
using namespace gtsam;
|
||||
|
||||
// In Wrappers we have no access to this so have a default ready
|
||||
static std::mt19937_64 kRandomNumberGenerator(42);
|
||||
|
||||
namespace gtsam {
|
||||
|
||||
// Instantiate base class
|
||||
|
@ -76,15 +73,6 @@ namespace gtsam {
|
|||
return result;
|
||||
}
|
||||
|
||||
/* ************************************************************************ */
|
||||
VectorValues GaussianBayesNet::sample() const {
|
||||
return sample(&kRandomNumberGenerator);
|
||||
}
|
||||
|
||||
VectorValues GaussianBayesNet::sample(const VectorValues& given) const {
|
||||
return sample(given, &kRandomNumberGenerator);
|
||||
}
|
||||
|
||||
/* ************************************************************************ */
|
||||
VectorValues GaussianBayesNet::optimizeGradientSearch() const
|
||||
{
|
||||
|
|
|
@ -131,7 +131,7 @@ namespace gtsam {
|
|||
* std::mt19937_64 rng(42);
|
||||
* auto sample = gbn.sample(&rng);
|
||||
*/
|
||||
VectorValues sample(std::mt19937_64* rng) const;
|
||||
VectorValues sample(std::mt19937_64* rng = nullptr) const;
|
||||
|
||||
/**
|
||||
* Sample from an incomplete BayesNet, given missing variables
|
||||
|
@ -140,13 +140,7 @@ namespace gtsam {
|
|||
* VectorValues given = ...;
|
||||
* auto sample = gbn.sample(given, &rng);
|
||||
*/
|
||||
VectorValues sample(const VectorValues& given, std::mt19937_64* rng) const;
|
||||
|
||||
/// Sample using ancestral sampling, use default rng
|
||||
VectorValues sample() const;
|
||||
|
||||
/// Sample from an incomplete BayesNet, use default rng
|
||||
VectorValues sample(const VectorValues& given) const;
|
||||
VectorValues sample(const VectorValues& given, std::mt19937_64* rng = nullptr) const;
|
||||
|
||||
/**
|
||||
* Return ordering corresponding to a topological sort.
|
||||
|
|
|
@ -15,11 +15,12 @@
|
|||
* @author Christian Potthast, Frank Dellaert
|
||||
*/
|
||||
|
||||
#include <gtsam/base/utilities.h>
|
||||
#include <gtsam/hybrid/HybridValues.h>
|
||||
#include <gtsam/linear/GaussianConditional.h>
|
||||
#include <gtsam/linear/Sampler.h>
|
||||
#include <gtsam/linear/VectorValues.h>
|
||||
#include <gtsam/linear/linearExceptions.h>
|
||||
#include <gtsam/hybrid/HybridValues.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
|
@ -34,9 +35,6 @@
|
|||
#include <string>
|
||||
#include <cmath>
|
||||
|
||||
// In wrappers we can access std::mt19937_64 via gtsam.MT19937
|
||||
static std::mt19937_64 kRandomNumberGenerator(42);
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace gtsam {
|
||||
|
@ -347,6 +345,10 @@ namespace gtsam {
|
|||
|
||||
VectorValues solution = solve(parentsValues);
|
||||
Key key = firstFrontalKey();
|
||||
|
||||
// Check if rng is nullptr, then assign default
|
||||
rng = (rng == nullptr) ? &kRandomNumberGenerator : rng;
|
||||
|
||||
// The vector of sigma values for sampling.
|
||||
// If no model, initialize sigmas to 1, else to model sigmas
|
||||
const Vector& sigmas = (!model_) ? Vector::Ones(rows()) : model_->sigmas();
|
||||
|
@ -359,16 +361,7 @@ namespace gtsam {
|
|||
throw std::invalid_argument(
|
||||
"sample() can only be invoked on no-parent prior");
|
||||
VectorValues values;
|
||||
return sample(values);
|
||||
}
|
||||
|
||||
/* ************************************************************************ */
|
||||
VectorValues GaussianConditional::sample() const {
|
||||
return sample(&kRandomNumberGenerator);
|
||||
}
|
||||
|
||||
VectorValues GaussianConditional::sample(const VectorValues& given) const {
|
||||
return sample(given, &kRandomNumberGenerator);
|
||||
return sample(values, rng);
|
||||
}
|
||||
|
||||
/* ************************************************************************ */
|
||||
|
|
|
@ -217,7 +217,7 @@ namespace gtsam {
|
|||
* std::mt19937_64 rng(42);
|
||||
* auto sample = gc.sample(&rng);
|
||||
*/
|
||||
VectorValues sample(std::mt19937_64* rng) const;
|
||||
VectorValues sample(std::mt19937_64* rng = nullptr) const;
|
||||
|
||||
/**
|
||||
* Sample from conditional, given missing variables
|
||||
|
@ -227,13 +227,7 @@ namespace gtsam {
|
|||
* auto sample = gc.sample(given, &rng);
|
||||
*/
|
||||
VectorValues sample(const VectorValues& parentsValues,
|
||||
std::mt19937_64* rng) const;
|
||||
|
||||
/// Sample, use default rng
|
||||
VectorValues sample() const;
|
||||
|
||||
/// Sample with given values, use default rng
|
||||
VectorValues sample(const VectorValues& parentsValues) const;
|
||||
std::mt19937_64* rng = nullptr) const;
|
||||
|
||||
/// @}
|
||||
/// @name Linear algebra.
|
||||
|
|
|
@ -560,10 +560,9 @@ virtual class GaussianConditional : gtsam::JacobianFactor {
|
|||
const gtsam::VectorValues& frontalValues) const;
|
||||
gtsam::JacobianFactor* likelihood(gtsam::Vector frontal) const;
|
||||
|
||||
gtsam::VectorValues sample(std::mt19937_64@ rng) const;
|
||||
gtsam::VectorValues sample(const gtsam::VectorValues& parents, std::mt19937_64@ rng) const;
|
||||
gtsam::VectorValues sample() const;
|
||||
gtsam::VectorValues sample(const gtsam::VectorValues& parents) const;
|
||||
gtsam::VectorValues sample(std::mt19937_64 @rng = nullptr) const;
|
||||
gtsam::VectorValues sample(const gtsam::VectorValues& parents,
|
||||
std::mt19937_64 @rng = nullptr) const;
|
||||
|
||||
// Advanced Interface
|
||||
gtsam::VectorValues solveOtherRHS(const gtsam::VectorValues& parents,
|
||||
|
@ -629,9 +628,10 @@ virtual class GaussianBayesNet {
|
|||
gtsam::VectorValues optimize() const;
|
||||
gtsam::VectorValues optimize(const gtsam::VectorValues& given) const;
|
||||
gtsam::VectorValues optimizeGradientSearch() const;
|
||||
|
||||
gtsam::VectorValues sample(const gtsam::VectorValues& given) const;
|
||||
gtsam::VectorValues sample() const;
|
||||
|
||||
gtsam::VectorValues sample(const gtsam::VectorValues& given,
|
||||
std::mt19937_64 @rng = nullptr) const;
|
||||
gtsam::VectorValues sample(std::mt19937_64 @rng = nullptr) const;
|
||||
gtsam::VectorValues backSubstitute(const gtsam::VectorValues& gx) const;
|
||||
gtsam::VectorValues backSubstituteTranspose(const gtsam::VectorValues& gx) const;
|
||||
|
||||
|
|
|
@ -441,7 +441,7 @@ TEST(GaussianConditional, likelihood) {
|
|||
|
||||
/* ************************************************************************* */
|
||||
// Test sampling
|
||||
TEST(GaussianConditional, sample) {
|
||||
TEST(GaussianConditional, Sample) {
|
||||
Matrix A1 = (Matrix(2, 2) << 1., 2., 3., 4.).finished();
|
||||
const Vector2 b(20, 40), x1(3, 4);
|
||||
const double sigma = 0.01;
|
||||
|
@ -465,8 +465,10 @@ TEST(GaussianConditional, sample) {
|
|||
auto actual3 = conditional.sample(given, &rng);
|
||||
EXPECT_LONGS_EQUAL(1, actual2.size());
|
||||
// regressions
|
||||
#if __APPLE__ || _WIN32
|
||||
EXPECT(assert_equal(Vector2(31.0111856, 64.9850775), actual2[X(0)], 1e-5));
|
||||
#if __APPLE__
|
||||
EXPECT(assert_equal(Vector2(31.0111856, 64.9850775), actual2[X(0)], 1e-5));
|
||||
#elif _WIN32
|
||||
EXPECT(assert_equal(Vector2(30.995317, 64.9943165), actual2[X(0)], 1e-5));
|
||||
#elif __linux__
|
||||
EXPECT(assert_equal(Vector2(30.9809331, 64.9927588), actual2[X(0)], 1e-5));
|
||||
#endif
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
#include <utility>
|
||||
#include <gtsam/nonlinear/Values.h>
|
||||
|
||||
#include <gtsam/nonlinear/Values.h> // Only so Eclipse finds class definition
|
||||
|
||||
namespace gtsam {
|
||||
|
||||
|
||||
|
|
|
@ -81,13 +81,12 @@ struct GTSAM_EXPORT SfmTrack2d {
|
|||
* @returns boolean result of the validation.
|
||||
*/
|
||||
bool hasUniqueCameras() const {
|
||||
std::vector<int> track_cam_indices;
|
||||
std::vector<size_t> cameraIndices;
|
||||
for (auto& measurement : measurements) {
|
||||
track_cam_indices.emplace_back(measurement.first);
|
||||
cameraIndices.emplace_back(measurement.first);
|
||||
}
|
||||
auto i =
|
||||
std::adjacent_find(track_cam_indices.begin(), track_cam_indices.end());
|
||||
bool all_cameras_unique = (i == track_cam_indices.end());
|
||||
auto i = std::adjacent_find(cameraIndices.begin(), cameraIndices.end());
|
||||
bool all_cameras_unique = (i == cameraIndices.end());
|
||||
return all_cameras_unique;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
namespace gtsam {
|
||||
|
||||
// In Wrappers we have no access to this so have a default ready
|
||||
static std::mt19937 kRandomNumberGenerator(42);
|
||||
static std::mt19937 kPRNG(42);
|
||||
|
||||
using Sparse = Eigen::SparseMatrix<double>;
|
||||
|
||||
|
@ -869,7 +869,7 @@ Values ShonanAveraging<d>::initializeRandomly(std::mt19937 &rng) const {
|
|||
/* ************************************************************************* */
|
||||
template <size_t d>
|
||||
Values ShonanAveraging<d>::initializeRandomly() const {
|
||||
return initializeRandomly(kRandomNumberGenerator);
|
||||
return initializeRandomly(kPRNG);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
@ -883,7 +883,7 @@ Values ShonanAveraging<d>::initializeRandomlyAt(size_t p,
|
|||
/* ************************************************************************* */
|
||||
template <size_t d>
|
||||
Values ShonanAveraging<d>::initializeRandomlyAt(size_t p) const {
|
||||
return initializeRandomlyAt(p, kRandomNumberGenerator);
|
||||
return initializeRandomlyAt(p, kPRNG);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
|
@ -39,7 +39,7 @@ using namespace gtsam;
|
|||
using namespace std;
|
||||
|
||||
// In Wrappers we have no access to this so have a default ready.
|
||||
static std::mt19937 kRandomNumberGenerator(42);
|
||||
static std::mt19937 kPRNG(42);
|
||||
|
||||
// Some relative translations may be zero. We treat nodes that have a zero
|
||||
// relativeTranslation as a single node.
|
||||
|
@ -185,7 +185,7 @@ Values TranslationRecovery::initializeRandomly(
|
|||
const std::vector<BinaryMeasurement<Point3>> &betweenTranslations,
|
||||
const Values &initialValues) const {
|
||||
return initializeRandomly(relativeTranslations, betweenTranslations,
|
||||
&kRandomNumberGenerator, initialValues);
|
||||
&kPRNG, initialValues);
|
||||
}
|
||||
|
||||
Values TranslationRecovery::run(
|
||||
|
|
|
@ -45,7 +45,7 @@ ShonanAveraging3 fromExampleName(
|
|||
|
||||
static const ShonanAveraging3 kShonan = fromExampleName("toyExample.g2o");
|
||||
|
||||
static std::mt19937 kRandomNumberGenerator(42);
|
||||
static std::mt19937 kPRNG(42);
|
||||
|
||||
/* ************************************************************************* */
|
||||
TEST(ShonanAveraging3, checkConstructor) {
|
||||
|
@ -78,7 +78,7 @@ TEST(ShonanAveraging3, buildGraphAt) {
|
|||
|
||||
/* ************************************************************************* */
|
||||
TEST(ShonanAveraging3, checkOptimality) {
|
||||
const Values randomRotations = kShonan.initializeRandomly(kRandomNumberGenerator);
|
||||
const Values randomRotations = kShonan.initializeRandomly(kPRNG);
|
||||
Values random = ShonanAveraging3::LiftTo<Rot3>(4, randomRotations); // lift to 4!
|
||||
auto Lambda = kShonan.computeLambda(random);
|
||||
EXPECT_LONGS_EQUAL(15, Lambda.rows());
|
||||
|
@ -106,7 +106,7 @@ TEST(ShonanAveraging3, checkSubgraph) {
|
|||
|
||||
// Create initial random estimation
|
||||
Values initial;
|
||||
initial = subgraphShonan.initializeRandomly(kRandomNumberGenerator);
|
||||
initial = subgraphShonan.initializeRandomly(kPRNG);
|
||||
|
||||
// Run Shonan with SUBGRAPH solver
|
||||
auto result = subgraphShonan.run(initial, 3, 3);
|
||||
|
@ -115,7 +115,7 @@ TEST(ShonanAveraging3, checkSubgraph) {
|
|||
|
||||
/* ************************************************************************* */
|
||||
TEST(ShonanAveraging3, tryOptimizingAt3) {
|
||||
const Values randomRotations = kShonan.initializeRandomly(kRandomNumberGenerator);
|
||||
const Values randomRotations = kShonan.initializeRandomly(kPRNG);
|
||||
Values initial = ShonanAveraging3::LiftTo<Rot3>(3, randomRotations); // convert to SOn
|
||||
EXPECT(!kShonan.checkOptimality(initial));
|
||||
const Values result = kShonan.tryOptimizingAt(3, initial);
|
||||
|
@ -130,7 +130,7 @@ TEST(ShonanAveraging3, tryOptimizingAt3) {
|
|||
|
||||
/* ************************************************************************* */
|
||||
TEST(ShonanAveraging3, tryOptimizingAt4) {
|
||||
const Values randomRotations = kShonan.initializeRandomly(kRandomNumberGenerator);
|
||||
const Values randomRotations = kShonan.initializeRandomly(kPRNG);
|
||||
Values random = ShonanAveraging3::LiftTo<Rot3>(4, randomRotations); // lift to 4!
|
||||
const Values result = kShonan.tryOptimizingAt(4, random);
|
||||
EXPECT(kShonan.checkOptimality(result));
|
||||
|
@ -228,7 +228,7 @@ TEST(ShonanAveraging3, CheckWithEigen) {
|
|||
|
||||
/* ************************************************************************* */
|
||||
TEST(ShonanAveraging3, initializeWithDescent) {
|
||||
const Values randomRotations = kShonan.initializeRandomly(kRandomNumberGenerator);
|
||||
const Values randomRotations = kShonan.initializeRandomly(kPRNG);
|
||||
Values random = ShonanAveraging3::LiftTo<Rot3>(3, randomRotations);
|
||||
const Values Qstar3 = kShonan.tryOptimizingAt(3, random);
|
||||
Vector minEigenVector;
|
||||
|
@ -240,7 +240,7 @@ TEST(ShonanAveraging3, initializeWithDescent) {
|
|||
|
||||
/* ************************************************************************* */
|
||||
TEST(ShonanAveraging3, run) {
|
||||
auto initial = kShonan.initializeRandomly(kRandomNumberGenerator);
|
||||
auto initial = kShonan.initializeRandomly(kPRNG);
|
||||
auto result = kShonan.run(initial, 5);
|
||||
EXPECT_DOUBLES_EQUAL(0, kShonan.cost(result.first), 1e-3);
|
||||
EXPECT_DOUBLES_EQUAL(-5.427688831332745e-07, result.second,
|
||||
|
@ -295,7 +295,7 @@ TEST(ShonanAveraging3, runKlaus) {
|
|||
EXPECT(assert_equal(R02, wR0.between(wR2), 0.1));
|
||||
|
||||
// Run Shonan (with prior on first rotation)
|
||||
auto initial = shonan.initializeRandomly(kRandomNumberGenerator);
|
||||
auto initial = shonan.initializeRandomly(kPRNG);
|
||||
auto result = shonan.run(initial, 5);
|
||||
EXPECT_DOUBLES_EQUAL(0, shonan.cost(result.first), 1e-2);
|
||||
EXPECT_DOUBLES_EQUAL(-9.2259161494467889e-05, result.second,
|
||||
|
@ -323,7 +323,7 @@ TEST(ShonanAveraging3, runKlausKarcher) {
|
|||
static const ShonanAveraging3 shonan = fromExampleName("Klaus3.g2o");
|
||||
|
||||
// Run Shonan (with Karcher mean prior)
|
||||
auto initial = shonan.initializeRandomly(kRandomNumberGenerator);
|
||||
auto initial = shonan.initializeRandomly(kPRNG);
|
||||
auto result = shonan.run(initial, 5);
|
||||
EXPECT_DOUBLES_EQUAL(0, shonan.cost(result.first), 1e-2);
|
||||
EXPECT_DOUBLES_EQUAL(-1.361402670507772e-05, result.second,
|
||||
|
@ -353,7 +353,7 @@ TEST(ShonanAveraging2, noisyToyGraph) {
|
|||
// Check graph building
|
||||
NonlinearFactorGraph graph = shonan.buildGraphAt(2);
|
||||
EXPECT_LONGS_EQUAL(6, graph.size());
|
||||
auto initial = shonan.initializeRandomly(kRandomNumberGenerator);
|
||||
auto initial = shonan.initializeRandomly(kPRNG);
|
||||
auto result = shonan.run(initial, 2);
|
||||
EXPECT_DOUBLES_EQUAL(0.0008211, shonan.cost(result.first), 1e-6);
|
||||
EXPECT_DOUBLES_EQUAL(0, result.second, 1e-10); // certificate!
|
||||
|
@ -391,7 +391,7 @@ TEST(ShonanAveraging2, noisyToyGraphWithHuber) {
|
|||
}
|
||||
|
||||
// test result
|
||||
auto initial = shonan.initializeRandomly(kRandomNumberGenerator);
|
||||
auto initial = shonan.initializeRandomly(kPRNG);
|
||||
auto result = shonan.run(initial, 2,2);
|
||||
EXPECT_DOUBLES_EQUAL(0.0008211, shonan.cost(result.first), 1e-6);
|
||||
EXPECT_DOUBLES_EQUAL(0, result.second, 1e-10); // certificate!
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
<buildtool_depend>cmake</buildtool_depend>
|
||||
|
||||
<depend>boost</depend>
|
||||
<depend>eigen</depend>
|
||||
<depend>tbb</depend>
|
||||
|
||||
|
|
|
@ -10,3 +10,5 @@
|
|||
* Without this they will be automatically converted to a Python object, and all
|
||||
* mutations on Python side will not be reflected on C++.
|
||||
*/
|
||||
|
||||
#include <pybind11/stl.h>
|
||||
|
|
Loading…
Reference in New Issue