sgptools 1.2.0__tar.gz → 2.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sgptools-2.0.0/PKG-INFO +216 -0
- sgptools-2.0.0/README.md +170 -0
- {sgptools-1.2.0 → sgptools-2.0.0}/setup.py +16 -6
- {sgptools-1.2.0 → sgptools-2.0.0}/sgptools/__init__.py +3 -4
- sgptools-2.0.0/sgptools/core/__init__.py +1 -0
- {sgptools-1.2.0/sgptools/models → sgptools-2.0.0/sgptools}/core/augmented_gpr.py +11 -17
- {sgptools-1.2.0/sgptools/models → sgptools-2.0.0/sgptools}/core/augmented_sgpr.py +27 -34
- sgptools-2.0.0/sgptools/core/osgpr.py +417 -0
- sgptools-2.0.0/sgptools/core/transformations.py +699 -0
- sgptools-2.0.0/sgptools/kernels/__init__.py +1 -0
- sgptools-2.0.0/sgptools/kernels/attentive_kernel.py +264 -0
- sgptools-2.0.0/sgptools/kernels/neural_kernel.py +343 -0
- sgptools-2.0.0/sgptools/kernels/neural_network.py +157 -0
- sgptools-2.0.0/sgptools/methods.py +1047 -0
- sgptools-2.0.0/sgptools/objectives.py +275 -0
- sgptools-2.0.0/sgptools/utils/__init__.py +1 -0
- sgptools-2.0.0/sgptools/utils/data.py +515 -0
- sgptools-2.0.0/sgptools/utils/gpflow.py +411 -0
- sgptools-2.0.0/sgptools/utils/metrics.py +447 -0
- sgptools-2.0.0/sgptools/utils/misc.py +196 -0
- sgptools-2.0.0/sgptools/utils/tsp.py +340 -0
- sgptools-2.0.0/sgptools.egg-info/PKG-INFO +216 -0
- {sgptools-1.2.0 → sgptools-2.0.0}/sgptools.egg-info/SOURCES.txt +7 -11
- {sgptools-1.2.0 → sgptools-2.0.0}/sgptools.egg-info/requires.txt +1 -0
- sgptools-1.2.0/PKG-INFO +0 -39
- sgptools-1.2.0/README.md +0 -123
- sgptools-1.2.0/sgptools/kernels/__init__.py +0 -9
- sgptools-1.2.0/sgptools/kernels/attentive_kernel.py +0 -119
- sgptools-1.2.0/sgptools/kernels/neural_kernel.py +0 -167
- sgptools-1.2.0/sgptools/kernels/neural_network.py +0 -58
- sgptools-1.2.0/sgptools/models/__init__.py +0 -10
- sgptools-1.2.0/sgptools/models/bo.py +0 -118
- sgptools-1.2.0/sgptools/models/cma_es.py +0 -121
- sgptools-1.2.0/sgptools/models/continuous_sgp.py +0 -68
- sgptools-1.2.0/sgptools/models/core/__init__.py +0 -9
- sgptools-1.2.0/sgptools/models/core/osgpr.py +0 -291
- sgptools-1.2.0/sgptools/models/core/transformations.py +0 -434
- sgptools-1.2.0/sgptools/models/greedy_mi.py +0 -115
- sgptools-1.2.0/sgptools/models/greedy_sgp.py +0 -97
- sgptools-1.2.0/sgptools/utils/__init__.py +0 -10
- sgptools-1.2.0/sgptools/utils/data.py +0 -212
- sgptools-1.2.0/sgptools/utils/gpflow.py +0 -250
- sgptools-1.2.0/sgptools/utils/metrics.py +0 -174
- sgptools-1.2.0/sgptools/utils/misc.py +0 -162
- sgptools-1.2.0/sgptools/utils/tsp.py +0 -200
- sgptools-1.2.0/sgptools.egg-info/PKG-INFO +0 -39
- {sgptools-1.2.0 → sgptools-2.0.0}/LICENSE.txt +0 -0
- {sgptools-1.2.0 → sgptools-2.0.0}/setup.cfg +0 -0
- {sgptools-1.2.0 → sgptools-2.0.0}/sgptools.egg-info/dependency_links.txt +0 -0
- {sgptools-1.2.0 → sgptools-2.0.0}/sgptools.egg-info/top_level.txt +0 -0
sgptools-2.0.0/PKG-INFO
ADDED
@@ -0,0 +1,216 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: sgptools
|
3
|
+
Version: 2.0.0
|
4
|
+
Summary: A Python library for efficient sensor placement and informative path planning
|
5
|
+
Home-page: https://www.SGP-Tools.com
|
6
|
+
Author: Kalvik
|
7
|
+
Author-email: itskalvik@gmail.com
|
8
|
+
License: Apache-2.0
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
10
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
11
|
+
Classifier: Operating System :: OS Independent
|
12
|
+
Requires-Python: >=3.6
|
13
|
+
Description-Content-Type: text/markdown
|
14
|
+
License-File: LICENSE.txt
|
15
|
+
Requires-Dist: apricot-select
|
16
|
+
Requires-Dist: matplotlib
|
17
|
+
Requires-Dist: pandas
|
18
|
+
Requires-Dist: scikit-learn
|
19
|
+
Requires-Dist: scipy
|
20
|
+
Requires-Dist: numpy<2.0.0
|
21
|
+
Requires-Dist: ortools
|
22
|
+
Requires-Dist: scikit-image
|
23
|
+
Requires-Dist: shapely
|
24
|
+
Requires-Dist: cma
|
25
|
+
Requires-Dist: bayesian-optimization
|
26
|
+
Requires-Dist: hkb_diamondsquare
|
27
|
+
Requires-Dist: tensorflow-probability[tf]>=0.21.0
|
28
|
+
Requires-Dist: tensorflow>=2.13.0; platform_machine != "arm64"
|
29
|
+
Requires-Dist: tensorflow-aarch64>=2.13.0; platform_machine == "arm64"
|
30
|
+
Requires-Dist: tensorflow-macos>=2.13.0; platform_system == "Darwin" and platform_machine == "arm64"
|
31
|
+
Requires-Dist: typing_extensions
|
32
|
+
Requires-Dist: gpflow>=2.7.0
|
33
|
+
Requires-Dist: pillow
|
34
|
+
Requires-Dist: geopandas
|
35
|
+
Dynamic: author
|
36
|
+
Dynamic: author-email
|
37
|
+
Dynamic: classifier
|
38
|
+
Dynamic: description
|
39
|
+
Dynamic: description-content-type
|
40
|
+
Dynamic: home-page
|
41
|
+
Dynamic: license
|
42
|
+
Dynamic: license-file
|
43
|
+
Dynamic: requires-dist
|
44
|
+
Dynamic: requires-python
|
45
|
+
Dynamic: summary
|
46
|
+
|
47
|
+
<p align="center">
|
48
|
+
<img src="docs/assets/SGP-Tools.png#gh-light-mode-only" alt="SGP-Tools Logo" width="600"/>
|
49
|
+
<img src="docs/assets/logo_dark.png#gh-dark-mode-only" alt="SGP-Tools Logo" width="600"/>
|
50
|
+
</p>
|
51
|
+
|
52
|
+
<p align="center">
|
53
|
+
<em>A Python library for efficient sensor placement and informative path planning</em>
|
54
|
+
</p>
|
55
|
+
|
56
|
+
<p align="center">
|
57
|
+
<a href="https://pypi.org/project/sgptools/"><img alt="PyPI" src="https://img.shields.io/pypi/v/sgptools.svg"></a>
|
58
|
+
<a href="https://github.com/itskalvik/sgptools/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/pypi/l/sgptools.svg"></a>
|
59
|
+
</p>
|
60
|
+
|
61
|
+
<p align="center">
|
62
|
+
<img src="docs/assets/point_sensing.gif" width="49%">
|
63
|
+
<img src="docs/assets/non-point_sensing.gif" width="49%">
|
64
|
+
<img src="docs/assets/AIPP-4R.gif" width="49%">
|
65
|
+
<img src="docs/assets/AIPP-non-point_sensing.gif" width="49%">
|
66
|
+
</p>
|
67
|
+
|
68
|
+
## What is SGP-Tools?
|
69
|
+
|
70
|
+
**SGP-Tools** is a powerful and flexible Python library designed for solving **Sensor Placement** and **Informative Path Planning** problems, enabling efficient and scalable solutions for environment monitoring, e.g., monitoring air/water quality, soil moisture, or temperature.
|
71
|
+
|
72
|
+
### Sensor Placement
|
73
|
+
|
74
|
+
**Sensor Placement** is the problem of finding ideal locations to deploy a set of static sensors to best monitor a spatial phenomenon. The goal is to select a finite number of locations from a continuous space or a discrete set of candidates to maximize the information gathered about an entire area of interest. This is crucial when deploying a limited number of sensors to cover a large field.
|
75
|
+
|
76
|
+
### Informative Path Planning (IPP)
|
77
|
+
|
78
|
+
**Informative Path Planning** extends this concept to mobile sensors. Instead of finding static locations, IPP aims to compute an informative path for one or more robots to travel along. The path is designed to maximize information gain about the environment, often while adhering to constraints such as a limited travel distance. This is essential for applications like aerial surveying or robotic exploration.
|
79
|
+
|
80
|
+
### IPP vs. Lawnmower Paths
|
81
|
+
|
82
|
+
A common approach to surveying an area is to use a "lawnmower" path, a simple back-and-forth pattern designed for complete coverage. The following table summarizes the key differences between IPP and Lawnmower Paths:
|
83
|
+
|
84
|
+
| Factor | Lawnmower Path | Informative Path Planning (IPP) |
|
85
|
+
| :--- | :--- | :--- |
|
86
|
+
| **Primary Goal** | Complete and uniform coverage of a predefined area. | Targeted data collection in areas of high information or uncertainty. |
|
87
|
+
| **Performance** | Slow data collection but provides a high accuracy reconstruction of the envionment. | Fast data collection but provides an approximate reconstruction of the envionment. |
|
88
|
+
| **Prior Knowledge** | Not required; often used when no prior information is available. | Beneficial, but not required for adaptiev IPP; uses prior information to guide the sampling strategy. |
|
89
|
+
| **Adaptability** | Non-adaptive; the path is fixed before the mission starts. | Highly adaptive; the path is updated in real-time based on sensor data. |
|
90
|
+
| **Efficiency** | Can be inefficient if the phenomenon of interest is sparse. | Highly efficient for sparse or spatially variable phenomena. |
|
91
|
+
| **Computational Cost** | Low; simple to plan and execute. | Medium; requires onboard processing to analyze data and update the path. |
|
92
|
+
| **Best For** | Baseline mapping, homogenous environments, initial surveys. | Dynamic phenomena, resource-constrained missions. |
|
93
|
+
|
94
|
+
## Why SGP-Tools?
|
95
|
+
|
96
|
+
- **State-of-the-Art Algorithms**: Includes a variety of optimization methods including greedy algorithms, Bayesian optimization, CMA-ES, and SGP-based optimization.
|
97
|
+
- **Advanced Modeling Capabilities**: Go beyond simple point sensing with tools for informative path planning for multi-robot systems and complex sensor field-of-view (FoV) models.
|
98
|
+
- **Non-Stationary Kernels**: Capture complex, real-world phenomena with specialized non-stationary kernels like the Neural Spectral Kernel and the Attentive Kernel.
|
99
|
+
- **Flexible and Extensible**: Built on GPflow and TensorFlow, the library is designed to be modular and easy to extend with your own custom methods, kernels, and objectives.
|
100
|
+
|
101
|
+
## Installation
|
102
|
+
The library is available as a ```pip``` package. To install the package, run the following command:
|
103
|
+
|
104
|
+
```
|
105
|
+
python3 -m pip install sgptools
|
106
|
+
```
|
107
|
+
|
108
|
+
Installation from source:
|
109
|
+
|
110
|
+
```
|
111
|
+
git clone https://github.com/itskalvik/sgp-tools.git
|
112
|
+
cd sgp-tools/
|
113
|
+
python3 -m pip install -r requirements.txt
|
114
|
+
python3 -m pip install -e .
|
115
|
+
```
|
116
|
+
|
117
|
+
Note: The requirements.txt file contains packages and their latest versions that were last verified to be working without any issues.
|
118
|
+
|
119
|
+
## Quick Start
|
120
|
+
|
121
|
+
Here's an example of how to use SGP-Tools to get an informative path using the `ContinuousSGP` method:
|
122
|
+
|
123
|
+
```python
|
124
|
+
from sgptools.utils.data import Dataset # Class for loading and managing datasets
|
125
|
+
from sgptools.utils.misc import get_inducing_pts # Utility for selecting inducing points
|
126
|
+
from sgptools.utils.tsp import run_tsp # TSP/VRP solver for initial path planning
|
127
|
+
from sgptools.utils.gpflow import get_model_params # For training initial GP/SGP hyperparameters
|
128
|
+
from sgptools.methods import get_method # Gets the class for continuous SGP optimization
|
129
|
+
from sgptools.core.transformations import IPPTransform # Transforms for IPP
|
130
|
+
|
131
|
+
# 1. Load or generate a dataset
|
132
|
+
# This will create a synthetic dataset for demonstration
|
133
|
+
dataset = Dataset(num_train=500, num_test=10000,
|
134
|
+
shape=(100, 100))
|
135
|
+
X_train, y_train = dataset.get_train()
|
136
|
+
X_test, y_test = dataset.get_test()
|
137
|
+
|
138
|
+
# 2. Learn the GP hyperparameters from the training data
|
139
|
+
print("Learning GP hyperparameters...")
|
140
|
+
_, noise_variance, kernel = get_model_params(
|
141
|
+
X_train, y_train, max_steps=1000, verbose=True
|
142
|
+
)
|
143
|
+
|
144
|
+
# 3. Setup the IPP model
|
145
|
+
num_placements = 15
|
146
|
+
|
147
|
+
# Initialize inducing points and get initial path
|
148
|
+
Xu_init = get_inducing_pts(X_train, num_placements)
|
149
|
+
Xu_init, _ = run_tsp(Xu_init, time_limit=10)
|
150
|
+
|
151
|
+
# Setup IPP transform with a sampling rate for continuous sensing
|
152
|
+
transform_continuous_sensing = IPPTransform(sampling_rate=4)
|
153
|
+
|
154
|
+
# Initialize the ContinuousSGP model
|
155
|
+
method = get_method('ContinuousSGP')
|
156
|
+
csgp_optimizer = method(
|
157
|
+
num_placements,
|
158
|
+
X_train,
|
159
|
+
kernel,
|
160
|
+
noise_variance,
|
161
|
+
transform_continuous_sensing,
|
162
|
+
X_init=Xu_init[0]
|
163
|
+
)
|
164
|
+
|
165
|
+
# 4. Run the optimization
|
166
|
+
print("Optimizing sensor placements...")
|
167
|
+
solution_path = csgp_optimizer.optimize(max_steps=200)
|
168
|
+
|
169
|
+
print(f"Solution Path: {solution_path}")
|
170
|
+
```
|
171
|
+
|
172
|
+
<p align="center">
|
173
|
+
<img src="docs/assets/quick_start.png" width="600">
|
174
|
+
</p>
|
175
|
+
|
176
|
+
For more detailed instructions, please refer to our [tutorials](http://sgp-tools.com/tutorials/index.html)
|
177
|
+
|
178
|
+
## SGP-based IPP
|
179
|
+
[](https://www.youtube.com/embed/G-RKFa1vNHM?si=PLmrmkCwXRj7mc4A "Video Summary")
|
180
|
+
|
181
|
+
## Datasets
|
182
|
+
High-resolution topography and bathymetry data can be downloaded from [NOAA Digital Coast](https://coast.noaa.gov/digitalcoast/)
|
183
|
+
|
184
|
+
## About
|
185
|
+
Please consider citing the following papers if you use SGP-Tools in your academic work 😄
|
186
|
+
|
187
|
+
```
|
188
|
+
@misc{JakkalaA23SP,
|
189
|
+
AUTHOR={Kalvik Jakkala and Srinivas Akella},
|
190
|
+
TITLE={Efficient Sensor Placement from Regression with Sparse Gaussian Processes in Continuous and Discrete Spaces},
|
191
|
+
NOTE= {Preprint},
|
192
|
+
YEAR={2023},
|
193
|
+
URL={https://www.itskalvik.com/research/publication/sgp-sp/},
|
194
|
+
}
|
195
|
+
|
196
|
+
@inproceedings{JakkalaA24IPP,
|
197
|
+
AUTHOR={Kalvik Jakkala and Srinivas Akella},
|
198
|
+
TITLE={Multi-Robot Informative Path Planning from Regression with Sparse Gaussian Processes},
|
199
|
+
booktitle={IEEE International Conference on Robotics and Automation, {ICRA}},
|
200
|
+
YEAR={2024},
|
201
|
+
PUBLISHER = {{IEEE}},
|
202
|
+
URL={https://www.itskalvik.com/research/publication/sgp-ipp/}
|
203
|
+
}
|
204
|
+
|
205
|
+
@inproceedings{JakkalaA25AIPP,
|
206
|
+
AUTHOR={Kalvik Jakkala and Srinivas Akella},
|
207
|
+
TITLE={Fully Differentiable Adaptive Informative Path Planning},
|
208
|
+
booktitle={IEEE International Conference on Robotics and Automation, {ICRA}},
|
209
|
+
YEAR={2025},
|
210
|
+
PUBLISHER = {{IEEE}},
|
211
|
+
URL={https://www.itskalvik.com/research/publication/sgp-aipp/}
|
212
|
+
}
|
213
|
+
```
|
214
|
+
|
215
|
+
## Acknowledgements
|
216
|
+
This work was funded in part by the UNC Charlotte Office of Research and Economic Development and by NSF under Award Number IIP-1919233.
|
sgptools-2.0.0/README.md
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
<p align="center">
|
2
|
+
<img src="docs/assets/SGP-Tools.png#gh-light-mode-only" alt="SGP-Tools Logo" width="600"/>
|
3
|
+
<img src="docs/assets/logo_dark.png#gh-dark-mode-only" alt="SGP-Tools Logo" width="600"/>
|
4
|
+
</p>
|
5
|
+
|
6
|
+
<p align="center">
|
7
|
+
<em>A Python library for efficient sensor placement and informative path planning</em>
|
8
|
+
</p>
|
9
|
+
|
10
|
+
<p align="center">
|
11
|
+
<a href="https://pypi.org/project/sgptools/"><img alt="PyPI" src="https://img.shields.io/pypi/v/sgptools.svg"></a>
|
12
|
+
<a href="https://github.com/itskalvik/sgptools/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/pypi/l/sgptools.svg"></a>
|
13
|
+
</p>
|
14
|
+
|
15
|
+
<p align="center">
|
16
|
+
<img src="docs/assets/point_sensing.gif" width="49%">
|
17
|
+
<img src="docs/assets/non-point_sensing.gif" width="49%">
|
18
|
+
<img src="docs/assets/AIPP-4R.gif" width="49%">
|
19
|
+
<img src="docs/assets/AIPP-non-point_sensing.gif" width="49%">
|
20
|
+
</p>
|
21
|
+
|
22
|
+
## What is SGP-Tools?
|
23
|
+
|
24
|
+
**SGP-Tools** is a powerful and flexible Python library designed for solving **Sensor Placement** and **Informative Path Planning** problems, enabling efficient and scalable solutions for environment monitoring, e.g., monitoring air/water quality, soil moisture, or temperature.
|
25
|
+
|
26
|
+
### Sensor Placement
|
27
|
+
|
28
|
+
**Sensor Placement** is the problem of finding ideal locations to deploy a set of static sensors to best monitor a spatial phenomenon. The goal is to select a finite number of locations from a continuous space or a discrete set of candidates to maximize the information gathered about an entire area of interest. This is crucial when deploying a limited number of sensors to cover a large field.
|
29
|
+
|
30
|
+
### Informative Path Planning (IPP)
|
31
|
+
|
32
|
+
**Informative Path Planning** extends this concept to mobile sensors. Instead of finding static locations, IPP aims to compute an informative path for one or more robots to travel along. The path is designed to maximize information gain about the environment, often while adhering to constraints such as a limited travel distance. This is essential for applications like aerial surveying or robotic exploration.
|
33
|
+
|
34
|
+
### IPP vs. Lawnmower Paths
|
35
|
+
|
36
|
+
A common approach to surveying an area is to use a "lawnmower" path, a simple back-and-forth pattern designed for complete coverage. The following table summarizes the key differences between IPP and Lawnmower Paths:
|
37
|
+
|
38
|
+
| Factor | Lawnmower Path | Informative Path Planning (IPP) |
|
39
|
+
| :--- | :--- | :--- |
|
40
|
+
| **Primary Goal** | Complete and uniform coverage of a predefined area. | Targeted data collection in areas of high information or uncertainty. |
|
41
|
+
| **Performance** | Slow data collection but provides a high accuracy reconstruction of the envionment. | Fast data collection but provides an approximate reconstruction of the envionment. |
|
42
|
+
| **Prior Knowledge** | Not required; often used when no prior information is available. | Beneficial, but not required for adaptiev IPP; uses prior information to guide the sampling strategy. |
|
43
|
+
| **Adaptability** | Non-adaptive; the path is fixed before the mission starts. | Highly adaptive; the path is updated in real-time based on sensor data. |
|
44
|
+
| **Efficiency** | Can be inefficient if the phenomenon of interest is sparse. | Highly efficient for sparse or spatially variable phenomena. |
|
45
|
+
| **Computational Cost** | Low; simple to plan and execute. | Medium; requires onboard processing to analyze data and update the path. |
|
46
|
+
| **Best For** | Baseline mapping, homogenous environments, initial surveys. | Dynamic phenomena, resource-constrained missions. |
|
47
|
+
|
48
|
+
## Why SGP-Tools?
|
49
|
+
|
50
|
+
- **State-of-the-Art Algorithms**: Includes a variety of optimization methods including greedy algorithms, Bayesian optimization, CMA-ES, and SGP-based optimization.
|
51
|
+
- **Advanced Modeling Capabilities**: Go beyond simple point sensing with tools for informative path planning for multi-robot systems and complex sensor field-of-view (FoV) models.
|
52
|
+
- **Non-Stationary Kernels**: Capture complex, real-world phenomena with specialized non-stationary kernels like the Neural Spectral Kernel and the Attentive Kernel.
|
53
|
+
- **Flexible and Extensible**: Built on GPflow and TensorFlow, the library is designed to be modular and easy to extend with your own custom methods, kernels, and objectives.
|
54
|
+
|
55
|
+
## Installation
|
56
|
+
The library is available as a ```pip``` package. To install the package, run the following command:
|
57
|
+
|
58
|
+
```
|
59
|
+
python3 -m pip install sgptools
|
60
|
+
```
|
61
|
+
|
62
|
+
Installation from source:
|
63
|
+
|
64
|
+
```
|
65
|
+
git clone https://github.com/itskalvik/sgp-tools.git
|
66
|
+
cd sgp-tools/
|
67
|
+
python3 -m pip install -r requirements.txt
|
68
|
+
python3 -m pip install -e .
|
69
|
+
```
|
70
|
+
|
71
|
+
Note: The requirements.txt file contains packages and their latest versions that were last verified to be working without any issues.
|
72
|
+
|
73
|
+
## Quick Start
|
74
|
+
|
75
|
+
Here's an example of how to use SGP-Tools to get an informative path using the `ContinuousSGP` method:
|
76
|
+
|
77
|
+
```python
|
78
|
+
from sgptools.utils.data import Dataset # Class for loading and managing datasets
|
79
|
+
from sgptools.utils.misc import get_inducing_pts # Utility for selecting inducing points
|
80
|
+
from sgptools.utils.tsp import run_tsp # TSP/VRP solver for initial path planning
|
81
|
+
from sgptools.utils.gpflow import get_model_params # For training initial GP/SGP hyperparameters
|
82
|
+
from sgptools.methods import get_method # Gets the class for continuous SGP optimization
|
83
|
+
from sgptools.core.transformations import IPPTransform # Transforms for IPP
|
84
|
+
|
85
|
+
# 1. Load or generate a dataset
|
86
|
+
# This will create a synthetic dataset for demonstration
|
87
|
+
dataset = Dataset(num_train=500, num_test=10000,
|
88
|
+
shape=(100, 100))
|
89
|
+
X_train, y_train = dataset.get_train()
|
90
|
+
X_test, y_test = dataset.get_test()
|
91
|
+
|
92
|
+
# 2. Learn the GP hyperparameters from the training data
|
93
|
+
print("Learning GP hyperparameters...")
|
94
|
+
_, noise_variance, kernel = get_model_params(
|
95
|
+
X_train, y_train, max_steps=1000, verbose=True
|
96
|
+
)
|
97
|
+
|
98
|
+
# 3. Setup the IPP model
|
99
|
+
num_placements = 15
|
100
|
+
|
101
|
+
# Initialize inducing points and get initial path
|
102
|
+
Xu_init = get_inducing_pts(X_train, num_placements)
|
103
|
+
Xu_init, _ = run_tsp(Xu_init, time_limit=10)
|
104
|
+
|
105
|
+
# Setup IPP transform with a sampling rate for continuous sensing
|
106
|
+
transform_continuous_sensing = IPPTransform(sampling_rate=4)
|
107
|
+
|
108
|
+
# Initialize the ContinuousSGP model
|
109
|
+
method = get_method('ContinuousSGP')
|
110
|
+
csgp_optimizer = method(
|
111
|
+
num_placements,
|
112
|
+
X_train,
|
113
|
+
kernel,
|
114
|
+
noise_variance,
|
115
|
+
transform_continuous_sensing,
|
116
|
+
X_init=Xu_init[0]
|
117
|
+
)
|
118
|
+
|
119
|
+
# 4. Run the optimization
|
120
|
+
print("Optimizing sensor placements...")
|
121
|
+
solution_path = csgp_optimizer.optimize(max_steps=200)
|
122
|
+
|
123
|
+
print(f"Solution Path: {solution_path}")
|
124
|
+
```
|
125
|
+
|
126
|
+
<p align="center">
|
127
|
+
<img src="docs/assets/quick_start.png" width="600">
|
128
|
+
</p>
|
129
|
+
|
130
|
+
For more detailed instructions, please refer to our [tutorials](http://sgp-tools.com/tutorials/index.html)
|
131
|
+
|
132
|
+
## SGP-based IPP
|
133
|
+
[](https://www.youtube.com/embed/G-RKFa1vNHM?si=PLmrmkCwXRj7mc4A "Video Summary")
|
134
|
+
|
135
|
+
## Datasets
|
136
|
+
High-resolution topography and bathymetry data can be downloaded from [NOAA Digital Coast](https://coast.noaa.gov/digitalcoast/)
|
137
|
+
|
138
|
+
## About
|
139
|
+
Please consider citing the following papers if you use SGP-Tools in your academic work 😄
|
140
|
+
|
141
|
+
```
|
142
|
+
@misc{JakkalaA23SP,
|
143
|
+
AUTHOR={Kalvik Jakkala and Srinivas Akella},
|
144
|
+
TITLE={Efficient Sensor Placement from Regression with Sparse Gaussian Processes in Continuous and Discrete Spaces},
|
145
|
+
NOTE= {Preprint},
|
146
|
+
YEAR={2023},
|
147
|
+
URL={https://www.itskalvik.com/research/publication/sgp-sp/},
|
148
|
+
}
|
149
|
+
|
150
|
+
@inproceedings{JakkalaA24IPP,
|
151
|
+
AUTHOR={Kalvik Jakkala and Srinivas Akella},
|
152
|
+
TITLE={Multi-Robot Informative Path Planning from Regression with Sparse Gaussian Processes},
|
153
|
+
booktitle={IEEE International Conference on Robotics and Automation, {ICRA}},
|
154
|
+
YEAR={2024},
|
155
|
+
PUBLISHER = {{IEEE}},
|
156
|
+
URL={https://www.itskalvik.com/research/publication/sgp-ipp/}
|
157
|
+
}
|
158
|
+
|
159
|
+
@inproceedings{JakkalaA25AIPP,
|
160
|
+
AUTHOR={Kalvik Jakkala and Srinivas Akella},
|
161
|
+
TITLE={Fully Differentiable Adaptive Informative Path Planning},
|
162
|
+
booktitle={IEEE International Conference on Robotics and Automation, {ICRA}},
|
163
|
+
YEAR={2025},
|
164
|
+
PUBLISHER = {{IEEE}},
|
165
|
+
URL={https://www.itskalvik.com/research/publication/sgp-aipp/}
|
166
|
+
}
|
167
|
+
```
|
168
|
+
|
169
|
+
## Acknowledgements
|
170
|
+
This work was funded in part by the UNC Charlotte Office of Research and Economic Development and by NSF under Award Number IIP-1919233.
|
@@ -1,18 +1,22 @@
|
|
1
1
|
from setuptools import setup, find_packages
|
2
2
|
|
3
|
-
__version__ = "
|
3
|
+
__version__ = "2.0.0"
|
4
|
+
|
5
|
+
with open("README.md", "r", encoding="utf-8") as fh:
|
6
|
+
long_description = fh.read()
|
4
7
|
|
5
8
|
setup(
|
6
9
|
name='sgptools',
|
7
10
|
version=__version__,
|
8
11
|
packages=find_packages(),
|
9
12
|
python_requires='>=3.6',
|
10
|
-
url='https://www.
|
13
|
+
url='https://www.SGP-Tools.com',
|
11
14
|
license='Apache-2.0',
|
12
15
|
author_email='itskalvik@gmail.com',
|
13
16
|
author='Kalvik',
|
14
|
-
description='
|
15
|
-
long_description=
|
17
|
+
description='A Python library for efficient sensor placement and informative path planning',
|
18
|
+
long_description=long_description,
|
19
|
+
long_description_content_type="text/markdown",
|
16
20
|
install_requires=['apricot-select',
|
17
21
|
'matplotlib',
|
18
22
|
'pandas',
|
@@ -31,6 +35,12 @@ setup(
|
|
31
35
|
'tensorflow-macos>=2.13.0; platform_system=="Darwin" and platform_machine=="arm64"',
|
32
36
|
'typing_extensions',
|
33
37
|
'gpflow>=2.7.0',
|
34
|
-
'pillow'
|
35
|
-
|
38
|
+
'pillow',
|
39
|
+
'geopandas'
|
40
|
+
],
|
41
|
+
classifiers=[
|
42
|
+
"Programming Language :: Python :: 3",
|
43
|
+
"License :: OSI Approved :: Apache Software License",
|
44
|
+
"Operating System :: OS Independent",
|
45
|
+
]
|
36
46
|
)
|
@@ -1,5 +1,4 @@
|
|
1
1
|
"""
|
2
|
-
|
3
2
|
SGP-Tools: SGP-based Optimization Tools
|
4
3
|
|
5
4
|
Software Suite for Sensor Placement and Informative Path Planning.
|
@@ -12,9 +11,9 @@ The library includes python code for the following:
|
|
12
11
|
|
13
12
|
"""
|
14
13
|
|
15
|
-
__version__ = "
|
14
|
+
__version__ = "2.0.0"
|
16
15
|
__author__ = 'Kalvik'
|
17
16
|
|
18
|
-
from .
|
19
|
-
from .
|
17
|
+
from .core import *
|
18
|
+
from .kernels import *
|
20
19
|
from .utils import *
|
@@ -0,0 +1 @@
|
|
1
|
+
# sgptools/core/__init__.py
|
@@ -13,7 +13,6 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
15
|
# Original GP code from GPflow library (https://github.com/GPflow/GPflow)
|
16
|
-
|
17
16
|
"""Provides a Gaussian process model with expand and aggregate functions
|
18
17
|
"""
|
19
18
|
|
@@ -25,6 +24,7 @@ from gpflow.base import InputData, MeanAndVariance
|
|
25
24
|
from gpflow.utilities import add_likelihood_noise_cov, assert_params_false
|
26
25
|
from .transformations import Transform
|
27
26
|
|
27
|
+
|
28
28
|
class AugmentedGPR(GPR):
|
29
29
|
"""GPR model from the GPFlow library augmented to use a transform object's
|
30
30
|
expand and aggregate functions on the data points where necessary.
|
@@ -39,24 +39,18 @@ class AugmentedGPR(GPR):
|
|
39
39
|
noise_variance (float): data variance
|
40
40
|
transform (Transform): Transform object
|
41
41
|
"""
|
42
|
-
|
43
|
-
|
44
|
-
*args,
|
45
|
-
transform=None,
|
46
|
-
**kwargs
|
47
|
-
):
|
48
|
-
super().__init__(
|
49
|
-
*args,
|
50
|
-
**kwargs
|
51
|
-
)
|
42
|
+
|
43
|
+
def __init__(self, *args, transform=None, **kwargs):
|
44
|
+
super().__init__(*args, **kwargs)
|
52
45
|
if transform is None:
|
53
46
|
self.transform = Transform()
|
54
47
|
else:
|
55
48
|
self.transform = transform
|
56
49
|
|
57
50
|
def predict_f(
|
58
|
-
self,
|
59
|
-
|
51
|
+
self,
|
52
|
+
Xnew: InputData,
|
53
|
+
full_cov: bool = True,
|
60
54
|
full_output_cov: bool = False,
|
61
55
|
aggregate_train: bool = False,
|
62
56
|
) -> MeanAndVariance:
|
@@ -84,10 +78,10 @@ class AugmentedGPR(GPR):
|
|
84
78
|
# which can when train and test data are the same size
|
85
79
|
if kmn.shape[0] != kmn.shape[1]:
|
86
80
|
kmn = self.transform.aggregate(kmn)
|
87
|
-
|
81
|
+
|
88
82
|
conditional = gpflow.conditionals.base_conditional
|
89
83
|
f_mean_zero, f_var = conditional(
|
90
|
-
kmn, kmm_plus_s, knn, err, full_cov=full_cov,
|
91
|
-
|
84
|
+
kmn, kmm_plus_s, knn, err, full_cov=full_cov,
|
85
|
+
white=False) # [N, P], [N, P] or [P, N, N]
|
92
86
|
f_mean = f_mean_zero + self.mean_function(Xnew)
|
93
|
-
return f_mean, f_var
|
87
|
+
return f_mean, f_var
|
@@ -13,7 +13,6 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
15
|
# Original SGP code from GPflow library (https://github.com/GPflow/GPflow)
|
16
|
-
|
17
16
|
"""Provides a sparse Gaussian process model with update, expand, and aggregate functions
|
18
17
|
"""
|
19
18
|
|
@@ -49,37 +48,34 @@ class AugmentedSGPR(SGPR):
|
|
49
48
|
inducing_variable_time (ndarray): (m, d); Temporal dimensions of the inducing points,
|
50
49
|
used when modeling spatio-temporal IPP
|
51
50
|
"""
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
super().__init__(
|
60
|
-
*args,
|
61
|
-
**kwargs
|
62
|
-
)
|
51
|
+
|
52
|
+
def __init__(self,
|
53
|
+
*args,
|
54
|
+
transform=None,
|
55
|
+
inducing_variable_time=None,
|
56
|
+
**kwargs):
|
57
|
+
super().__init__(*args, **kwargs)
|
63
58
|
if transform is None:
|
64
59
|
self.transform = Transform()
|
65
60
|
else:
|
66
61
|
self.transform = transform
|
67
62
|
|
68
63
|
if inducing_variable_time is not None:
|
69
|
-
self.inducing_variable_time = inducingpoint_wrapper(
|
64
|
+
self.inducing_variable_time = inducingpoint_wrapper(
|
65
|
+
inducing_variable_time)
|
70
66
|
self.transform.inducing_variable_time = self.inducing_variable_time
|
71
67
|
else:
|
72
68
|
self.inducing_variable_time = None
|
73
69
|
|
74
|
-
def update(self,
|
70
|
+
def update(self, kernel, noise_variance):
|
75
71
|
"""Update SGP noise variance and kernel function parameters
|
76
72
|
|
77
73
|
Args:
|
78
|
-
noise_variance (float): data variance
|
79
74
|
kernel (gpflow.kernels.Kernel): gpflow kernel function
|
75
|
+
noise_variance (float): data variance
|
80
76
|
"""
|
81
77
|
self.likelihood.variance.assign(noise_variance)
|
82
|
-
for self_var, var in zip(self.kernel.trainable_variables,
|
78
|
+
for self_var, var in zip(self.kernel.trainable_variables,
|
83
79
|
kernel.trainable_variables):
|
84
80
|
self_var.assign(var)
|
85
81
|
|
@@ -91,7 +87,7 @@ class AugmentedSGPR(SGPR):
|
|
91
87
|
A is M x N, B is M x M, LB is M x M, AAT is M x M
|
92
88
|
"""
|
93
89
|
x, _ = self.data
|
94
|
-
|
90
|
+
|
95
91
|
iv = self.inducing_variable.Z # [M]
|
96
92
|
iv = self.transform.expand(iv)
|
97
93
|
|
@@ -130,9 +126,10 @@ class AugmentedSGPR(SGPR):
|
|
130
126
|
constraints = self.transform.constraints(self.inducing_variable.Z)
|
131
127
|
return const + logdet + quad + constraints
|
132
128
|
|
133
|
-
def predict_f(
|
134
|
-
|
135
|
-
|
129
|
+
def predict_f(self,
|
130
|
+
Xnew: InputData,
|
131
|
+
full_cov: bool = False,
|
132
|
+
full_output_cov: bool = False) -> MeanAndVariance:
|
136
133
|
|
137
134
|
# could copy into posterior into a fused version
|
138
135
|
"""
|
@@ -141,7 +138,7 @@ class AugmentedSGPR(SGPR):
|
|
141
138
|
notebook.
|
142
139
|
"""
|
143
140
|
X_data, Y_data = self.data
|
144
|
-
|
141
|
+
|
145
142
|
iv = self.inducing_variable.Z
|
146
143
|
iv = self.transform.expand(iv)
|
147
144
|
|
@@ -155,8 +152,7 @@ class AugmentedSGPR(SGPR):
|
|
155
152
|
L = tf.linalg.cholesky(kuu)
|
156
153
|
A = tf.linalg.triangular_solve(L, kuf, lower=True) / sigma
|
157
154
|
B = tf.linalg.matmul(A, A, transpose_b=True) + tf.eye(
|
158
|
-
num_inducing, dtype=default_float()
|
159
|
-
) # cache qinv
|
155
|
+
num_inducing, dtype=default_float()) # cache qinv
|
160
156
|
LB = tf.linalg.cholesky(B)
|
161
157
|
Aerr = tf.linalg.matmul(A, err)
|
162
158
|
c = tf.linalg.triangular_solve(LB, Aerr, lower=True) / sigma
|
@@ -164,18 +160,15 @@ class AugmentedSGPR(SGPR):
|
|
164
160
|
tmp2 = tf.linalg.triangular_solve(LB, tmp1, lower=True)
|
165
161
|
mean = tf.linalg.matmul(tmp2, c, transpose_a=True)
|
166
162
|
if full_cov:
|
167
|
-
var = (
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
var = tf.tile(var[None, ...], [self.num_latent_gps, 1, 1]) # [P, N, N]
|
163
|
+
var = (self.kernel(Xnew) +
|
164
|
+
tf.linalg.matmul(tmp2, tmp2, transpose_a=True) -
|
165
|
+
tf.linalg.matmul(tmp1, tmp1, transpose_a=True))
|
166
|
+
var = tf.tile(var[None, ...],
|
167
|
+
[self.num_latent_gps, 1, 1]) # [P, N, N]
|
173
168
|
else:
|
174
|
-
var = (
|
175
|
-
|
176
|
-
|
177
|
-
- tf.reduce_sum(tf.square(tmp1), 0)
|
178
|
-
)
|
169
|
+
var = (self.kernel(Xnew, full_cov=False) +
|
170
|
+
tf.reduce_sum(tf.square(tmp2), 0) -
|
171
|
+
tf.reduce_sum(tf.square(tmp1), 0))
|
179
172
|
var = tf.tile(var[:, None], [1, self.num_latent_gps])
|
180
173
|
|
181
174
|
return mean + self.mean_function(Xnew), var
|