sci-solver 0.1.0__tar.gz → 0.2.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.
- {sci_solver-0.1.0 → sci_solver-0.2.0}/CITATION.cff +1 -1
- {sci_solver-0.1.0 → sci_solver-0.2.0}/MANIFEST.in +1 -1
- {sci_solver-0.1.0 → sci_solver-0.2.0}/PKG-INFO +24 -5
- {sci_solver-0.1.0 → sci_solver-0.2.0}/README.md +23 -4
- {sci_solver-0.1.0 → sci_solver-0.2.0}/UPSTREAM.json +13 -2
- sci_solver-0.2.0/docs/api.md +121 -0
- sci_solver-0.2.0/docs/component-reuse.md +215 -0
- sci_solver-0.2.0/docs/fleet-partitions-small.md +119 -0
- sci_solver-0.2.0/docs/fleet-partitions.md +135 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/docs/migration.md +31 -4
- sci_solver-0.2.0/docs/release-notes.md +36 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/docs/releasing.md +11 -8
- {sci_solver-0.1.0 → sci_solver-0.2.0}/pyproject.toml +1 -1
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver/api.py +3 -2
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver/cli/vector_sci.py +3 -1
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver/config.py +4 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver/solvers/contact_solver.py +63 -166
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver/solvers/matching_numerics.py +58 -21
- sci_solver-0.2.0/src/sci_solver/solvers/matching_operations.py +162 -0
- sci_solver-0.2.0/src/sci_solver/solvers/partitioned_matching.py +489 -0
- sci_solver-0.2.0/src/sci_solver/solvers/stage_timing.py +41 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver.egg-info/PKG-INFO +24 -5
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver.egg-info/SOURCES.txt +24 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/tests/test_api.py +38 -0
- sci_solver-0.2.0/tests/test_partitioned_matching.py +326 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/tests/test_provenance.py +4 -2
- {sci_solver-0.1.0 → sci_solver-0.2.0}/tests/test_vector_solver.py +3 -0
- sci_solver-0.2.0/tools/benchmark_component_reuse.py +277 -0
- sci_solver-0.2.0/tools/benchmark_partitions.py +267 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/tools/compare_upstream.py +10 -5
- sci_solver-0.2.0/tools/validate_component_reuse.py +108 -0
- sci_solver-0.2.0/validation/component-reuse-profile.csv +6 -0
- sci_solver-0.2.0/validation/component-reuse-validation.json +1792 -0
- sci_solver-0.2.0/validation/component-reuse.csv +37 -0
- sci_solver-0.2.0/validation/component-reuse.json.gz +0 -0
- sci_solver-0.2.0/validation/fleet-partitions-small-summary.json +93 -0
- sci_solver-0.2.0/validation/fleet-partitions-small-validation.json +1536 -0
- sci_solver-0.2.0/validation/fleet-partitions-small.csv +301 -0
- sci_solver-0.2.0/validation/fleet-partitions-small.json.gz +0 -0
- sci_solver-0.2.0/validation/fleet-partitions.csv +16 -0
- sci_solver-0.2.0/validation/fleet-partitions.json +53147 -0
- sci_solver-0.2.0/validation/fleet-small-inputs.json +7807 -0
- sci_solver-0.2.0/validation/partition-baseline-parity.json +41 -0
- sci_solver-0.2.0/validation/release-0.1.0.json +111 -0
- sci_solver-0.2.0/validation/release-0.2.0-local.json +116 -0
- sci_solver-0.1.0/docs/api.md +0 -62
- sci_solver-0.1.0/docs/release-notes.md +0 -14
- {sci_solver-0.1.0 → sci_solver-0.2.0}/LICENSE +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/NOTICE +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/examples/config.json +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/examples/fleet.py +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/examples/two_robots.py +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/setup.cfg +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/setup.py +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver/__init__.py +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver/cli/__init__.py +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver/evaluation.py +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver/solvers/__init__.py +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver/solvers/_cubic_minima.c +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver/solvers/base.py +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver/solvers/collision_search.py +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver/solvers/cubic_utils.py +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver/solvers/reaction_matching.py +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver/solvers/vector_matching.py +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver.egg-info/dependency_links.txt +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver.egg-info/entry_points.txt +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver.egg-info/requires.txt +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/src/sci_solver.egg-info/top_level.txt +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/tests/data/fleet20_seed15.npz +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/tests/data/fleet20_seed2.npz +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/tests/data/fleet20_seed35.npz +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/tests/data/fleet20_seed47.npz +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/tests/data/fleet20_seed9.npz +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/tests/test_collision_search.py +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/tests/test_cubic_separation.py +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/validation/local-validation.json +0 -0
- {sci_solver-0.1.0 → sci_solver-0.2.0}/validation/upstream-comparison.json +0 -0
|
@@ -5,7 +5,7 @@ title: "SCI: Sequential Contact Insertion"
|
|
|
5
5
|
authors:
|
|
6
6
|
- family-names: Kamm
|
|
7
7
|
given-names: Jan
|
|
8
|
-
version: 0.
|
|
8
|
+
version: 0.2.0
|
|
9
9
|
license: Apache-2.0
|
|
10
10
|
repository-code: "https://github.com/jankammeth/sci"
|
|
11
11
|
abstract: "Continuous-time robot fleet planning with sequential contact insertion."
|
|
@@ -3,5 +3,5 @@ recursive-include docs *.md
|
|
|
3
3
|
recursive-include examples *.py *.json
|
|
4
4
|
recursive-include tests *.py *.npz
|
|
5
5
|
recursive-include tools *.py
|
|
6
|
-
recursive-include validation *.json
|
|
6
|
+
recursive-include validation *.json *.json.gz *.csv
|
|
7
7
|
include src/sci_solver/solvers/_cubic_minima.c
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sci-solver
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Sequential Contact Insertion for continuous-time robot fleet planning.
|
|
5
5
|
Author: Jan Kamm
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -38,13 +38,13 @@ checks separation over the entire trajectory.
|
|
|
38
38
|
|
|
39
39
|
## Installation
|
|
40
40
|
|
|
41
|
-
Python 3.10 or newer is required.
|
|
41
|
+
Python 3.10 or newer is required. Install from [PyPI](https://pypi.org/project/sci-solver/):
|
|
42
42
|
|
|
43
43
|
```sh
|
|
44
44
|
pip install sci-solver
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
To install directly from GitHub
|
|
47
|
+
To install directly from GitHub:
|
|
48
48
|
|
|
49
49
|
```sh
|
|
50
50
|
python -m pip install git+https://github.com/jankammeth/sci.git
|
|
@@ -116,6 +116,21 @@ and diagnostics; it is not a usable collision-free plan. Tolerances are absolute
|
|
|
116
116
|
and should be chosen for the physical scale of the problem. The reference default
|
|
117
117
|
separation allowance is zero; the examples explicitly use `1e-6`.
|
|
118
118
|
|
|
119
|
+
Starting with 0.2.0, the default `sci_fleet_mode="components"` uses union-find to
|
|
120
|
+
group robots connected by contacts and solves one system per group. Robots with
|
|
121
|
+
no contacts follow their unconstrained trajectories. Unchanged groups reuse their
|
|
122
|
+
solutions and checks. All modes check continuous separation across the entire fleet.
|
|
123
|
+
|
|
124
|
+
Select `SolverConfig(sci_fleet_mode="full")` to reproduce the earlier full-fleet
|
|
125
|
+
formulation, or `sci_fleet_mode="active"` to solve one system containing all
|
|
126
|
+
participating robots. The default uses the same component algorithm for every
|
|
127
|
+
fleet size; it has no robot-count threshold. Small contacting fleets can incur
|
|
128
|
+
extra bookkeeping overhead; the benchmarks report those cases as well.
|
|
129
|
+
[The component reuse benchmark](docs/component-reuse.md) compares the optimized
|
|
130
|
+
driver with its prototype and full-fleet mode on saved 2-, 4-, and 20-robot cases,
|
|
131
|
+
including a detailed Newton breakdown. Unchanged components retain their solved
|
|
132
|
+
states and checks; graph rebuilding remains simple union-find.
|
|
133
|
+
|
|
119
134
|
## Development and provenance
|
|
120
135
|
|
|
121
136
|
```sh
|
|
@@ -127,10 +142,14 @@ ruff check .
|
|
|
127
142
|
The numerical implementation is preserved from
|
|
128
143
|
[`contact-solver` at `641a234`](https://github.com/jankammeth/contact-solver/tree/641a2341a6a59938e285b8ff872bd484713e0605).
|
|
129
144
|
[UPSTREAM.json](UPSTREAM.json) records source paths, SHA-256 hashes, and every
|
|
130
|
-
extraction edit.
|
|
145
|
+
extraction edit. Four core files remain byte-identical. The collision wrapper changes
|
|
131
146
|
only the package name in its fallback warning; the C kernel adds equivalent
|
|
132
147
|
stack workspace allocation for Microsoft's C compiler. Numerical formulas and
|
|
133
|
-
control flow are
|
|
148
|
+
control flow in the explicit full-fleet mode are retained; its driver records
|
|
149
|
+
stage timings and dispatches the default component solver. Contact initialization,
|
|
150
|
+
recovery, and validation are shared with the component driver; Newton has optional
|
|
151
|
+
fine stage profiling. Original extraction hashes are retained alongside current
|
|
152
|
+
hashes and change descriptions.
|
|
134
153
|
[The migration guide](docs/migration.md) describes the extraction and comparison
|
|
135
154
|
procedure. The paper and historical experiment infrastructure remain separate.
|
|
136
155
|
|
|
@@ -10,13 +10,13 @@ checks separation over the entire trajectory.
|
|
|
10
10
|
|
|
11
11
|
## Installation
|
|
12
12
|
|
|
13
|
-
Python 3.10 or newer is required.
|
|
13
|
+
Python 3.10 or newer is required. Install from [PyPI](https://pypi.org/project/sci-solver/):
|
|
14
14
|
|
|
15
15
|
```sh
|
|
16
16
|
pip install sci-solver
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
To install directly from GitHub
|
|
19
|
+
To install directly from GitHub:
|
|
20
20
|
|
|
21
21
|
```sh
|
|
22
22
|
python -m pip install git+https://github.com/jankammeth/sci.git
|
|
@@ -88,6 +88,21 @@ and diagnostics; it is not a usable collision-free plan. Tolerances are absolute
|
|
|
88
88
|
and should be chosen for the physical scale of the problem. The reference default
|
|
89
89
|
separation allowance is zero; the examples explicitly use `1e-6`.
|
|
90
90
|
|
|
91
|
+
Starting with 0.2.0, the default `sci_fleet_mode="components"` uses union-find to
|
|
92
|
+
group robots connected by contacts and solves one system per group. Robots with
|
|
93
|
+
no contacts follow their unconstrained trajectories. Unchanged groups reuse their
|
|
94
|
+
solutions and checks. All modes check continuous separation across the entire fleet.
|
|
95
|
+
|
|
96
|
+
Select `SolverConfig(sci_fleet_mode="full")` to reproduce the earlier full-fleet
|
|
97
|
+
formulation, or `sci_fleet_mode="active"` to solve one system containing all
|
|
98
|
+
participating robots. The default uses the same component algorithm for every
|
|
99
|
+
fleet size; it has no robot-count threshold. Small contacting fleets can incur
|
|
100
|
+
extra bookkeeping overhead; the benchmarks report those cases as well.
|
|
101
|
+
[The component reuse benchmark](docs/component-reuse.md) compares the optimized
|
|
102
|
+
driver with its prototype and full-fleet mode on saved 2-, 4-, and 20-robot cases,
|
|
103
|
+
including a detailed Newton breakdown. Unchanged components retain their solved
|
|
104
|
+
states and checks; graph rebuilding remains simple union-find.
|
|
105
|
+
|
|
91
106
|
## Development and provenance
|
|
92
107
|
|
|
93
108
|
```sh
|
|
@@ -99,10 +114,14 @@ ruff check .
|
|
|
99
114
|
The numerical implementation is preserved from
|
|
100
115
|
[`contact-solver` at `641a234`](https://github.com/jankammeth/contact-solver/tree/641a2341a6a59938e285b8ff872bd484713e0605).
|
|
101
116
|
[UPSTREAM.json](UPSTREAM.json) records source paths, SHA-256 hashes, and every
|
|
102
|
-
extraction edit.
|
|
117
|
+
extraction edit. Four core files remain byte-identical. The collision wrapper changes
|
|
103
118
|
only the package name in its fallback warning; the C kernel adds equivalent
|
|
104
119
|
stack workspace allocation for Microsoft's C compiler. Numerical formulas and
|
|
105
|
-
control flow are
|
|
120
|
+
control flow in the explicit full-fleet mode are retained; its driver records
|
|
121
|
+
stage timings and dispatches the default component solver. Contact initialization,
|
|
122
|
+
recovery, and validation are shared with the component driver; Newton has optional
|
|
123
|
+
fine stage profiling. Original extraction hashes are retained alongside current
|
|
124
|
+
hashes and change descriptions.
|
|
106
125
|
[The migration guide](docs/migration.md) describes the extraction and comparison
|
|
107
126
|
procedure. The paper and historical experiment infrastructure remain separate.
|
|
108
127
|
|
|
@@ -10,7 +10,14 @@
|
|
|
10
10
|
"src/sci_solver/solvers/contact_solver.py": {
|
|
11
11
|
"upstream_path": "src/contact_solver/solvers/contact_solver.py",
|
|
12
12
|
"sha256": "9ae40bc11838b8fc0ca76f439f21af878d27669f3d3440bfd8519196e624b7a1",
|
|
13
|
-
"extracted_sha256": "9ae40bc11838b8fc0ca76f439f21af878d27669f3d3440bfd8519196e624b7a1"
|
|
13
|
+
"extracted_sha256": "9ae40bc11838b8fc0ca76f439f21af878d27669f3d3440bfd8519196e624b7a1",
|
|
14
|
+
"current_sha256": "08214666e733cfe2fe8c3f5b249ab08ec4c6ee6475cc6c771914cd46a46f6cc6",
|
|
15
|
+
"post_extraction_changes": [
|
|
16
|
+
"Active-robot and connected-component matching drivers; components become the default in 0.2.0, with explicit full mode retained.",
|
|
17
|
+
"Disjoint stage timings and system sizes for benchmark comparisons.",
|
|
18
|
+
"Share pure contact initialization, recovery and validation operations with lightweight components; allow selected-coordinate evaluation.",
|
|
19
|
+
"Configuration objects without a fleet-mode field inherit the public SolverConfig default."
|
|
20
|
+
]
|
|
14
21
|
},
|
|
15
22
|
"src/sci_solver/solvers/collision_search.py": {
|
|
16
23
|
"upstream_path": "src/contact_solver/solvers/collision_search.py",
|
|
@@ -31,7 +38,11 @@
|
|
|
31
38
|
"src/sci_solver/solvers/matching_numerics.py": {
|
|
32
39
|
"upstream_path": "src/contact_solver/solvers/matching_numerics.py",
|
|
33
40
|
"sha256": "e10f5dbf0747163754355cdffd62b9067b2dea82a31d72222e368f67f7a8cd66",
|
|
34
|
-
"extracted_sha256": "e10f5dbf0747163754355cdffd62b9067b2dea82a31d72222e368f67f7a8cd66"
|
|
41
|
+
"extracted_sha256": "e10f5dbf0747163754355cdffd62b9067b2dea82a31d72222e368f67f7a8cd66",
|
|
42
|
+
"current_sha256": "67abc420c4b84ea8947a798b3913597baee9aaa9b5c9ad069dac82811b400889",
|
|
43
|
+
"post_extraction_changes": [
|
|
44
|
+
"Optional Newton-stage timing and LSMR iteration diagnostics; numerical algorithm and tolerances unchanged."
|
|
45
|
+
]
|
|
35
46
|
},
|
|
36
47
|
"src/sci_solver/solvers/reaction_matching.py": {
|
|
37
48
|
"upstream_path": "src/contact_solver/solvers/reaction_matching.py",
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# API and numerical options
|
|
2
|
+
|
|
3
|
+
`solve(initial_positions, final_positions, *, time_horizon, min_distance,
|
|
4
|
+
initial_velocities=None, final_velocities=None, options=None)` returns a `Solution`.
|
|
5
|
+
Endpoint arrays have shape `(N, d)` with `N >= 2` and `d >= 2`.
|
|
6
|
+
|
|
7
|
+
## Results
|
|
8
|
+
|
|
9
|
+
| Member | Meaning |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| `success` | Matching checks and continuous separation both passed. |
|
|
12
|
+
| `sample(times, derivative=0)` | Array with shape `(N, len(times), d)`; derivative orders 0–3. |
|
|
13
|
+
| `trajectory` | Knot times, relative cubic coefficients, and barycenter coefficients. |
|
|
14
|
+
| `contacts` | Pair indices, times, normals, relative velocities, and reaction masses. |
|
|
15
|
+
| `acceleration_cost` | Integrated sum of squared robot accelerations. |
|
|
16
|
+
| `metrics` | Status, reason, residuals, separation, backend, timing, and recovery details. |
|
|
17
|
+
|
|
18
|
+
Times may be unordered but must be finite and inside the horizon. At a contact,
|
|
19
|
+
the third derivative uses the segment to its right; the final endpoint uses the
|
|
20
|
+
last segment. Orders 0–2 are continuous up to the matching tolerance.
|
|
21
|
+
|
|
22
|
+
## Options
|
|
23
|
+
|
|
24
|
+
Pass `SolverConfig(...)` through `options`. Numerical tolerances retain the
|
|
25
|
+
reference defaults; equation systems use contact components by default since 0.2.0.
|
|
26
|
+
|
|
27
|
+
| Option | Default | Meaning |
|
|
28
|
+
| --- | --- | --- |
|
|
29
|
+
| `sci_detection_tol` | `0.0` | Allowed absolute separation deficit. |
|
|
30
|
+
| `sci_residual_tol` | `1e-7` | Matching and endpoint residual tolerance. |
|
|
31
|
+
| `sci_mass_tol` | `1e-9` | Allowed negative reaction mass within tolerance. |
|
|
32
|
+
| `sci_min_contact_gap` | `0.0` | Minimum knot gap; zero still requires strict ordering. |
|
|
33
|
+
| `sci_root_max_iterations` | `100` | Newton iterations per matching solve. |
|
|
34
|
+
| `sci_reaction_recovery` | `True` | Enable condensed recovery when matching fails. |
|
|
35
|
+
| `timeout` | `300.0` | Cooperative solve deadline in seconds. |
|
|
36
|
+
| `use_analytical_jacobian` | `True` | Use the analytical matching Jacobian. |
|
|
37
|
+
| `sci_fleet_mode` | `"components"` | `"full"`, `"active"`, or `"components"`; see below. |
|
|
38
|
+
| `sci_profile_newton` | `False` | Record detailed Newton-stage times and LSMR iteration counts. |
|
|
39
|
+
|
|
40
|
+
Statuses are `success`, `unresolved`, `root_failure`, and `invalid_solution`.
|
|
41
|
+
`metrics["convergence_reason"]` supplies details. Unsuccessful iterates remain
|
|
42
|
+
available for diagnosis. The deadline is checked between numerical operations;
|
|
43
|
+
it does not interrupt an in-progress linear solve.
|
|
44
|
+
|
|
45
|
+
For direct control, use `Config`, `ProblemConfig`, and `ContactSolver`, followed by
|
|
46
|
+
`set_initial_states`, `set_final_states`, and `generate_trajectories`. This retains
|
|
47
|
+
the reference interface. Its `ProblemConfig.timestep` is a legacy configuration
|
|
48
|
+
field used by automatic horizon selection when the horizon is omitted; it does
|
|
49
|
+
not discretize contact matching or collision checking. The convenience `solve`
|
|
50
|
+
function requires an explicit horizon.
|
|
51
|
+
|
|
52
|
+
## Contact components
|
|
53
|
+
|
|
54
|
+
`components` is the default for `solve`, `ContactSolver`, and the CLI, including
|
|
55
|
+
saved configurations that omit `sci_fleet_mode`. `full` uses all robots in every
|
|
56
|
+
contact block. `active` eliminates robots with no
|
|
57
|
+
current contacts and solves one system for the remaining robots. `components`
|
|
58
|
+
also partitions the contact graph and solves one system per connected group.
|
|
59
|
+
The graph is rebuilt with union-find after every insertion or removal; there is
|
|
60
|
+
no persistent graph cache. Groups whose robot and contact identities have not
|
|
61
|
+
changed retain their solution, trajectory, and validation checks. Changed groups,
|
|
62
|
+
including merges and splits, are rebuilt. Every group uses the same Newton and
|
|
63
|
+
recovery routines and its own endpoint barycenter. Uninvolved robots follow their unconstrained
|
|
64
|
+
endpoint cubics. Collision search still covers all pairs and can activate robots
|
|
65
|
+
or join components on later iterations.
|
|
66
|
+
|
|
67
|
+
Component trajectories are joined by translating cubic coefficients onto the
|
|
68
|
+
union of their knots. Independent components can have simultaneous contacts.
|
|
69
|
+
Minimum knot gaps and ordering constraints apply within each component. If a
|
|
70
|
+
new edge joins components whose existing contact times coincide or violate the
|
|
71
|
+
configured gap, the solver returns `unresolved` with reason
|
|
72
|
+
`merged_component_knot_gap`; it does not move already solved contact times to
|
|
73
|
+
make the merge fit the current Hermite representation.
|
|
74
|
+
|
|
75
|
+
`Solution`, sampling, contact indices, and CLI exports retain their fleet-wide
|
|
76
|
+
shape. For low-level diagnostics in the reduced modes, `ContactSolver.system`
|
|
77
|
+
is a tuple of local matching systems, `solution` concatenates their local vectors,
|
|
78
|
+
and `matching_components` associates each local system/vector/trajectory with
|
|
79
|
+
its original robot IDs. `metrics["system_size"]` is the sum of local system sizes;
|
|
80
|
+
`partition_history` records robot groups, contact counts, sizes, and `rebuilt` and
|
|
81
|
+
`reused` groups after each contact-set change. `component_builds` and
|
|
82
|
+
`component_reuses` total these events. Each root record reports a solve actually
|
|
83
|
+
performed; reused components do not add root records.
|
|
84
|
+
|
|
85
|
+
`metrics["timing"]` includes `stage_seconds` and `stage_calls` for partitioning,
|
|
86
|
+
assembly, Newton, recovery, reconstruction, validation, and collision search.
|
|
87
|
+
Stages do not overlap. Partitioning includes union-find, index grouping, and
|
|
88
|
+
sorting; assembly includes local systems and initial vectors; recovery includes its own
|
|
89
|
+
assembly/reconstruction/checks. `other` accounts for remaining solve overhead.
|
|
90
|
+
Final output sampling and export of fleet-indexed contact vectors are separately
|
|
91
|
+
reported as `postprocess_time`; `contact_export_seconds` is the export portion in
|
|
92
|
+
reduced modes. `wall_time` includes postprocessing.
|
|
93
|
+
Use these stages for comparisons: the legacy `matching_seconds` in full mode
|
|
94
|
+
also contains active-set bookkeeping, while reduced modes report Newton plus
|
|
95
|
+
recovery there. Timings are wall-clock seconds, not CPU-time measurements.
|
|
96
|
+
|
|
97
|
+
When `sci_profile_newton=True`, Newton root records additionally contain
|
|
98
|
+
`newton_timing.stage_seconds`, `newton_timing.stage_calls`, and `lsmr_iterations`.
|
|
99
|
+
These nested stages separate residual/Jacobian evaluation, band assembly, band
|
|
100
|
+
solve, sparse assembly/scaling, LSMR, line-search residual evaluation, and other
|
|
101
|
+
Newton work. They are subdivisions of the outer `newton` stage, not additional
|
|
102
|
+
solve time. Recovery retains its own outer timer. Use profiling separately from
|
|
103
|
+
baseline timing comparisons because instrumentation itself adds overhead.
|
|
104
|
+
|
|
105
|
+
See [the component reuse benchmark](component-reuse.md) for current measured
|
|
106
|
+
costs and [the original fleet benchmark](fleet-partitions.md) for the prototype.
|
|
107
|
+
|
|
108
|
+
## Saved problems
|
|
109
|
+
|
|
110
|
+
```sh
|
|
111
|
+
sci-solve --states endpoints.npz --config examples/config.json \
|
|
112
|
+
--output outputs/metrics.json --trajectories outputs/trajectories.npz
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Input NPZ keys are `initial_positions`, `final_positions`, and optionally
|
|
116
|
+
`initial_velocities`, `final_velocities`. JSON configuration uses `problem` and
|
|
117
|
+
`solver` objects; unknown fields are rejected. `Config.to_json` and
|
|
118
|
+
`Config.from_json` support roundtrips without a YAML dependency.
|
|
119
|
+
|
|
120
|
+
The CLI exits zero only for a successful solve. Sampled output includes times,
|
|
121
|
+
positions, velocities, accelerations, contact states, and contact pairs.
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# Component reuse benchmark
|
|
2
|
+
|
|
3
|
+
This report records the benchmark before the 0.2.0 release. At that time, full
|
|
4
|
+
mode remained the default. Version 0.2.0 adopts the optimized component method;
|
|
5
|
+
the measurements and source hashes below retain their original meaning.
|
|
6
|
+
|
|
7
|
+
The three general improvements reduce component-driver overhead without any
|
|
8
|
+
fleet-size threshold. The selected small interacting cases improve by 11–24%
|
|
9
|
+
against the prototype, but remain 9–24% slower than full-fleet solves. At N=20,
|
|
10
|
+
three cases improve by 22–30%; the other two change little. The optimized
|
|
11
|
+
components are 3–10 times faster than full-fleet solves on these five N=20 cases.
|
|
12
|
+
Union-find is a small fraction of runtime. Newton evaluation and sparse fallback
|
|
13
|
+
are the useful next profiling targets.
|
|
14
|
+
|
|
15
|
+
## Changes
|
|
16
|
+
|
|
17
|
+
1. Components hold a matching system, vector, endpoint data, and trajectory.
|
|
18
|
+
They no longer construct nested `Config` and `ContactSolver` objects. Contact
|
|
19
|
+
initialization, recovery, and validation use shared numerical functions.
|
|
20
|
+
2. Initialization reads only the selected relative coordinates. Reconstruction
|
|
21
|
+
assembles relative cubic coefficients directly. Fleet-indexed public contact
|
|
22
|
+
vectors are exported once at the end. When a single component already has the
|
|
23
|
+
full fleet layout, its trajectory is returned directly; this is a representation
|
|
24
|
+
identity that applies at every N.
|
|
25
|
+
3. Unchanged robot/contact groups retain their solution, trajectory, and checks.
|
|
26
|
+
Stable contact identities distinguish retained contacts from newly inserted
|
|
27
|
+
ones, including after recovery reorders contacts. Merges, splits, insertions,
|
|
28
|
+
and removals rebuild affected groups. No component state persists across solves.
|
|
29
|
+
|
|
30
|
+
Union-find is still rebuilt after every contact-set update. No dependencies,
|
|
31
|
+
matching equations, numerical tolerances, or solver selection thresholds were
|
|
32
|
+
added. The default remains `full`; no full experiment campaign was rerun.
|
|
33
|
+
|
|
34
|
+
These measurements evaluate the three changes together, not their isolated
|
|
35
|
+
contributions. Stage timings and component reuse counts explain where work was
|
|
36
|
+
removed, but are not a three-way ablation.
|
|
37
|
+
|
|
38
|
+
## Protocol
|
|
39
|
+
|
|
40
|
+
Measured on 2026-10-17, macOS arm64, Python 3.14.7, NumPy 2.5.3, SciPy 1.18.1,
|
|
41
|
+
native collision backend, and numerical-library thread limits of one. The input
|
|
42
|
+
settings match the prior benchmarks: minimum distance 0.5, separation allowance
|
|
43
|
+
0.001, residual tolerance 1e-7, recovery enabled, and a 30-second deadline.
|
|
44
|
+
|
|
45
|
+
The selection was fixed before timing: N=2 uses the first free seed and first two
|
|
46
|
+
interacting seeds; N=4 uses the first seed at each observed contact count 0–3;
|
|
47
|
+
N=20 uses all five previously benchmarked regression cases. Endpoints and
|
|
48
|
+
configuration are embedded in the raw report.
|
|
49
|
+
|
|
50
|
+
`Before` is SCI commit `5e7a8e3c667f70c7230db2024d9525254eb409f2`, archived
|
|
51
|
+
before editing and imported as a separate package. `Full` and `After` use the
|
|
52
|
+
current sources, whose hashes are recorded. All run in the same process with one
|
|
53
|
+
warmup per case/variant, then 21 repetitions for N=2/4 and seven for N=20. Case
|
|
54
|
+
and variant order are shuffled deterministically. This gives 546 timed solves.
|
|
55
|
+
|
|
56
|
+
Detailed Newton profiling is disabled in this comparison. A separate pass uses
|
|
57
|
+
three profiled repetitions per N=20 case. Reported times are medians; stage
|
|
58
|
+
medians need not sum exactly to the median total. Quartiles are in the CSV.
|
|
59
|
+
|
|
60
|
+
## Solve times
|
|
61
|
+
|
|
62
|
+
Milliseconds. `Reduction` compares optimized components against the prototype.
|
|
63
|
+
Solve time excludes final output sampling and contact-vector export.
|
|
64
|
+
|
|
65
|
+
| N | Seed | Final contacts | Full | Components before | Components after | Reduction |
|
|
66
|
+
| ---: | ---: | ---: | ---: | ---: | ---: | ---: |
|
|
67
|
+
| 2 | 0 | 0 | 0.117 | 0.129 | 0.100 | 22.9% |
|
|
68
|
+
| 2 | 2 | 1 | 0.825 | 1.212 | 0.925 | 23.7% |
|
|
69
|
+
| 2 | 10 | 1 | 0.837 | 1.208 | 0.915 | 24.3% |
|
|
70
|
+
| 4 | 0 | 1 | 0.869 | 1.220 | 1.078 | 11.7% |
|
|
71
|
+
| 4 | 1 | 0 | 0.128 | 0.136 | 0.106 | 22.4% |
|
|
72
|
+
| 4 | 8 | 3 | 3.638 | 4.917 | 4.001 | 18.6% |
|
|
73
|
+
| 4 | 40 | 2 | 1.951 | 2.616 | 2.336 | 10.7% |
|
|
74
|
+
| 20 | 2 | 3 | 82.280 | 19.562 | 19.436 | 0.6% |
|
|
75
|
+
| 20 | 9 | 13 | 1610.075 | 545.170 | 537.159 | 1.5% |
|
|
76
|
+
| 20 | 15 | 8 | 101.151 | 24.667 | 17.956 | 27.2% |
|
|
77
|
+
| 20 | 35 | 7 | 1101.601 | 169.983 | 118.573 | 30.2% |
|
|
78
|
+
| 20 | 47 | 6 | 135.752 | 17.466 | 13.587 | 22.2% |
|
|
79
|
+
|
|
80
|
+
Seed 2 has overlapping interquartile ranges (before 19.353–20.522 ms,
|
|
81
|
+
after 19.160–20.046 ms); its apparent 0.6% gain should be treated as inconclusive.
|
|
82
|
+
Seed 9 improves little because most time is inside Newton, not component setup.
|
|
83
|
+
The small-case selection is representative of contact counts, not an estimate
|
|
84
|
+
over the entire previous 100-case set.
|
|
85
|
+
|
|
86
|
+
The CSV also records the complete `generate_trajectories` call, including final
|
|
87
|
+
contact export and sampled output. Its before/after reduction is 8–17% on the
|
|
88
|
+
small interacting cases, and 0.7%, 1.4%, 24.8%, 29.9%, and 19.2% on the five N=20
|
|
89
|
+
cases respectively. Thus the improvement remains when moved export work is
|
|
90
|
+
included. For N=20 the export itself takes 0.066–0.106 ms. Configuration and cost
|
|
91
|
+
evaluation are outside both timers.
|
|
92
|
+
|
|
93
|
+
For N=2 seed 2, component assembly falls from 0.171 to 0.076 ms and reconstruction
|
|
94
|
+
from 0.221 to 0.053 ms. Newton stays at about 0.473 ms in all three variants.
|
|
95
|
+
The remaining component/full gap is 0.100 ms. For N=4 seed 40, the gap is 0.386 ms
|
|
96
|
+
over two contact updates, with reconstruction contributing 0.290 ms in components
|
|
97
|
+
versus 0.069 ms in full mode. The overhead scales with components, knots, and
|
|
98
|
+
updates; it is not a constant tax determined only by the fleet size.
|
|
99
|
+
|
|
100
|
+
## N=20 outer stages
|
|
101
|
+
|
|
102
|
+
Accumulated milliseconds per optimized component solve, from the unprofiled
|
|
103
|
+
seven-repeat comparison. Stages are disjoint.
|
|
104
|
+
|
|
105
|
+
| Stage | Seed 2 | Seed 9 | Seed 15 | Seed 35 | Seed 47 |
|
|
106
|
+
| --- | ---: | ---: | ---: | ---: | ---: |
|
|
107
|
+
| Partition: union-find, grouping, sorting | 0.028 | 0.135 | 0.059 | 0.064 | 0.049 |
|
|
108
|
+
| Component assembly | 0.604 | 3.122 | 0.878 | 0.980 | 0.903 |
|
|
109
|
+
| Newton | 16.189 | 516.226 | 11.606 | 111.093 | 7.882 |
|
|
110
|
+
| Reaction recovery | 0.000 | 7.170 | 0.000 | 1.185 | 0.000 |
|
|
111
|
+
| Trajectory reconstruction | 0.840 | 3.204 | 1.854 | 1.886 | 1.654 |
|
|
112
|
+
| Validation | 0.637 | 2.609 | 1.250 | 1.107 | 1.130 |
|
|
113
|
+
| Collision search | 0.562 | 2.705 | 1.224 | 1.187 | 1.020 |
|
|
114
|
+
| Other bookkeeping | 0.600 | 2.095 | 1.128 | 1.156 | 0.989 |
|
|
115
|
+
| Total solve | 19.436 | 537.159 | 17.956 | 118.573 | 13.587 |
|
|
116
|
+
|
|
117
|
+
There are respectively 5, 15, 8, 9, and 8 partition calls: approximately
|
|
118
|
+
5.6–9.0 microseconds per call. Partitioning is 0.025–0.362% of solve time and
|
|
119
|
+
includes more than union-find alone. Graph rebuilding costs
|
|
120
|
+
O(m alpha(A)) plus O(A log A) deterministic ordering, for m contacts and A active
|
|
121
|
+
robots. It is not constant, but is negligible on these cases.
|
|
122
|
+
|
|
123
|
+
Actual component solves and reuse events explain the savings:
|
|
124
|
+
|
|
125
|
+
| Seed | Newton calls before | Newton calls after | Unchanged groups reused | Function evaluations before → after |
|
|
126
|
+
| ---: | ---: | ---: | ---: | ---: |
|
|
127
|
+
| 2 | 5 | 5 | 0 | 143 → 143 |
|
|
128
|
+
| 9 | 32 | 15 | 17 | 658 → 641 |
|
|
129
|
+
| 15 | 22 | 8 | 14 | 96 → 82 |
|
|
130
|
+
| 35 | 20 | 9 | 11 | 598 → 470 |
|
|
131
|
+
| 47 | 17 | 9 | 8 | 78 → 70 |
|
|
132
|
+
|
|
133
|
+
Recovery evaluations are included in the last column, separately timed above.
|
|
134
|
+
The changes also alter floating-point warm starts by avoiding global coordinate
|
|
135
|
+
round trips; all numerical comparisons and physical checks pass below. The
|
|
136
|
+
seed-35 gain should not be attributed entirely to its 11 skipped initial residual
|
|
137
|
+
evaluations: its total evaluation count also falls substantially.
|
|
138
|
+
|
|
139
|
+
## Inside Newton
|
|
140
|
+
|
|
141
|
+
Milliseconds accumulated across all Newton calls in each solve, measured in the
|
|
142
|
+
separate three-repeat profiling pass. These are subdivisions of Newton, not
|
|
143
|
+
additional time to add to the outer table. Recovery has its own timer.
|
|
144
|
+
|
|
145
|
+
| Newton stage | Seed 2 | Seed 9 | Seed 15 | Seed 35 | Seed 47 |
|
|
146
|
+
| --- | ---: | ---: | ---: | ---: | ---: |
|
|
147
|
+
| Residual and Jacobian evaluation | 5.723 | 44.742 | 5.557 | 14.398 | 3.791 |
|
|
148
|
+
| Band matrix assembly | 0.989 | 17.833 | 0.955 | 3.013 | 0.576 |
|
|
149
|
+
| Banded linear solve | 1.088 | 28.689 | 1.155 | 3.352 | 0.789 |
|
|
150
|
+
| Sparse assembly and scaling | 0.000 | 12.852 | 0.000 | 3.455 | 0.000 |
|
|
151
|
+
| Sparse LSMR solve | 0.000 | 332.378 | 0.000 | 55.412 | 0.000 |
|
|
152
|
+
| Line-search residual evaluations | 6.827 | 71.132 | 2.647 | 28.192 | 1.732 |
|
|
153
|
+
| Other Newton work | 1.593 | 7.558 | 1.237 | 4.734 | 1.057 |
|
|
154
|
+
| Total Newton | 16.273 | 514.929 | 11.608 | 112.604 | 7.986 |
|
|
155
|
+
| Total profiled solve | 19.377 | 535.144 | 17.900 | 120.019 | 13.723 |
|
|
156
|
+
|
|
157
|
+
| Seed | Newton iterations | Residual/Jacobian calls | Line-search residual calls | LSMR calls | LSMR iterations |
|
|
158
|
+
| ---: | ---: | ---: | ---: | ---: | ---: |
|
|
159
|
+
| 2 | 37 | 42 | 101 | 0 | 0 |
|
|
160
|
+
| 9 | 106 | 121 | 482 | 14 | 15,232 |
|
|
161
|
+
| 15 | 34 | 42 | 40 | 0 | 0 |
|
|
162
|
+
| 35 | 82 | 91 | 369 | 10 | 2,880 |
|
|
163
|
+
| 47 | 29 | 38 | 32 | 0 | 0 |
|
|
164
|
+
|
|
165
|
+
Seed 9 spends 62% of its complete profiled solve in LSMR and another 22% in
|
|
166
|
+
residual/Jacobian and line-search evaluation. For seed 35 those shares are 46%
|
|
167
|
+
and 35%. The easier cases use no LSMR; evaluation accounts for 40–65% of their
|
|
168
|
+
total solve time. Banded linear solves take only 3–6% across these cases.
|
|
169
|
+
|
|
170
|
+
The next general optimization target is therefore numerical evaluation and the
|
|
171
|
+
fallback path. For the hard cases, inspect why fallback needs so many iterations
|
|
172
|
+
before changing the linear solver or safeguards. For the easier cases, reducing
|
|
173
|
+
repeated residual/Jacobian allocations and polynomial work is more promising
|
|
174
|
+
than a more elaborate graph algorithm. These are directions justified by the
|
|
175
|
+
profile, not measured speedup claims. The current results do not justify an
|
|
176
|
+
N-dependent policy.
|
|
177
|
+
|
|
178
|
+
## Validation and reproduction
|
|
179
|
+
|
|
180
|
+
All 546 timed runs and 15 profiled runs converge with valid matching checks and
|
|
181
|
+
continuous separation. The largest relative cost difference from paired full
|
|
182
|
+
mode is 1.19e-11; the largest position-coordinate difference over 201 times is
|
|
183
|
+
6.31e-7. Separate independent polynomial checks pass for all 12 cases in
|
|
184
|
+
`full`, `active`, and `components` (36 checks): endpoints, continuity, jerk
|
|
185
|
+
balance, contact geometry, reaction signs, and continuous separation.
|
|
186
|
+
|
|
187
|
+
Profiling on/off produces exactly equal knot times and trajectory coefficients
|
|
188
|
+
on all five N=20 cases. The refactored full mode matches the preserved version
|
|
189
|
+
exactly across the existing 29-case comparison: identical records and zero
|
|
190
|
+
difference in all 174 arrays, including sampled derivatives and failed solves.
|
|
191
|
+
The complete test suite passes 172 tests; lint and whitespace checks pass.
|
|
192
|
+
|
|
193
|
+
From the SCI checkout, prepare an archive of `5e7a8e3` at `SCI_REFERENCE` with
|
|
194
|
+
the same native collision extension built for the current Python interpreter.
|
|
195
|
+
Then run:
|
|
196
|
+
|
|
197
|
+
```sh
|
|
198
|
+
PYTHONPATH=src python tools/benchmark_component_reuse.py \
|
|
199
|
+
--reference-source "$SCI_REFERENCE"
|
|
200
|
+
|
|
201
|
+
PYTHONPATH="$SCI_REFERENCE/src" python tools/compare_upstream.py \
|
|
202
|
+
--worker sci_solver --output /tmp/sci-reuse-reference-full.json
|
|
203
|
+
PYTHONPATH=src python tools/compare_upstream.py \
|
|
204
|
+
--worker sci_solver --output /tmp/sci-reuse-current-full.json
|
|
205
|
+
PYTHONPATH=src python tools/validate_component_reuse.py \
|
|
206
|
+
--full-before /tmp/sci-reuse-reference-full.json \
|
|
207
|
+
--full-after /tmp/sci-reuse-current-full.json
|
|
208
|
+
PYTHONPATH=src python -m pytest -q
|
|
209
|
+
ruff check .
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
- [Raw runs and source hashes](../validation/component-reuse.json.gz)
|
|
213
|
+
- [Per-case timing CSV and quartiles](../validation/component-reuse.csv)
|
|
214
|
+
- [Detailed Newton profiling CSV](../validation/component-reuse-profile.csv)
|
|
215
|
+
- [Validation records](../validation/component-reuse-validation.json)
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Fleet reductions at N=2 and N=4
|
|
2
|
+
|
|
3
|
+
The original component prototype was slower than the full-fleet solver for
|
|
4
|
+
these small cases. The subsequent [component reuse benchmark](component-reuse.md)
|
|
5
|
+
measures a general optimization of that implementation. The results below are
|
|
6
|
+
historical measurements; they do not prescribe fleet-size dispatch. No solver
|
|
7
|
+
code, defaults, experiment campaigns, or manuscript data were changed for this
|
|
8
|
+
original comparison.
|
|
9
|
+
|
|
10
|
+
## Inputs and protocol
|
|
11
|
+
|
|
12
|
+
All 50 saved fleet-study seeds for N=2 and all 50 for N=4 are included, without
|
|
13
|
+
filtering by outcome. The exact endpoints, velocities, horizons, minimum distance,
|
|
14
|
+
and separation allowance are copied into the self-contained
|
|
15
|
+
[input snapshot](../validation/fleet-small-inputs.json). It records the original
|
|
16
|
+
table, input, and configuration hashes. The selected settings are minimum
|
|
17
|
+
distance 0.5 and separation allowance 0.001; matching uses the current defaults
|
|
18
|
+
including reaction recovery and a 30-second deadline.
|
|
19
|
+
|
|
20
|
+
Each case/mode receives one warmup and 21 timed repetitions. Case and mode order
|
|
21
|
+
are deterministically shuffled within every repetition; execution is sequential
|
|
22
|
+
in one process. The native collision backend is used, with numerical-library
|
|
23
|
+
thread limits set to one. Environment: macOS arm64, Python 3.14.7, NumPy 2.5.3,
|
|
24
|
+
SciPy 1.18.1. The solver implementation is unchanged from the N=20 comparison.
|
|
25
|
+
|
|
26
|
+
Reported times are the median across cases of each case's median over 21 runs.
|
|
27
|
+
They include planning, reconstruction within planning, and collision search,
|
|
28
|
+
and exclude final output sampling. Setup and complete wall time are also logged.
|
|
29
|
+
Input loading is outside the solve timer. Contact-free and interacting cases are
|
|
30
|
+
reported separately because 74 of the 100 cases need no matching equations.
|
|
31
|
+
|
|
32
|
+
## Results
|
|
33
|
+
|
|
34
|
+
Times in milliseconds:
|
|
35
|
+
|
|
36
|
+
| N | Cases | Count | Full | Active | Components |
|
|
37
|
+
| --- | --- | ---: | ---: | ---: | ---: |
|
|
38
|
+
| 2 | Contact-free | 41 | 0.115 | 0.121 | 0.122 |
|
|
39
|
+
| 2 | Interacting | 9 | 0.818 | 1.196 | 1.189 |
|
|
40
|
+
| 4 | Contact-free | 33 | 0.121 | 0.129 | 0.129 |
|
|
41
|
+
| 4 | Interacting | 17 | 0.873 | 1.225 | 1.214 |
|
|
42
|
+
|
|
43
|
+
On the interacting cases, the median paired slowdown for components is 45.5%
|
|
44
|
+
at N=2 and 39.9% at N=4. Components are slower on every interacting case.
|
|
45
|
+
Contact-free cases show a smaller median paired slowdown of 5.4% and 6.7%.
|
|
46
|
+
Summing all 50 per-case median times gives:
|
|
47
|
+
|
|
48
|
+
| N | Full sum (ms) | Active sum (ms) | Components sum (ms) |
|
|
49
|
+
| --- | ---: | ---: | ---: |
|
|
50
|
+
| 2 | 12.095 | 15.632 | 15.596 |
|
|
51
|
+
| 4 | 23.054 | 30.556 | 30.765 |
|
|
52
|
+
|
|
53
|
+
Thus the component implementation takes 28.9% and 33.4% more total time across
|
|
54
|
+
the two respective 50-case sets. This is a ratio of summed per-case medians,
|
|
55
|
+
distinct from the median paired slowdown above. All 6,300 timed solves succeeded.
|
|
56
|
+
The largest relative cost difference from the paired full solve is 4.27e-15;
|
|
57
|
+
the largest coordinate difference over 201 comparison times is 1.21e-7.
|
|
58
|
+
|
|
59
|
+
## Why it is slower
|
|
60
|
+
|
|
61
|
+
Median accumulated stages over the interacting cases, in microseconds:
|
|
62
|
+
|
|
63
|
+
| N | Mode | Partition including UFDS | Assembly | Newton | Reconstruction | Validation | Collision search |
|
|
64
|
+
| --- | --- | ---: | ---: | ---: | ---: | ---: | ---: |
|
|
65
|
+
| 2 | Full | 0 | 69.5 | 468.6 | 41.5 | 111.3 | 77.0 |
|
|
66
|
+
| 2 | Active | 1.9 | 170.4 | 472.0 | 208.1 | 145.4 | 77.7 |
|
|
67
|
+
| 2 | Components | 4.0 | 170.0 | 470.9 | 208.1 | 145.0 | 75.8 |
|
|
68
|
+
| 4 | Full | 0 | 77.2 | 489.5 | 41.6 | 117.1 | 87.4 |
|
|
69
|
+
| 4 | Active | 1.9 | 174.0 | 470.7 | 215.0 | 152.0 | 84.8 |
|
|
70
|
+
| 4 | Components | 4.3 | 173.4 | 468.0 | 213.0 | 151.5 | 86.4 |
|
|
71
|
+
|
|
72
|
+
Recovery was unused. Other bookkeeping is separately logged, and medians need
|
|
73
|
+
not add to the median total. Partition timing includes union-find, grouping,
|
|
74
|
+
and sorting, so it bounds union-find alone from above. It is zero on all
|
|
75
|
+
contact-free runs and about four microseconds per interacting solve.
|
|
76
|
+
|
|
77
|
+
With N=2 there are no variables to eliminate once the two robots interact.
|
|
78
|
+
At N=4 the smaller Newton systems save little time. In both sizes, the extra
|
|
79
|
+
local system assembly, trajectory reconstruction, and bookkeeping outweigh that
|
|
80
|
+
saving. Graph construction contributes only about 1% of the added time in the
|
|
81
|
+
typical interacting case.
|
|
82
|
+
|
|
83
|
+
These measurements identify avoidable setup and reconstruction overhead in the
|
|
84
|
+
prototype. They do not establish a crossover for intermediate fleet sizes.
|
|
85
|
+
The subsequent implementation removes duplicate work and reuses unchanged
|
|
86
|
+
components without introducing any fleet-size thresholds.
|
|
87
|
+
|
|
88
|
+
## Validation and reproduction
|
|
89
|
+
|
|
90
|
+
All 100 cases and three modes also passed separate physical checks outside the
|
|
91
|
+
timing runs: independent polynomial separation, endpoints, continuity, jerk
|
|
92
|
+
balance, contact geometry, and multiplier signs. This gives 300 independent
|
|
93
|
+
case/mode checks. All 6,300 timed records were checked for convergence, residuals,
|
|
94
|
+
continuous separation, paired cost/position differences, and timing accounting.
|
|
95
|
+
[Validation details](../validation/fleet-partitions-small-validation.json) record
|
|
96
|
+
the checker and solver source hashes.
|
|
97
|
+
|
|
98
|
+
From the SCI repository:
|
|
99
|
+
|
|
100
|
+
```sh
|
|
101
|
+
PYTHONPATH=src python tools/benchmark_partitions.py \
|
|
102
|
+
--cases validation/fleet-small-inputs.json --repeats 21 --warmups 1 \
|
|
103
|
+
--output validation/fleet-partitions-small.json
|
|
104
|
+
gzip -n validation/fleet-partitions-small.json
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The original five-case N=20 benchmark remains the default when `--cases` is
|
|
108
|
+
omitted. The new input snapshot is portable and needs no local paper run files.
|
|
109
|
+
|
|
110
|
+
- [Raw runs, compressed JSON](../validation/fleet-partitions-small.json.gz): every
|
|
111
|
+
run, stage timing, root record, environment, and source/input hash.
|
|
112
|
+
- [Per-case CSV](../validation/fleet-partitions-small.csv): medians and quartiles
|
|
113
|
+
for all 300 case/mode combinations.
|
|
114
|
+
- [Aggregate summary](../validation/fleet-partitions-small-summary.json): the
|
|
115
|
+
grouped figures and paired slowdown calculations used above.
|
|
116
|
+
|
|
117
|
+
The benchmark's recorded Git commit is its pre-change base; source hashes
|
|
118
|
+
identify the benchmark script used in the working tree. Only benchmark tooling,
|
|
119
|
+
inputs, results, and documentation changed in this comparison.
|