reality 0.1.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.
Files changed (85) hide show
  1. reality-0.1.0/.github/workflows/ci.yml +78 -0
  2. reality-0.1.0/.gitignore +11 -0
  3. reality-0.1.0/API_DESIGN.md +169 -0
  4. reality-0.1.0/ARCHITECTURE.md +118 -0
  5. reality-0.1.0/CHANGELOG.md +17 -0
  6. reality-0.1.0/CONTRIBUTING.md +24 -0
  7. reality-0.1.0/FUTURES_AUDIT.md +56 -0
  8. reality-0.1.0/FUTURES_RESULTS.json +92 -0
  9. reality-0.1.0/LICENSE +173 -0
  10. reality-0.1.0/PKG-INFO +245 -0
  11. reality-0.1.0/PROJECT.md +63 -0
  12. reality-0.1.0/README.md +210 -0
  13. reality-0.1.0/REALITY_AUDIT.md +497 -0
  14. reality-0.1.0/REALITY_GPU_AUDIT.md +225 -0
  15. reality-0.1.0/REALITY_GPU_RESULTS.json +137 -0
  16. reality-0.1.0/RELEASE_AUDIT.md +66 -0
  17. reality-0.1.0/RELEASE_RESULTS.json +173 -0
  18. reality-0.1.0/ROADMAP.md +75 -0
  19. reality-0.1.0/benchmarks/articulation.py +25 -0
  20. reality-0.1.0/benchmarks/batch_branches.py +37 -0
  21. reality-0.1.0/benchmarks/branching_1000_objects.py +73 -0
  22. reality-0.1.0/benchmarks/explore_scaling.py +69 -0
  23. reality-0.1.0/benchmarks/futures_scaling.py +57 -0
  24. reality-0.1.0/benchmarks/gpu_branch_scaling.py +97 -0
  25. reality-0.1.0/benchmarks/graph_200_objects.py +38 -0
  26. reality-0.1.0/benchmarks/navigation_scaling.py +76 -0
  27. reality-0.1.0/benchmarks/physics_cpu.py +58 -0
  28. reality-0.1.0/examples/articulation.py +31 -0
  29. reality-0.1.0/examples/batch_branches.py +21 -0
  30. reality-0.1.0/examples/game_level_clearance.py +38 -0
  31. reality-0.1.0/examples/mechanism_feasibility.py +25 -0
  32. reality-0.1.0/examples/navigation.py +21 -0
  33. reality-0.1.0/examples/navigation_branch.py +29 -0
  34. reality-0.1.0/examples/parallel_futures.py +53 -0
  35. reality-0.1.0/examples/physics.py +24 -0
  36. reality-0.1.0/examples/query_room.py +9 -0
  37. reality-0.1.0/examples/relationships.py +8 -0
  38. reality-0.1.0/examples/robot_planning.py +38 -0
  39. reality-0.1.0/examples/room_layout_optimization.py +33 -0
  40. reality-0.1.0/examples/visibility.py +11 -0
  41. reality-0.1.0/notebooks/reality_gpu_validation.ipynb +249 -0
  42. reality-0.1.0/pyproject.toml +71 -0
  43. reality-0.1.0/src/reality/__init__.py +128 -0
  44. reality-0.1.0/src/reality/__main__.py +12 -0
  45. reality-0.1.0/src/reality/_accelerators.py +63 -0
  46. reality-0.1.0/src/reality/_articulation.py +274 -0
  47. reality-0.1.0/src/reality/_batch.py +598 -0
  48. reality-0.1.0/src/reality/_branch.py +661 -0
  49. reality-0.1.0/src/reality/_explore.py +227 -0
  50. reality-0.1.0/src/reality/_graph.py +383 -0
  51. reality-0.1.0/src/reality/_loaders.py +190 -0
  52. reality-0.1.0/src/reality/_metadata.py +264 -0
  53. reality-0.1.0/src/reality/_models.py +303 -0
  54. reality-0.1.0/src/reality/_navigation.py +594 -0
  55. reality-0.1.0/src/reality/_physics.py +114 -0
  56. reality-0.1.0/src/reality/_state.py +215 -0
  57. reality-0.1.0/src/reality/_warp_ops.py +574 -0
  58. reality-0.1.0/src/reality/_world.py +945 -0
  59. reality-0.1.0/src/reality/backends/__init__.py +5 -0
  60. reality-0.1.0/src/reality/backends/base.py +37 -0
  61. reality-0.1.0/src/reality/backends/mujoco.py +324 -0
  62. reality-0.1.0/src/reality/experimental/__init__.py +8 -0
  63. reality-0.1.0/src/reality/experimental/predictor.py +60 -0
  64. reality-0.1.0/src/reality/predicates.py +103 -0
  65. reality-0.1.0/src/reality/py.typed +1 -0
  66. reality-0.1.0/tests/conftest.py +20 -0
  67. reality-0.1.0/tests/test_articulation.py +123 -0
  68. reality-0.1.0/tests/test_batch.py +55 -0
  69. reality-0.1.0/tests/test_branching.py +195 -0
  70. reality-0.1.0/tests/test_cli.py +10 -0
  71. reality-0.1.0/tests/test_explore.py +94 -0
  72. reality-0.1.0/tests/test_futures.py +102 -0
  73. reality-0.1.0/tests/test_gpu.py +94 -0
  74. reality-0.1.0/tests/test_graph.py +109 -0
  75. reality-0.1.0/tests/test_loaders.py +115 -0
  76. reality-0.1.0/tests/test_models.py +57 -0
  77. reality-0.1.0/tests/test_navigation.py +189 -0
  78. reality-0.1.0/tests/test_physics.py +175 -0
  79. reality-0.1.0/tests/test_world.py +66 -0
  80. reality-0.1.0/tools/futures_audit.py +374 -0
  81. reality-0.1.0/tools/generate_explore_dataset.py +39 -0
  82. reality-0.1.0/tools/reality_audit.py +529 -0
  83. reality-0.1.0/tools/reality_gpu_audit.py +415 -0
  84. reality-0.1.0/tools/release_audit.py +261 -0
  85. reality-0.1.0/tools/train_explore_predictor.py +29 -0
@@ -0,0 +1,78 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches: [main]
7
+ tags: ["v*"]
8
+ workflow_dispatch:
9
+ inputs:
10
+ publish:
11
+ description: Publish the current package version to PyPI
12
+ required: true
13
+ type: boolean
14
+ default: false
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ jobs:
20
+ test:
21
+ runs-on: ubuntu-latest
22
+ strategy:
23
+ fail-fast: false
24
+ matrix:
25
+ python-version: ["3.11", "3.12", "3.13"]
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ - uses: actions/setup-python@v5
29
+ with:
30
+ python-version: ${{ matrix.python-version }}
31
+ - run: python -m pip install --upgrade pip
32
+ - run: python -m pip install -e ".[dev,physics]"
33
+ - run: ruff format --check .
34
+ - run: ruff check .
35
+ # Run the strict static check once on the oldest supported interpreter.
36
+ # Runtime and packaging checks still run across the complete 3.11–3.13 matrix.
37
+ - name: Type check (mypy)
38
+ if: matrix.python-version == '3.11'
39
+ run: python -m mypy --no-incremental --follow-imports=skip --config-file pyproject.toml src/reality
40
+ - run: pytest
41
+ - run: python -m build
42
+ - run: python -m venv .release-venv
43
+ - run: .release-venv/bin/python -m pip install dist/*.whl
44
+ - run: .release-venv/bin/python -c "import reality; print(reality.__name__)"
45
+
46
+ cuda:
47
+ # Enable only after configuring a self-hosted NVIDIA runner with this repository
48
+ # variable. The CPU job above remains the required portable release gate.
49
+ if: ${{ vars.REALITY_CUDA_RUNNER == 'true' }}
50
+ runs-on: [self-hosted, linux, x64, gpu]
51
+ steps:
52
+ - uses: actions/checkout@v4
53
+ - uses: actions/setup-python@v5
54
+ with:
55
+ python-version: "3.11"
56
+ - run: python -m pip install --upgrade pip
57
+ - run: python -m pip install -e ".[dev,gpu]"
58
+ - run: python -m pytest tests/test_gpu.py -q
59
+ - run: python tools/futures_audit.py --full --output FUTURES_AUDIT.md
60
+
61
+ publish:
62
+ name: Publish to PyPI
63
+ if: github.event_name == 'workflow_dispatch' && inputs.publish || startsWith(github.ref, 'refs/tags/v')
64
+ needs: test
65
+ runs-on: ubuntu-latest
66
+ environment: pypi
67
+ permissions:
68
+ contents: read
69
+ id-token: write
70
+ steps:
71
+ - uses: actions/checkout@v4
72
+ - uses: actions/setup-python@v5
73
+ with:
74
+ python-version: "3.11"
75
+ - run: python -m pip install --upgrade build
76
+ - run: python -m build
77
+ - name: Publish package distributions to PyPI
78
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,11 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .mypy_cache/
4
+ .pytest_cache/
5
+ .ruff_cache/
6
+ .venv/
7
+ build/
8
+ dist/
9
+ *.egg-info/
10
+ navigation.svg
11
+ .warp-cache/
@@ -0,0 +1,169 @@
1
+ # API design
2
+
3
+ ## Stable surface
4
+
5
+ ```python
6
+ import reality
7
+
8
+ world = reality.load("room.glb")
9
+ object_ = world.object("Chair")
10
+ result = world.distance("Chair", "Table")
11
+ ```
12
+
13
+ `World.object()` accepts an object id, a unique name, or a registered `WorldObject`. Duplicate names are permitted but require lookup by id.
14
+
15
+ `WorldObject` exposes `name`, `id`, `transform`, `position`, `rotation`, `scale`, `bounds`, and `mesh`. Bounds are world-space AABBs; `local_bounds` retains the geometry before applying its transform. Rotations are XYZ Euler angles in radians.
16
+
17
+ All predicate methods accept two object references. `near` additionally accepts `within`, defaulting to `1.0` in `World.units`. `distance` returns `PredicateResult[float]`; the remaining methods return `PredicateResult[bool]`.
18
+
19
+ ## Graph and visibility
20
+
21
+ ```python
22
+ visibility = world.visible("Television", from_="Sofa")
23
+ assert visibility.value
24
+ print(visibility.visibility_fraction)
25
+ print([object_.name for object_ in visibility.occluding_objects])
26
+
27
+ for edge in world.relationships("Cup"):
28
+ print(edge.source.name, edge.type.value, edge.target.name)
29
+ ```
30
+
31
+ `RelationshipType` includes `near`, `above`, `below`, `inside`, `contains`, `intersects`, `touching`, and `visible_from`. Graph construction records true deterministic spatial relationships. A successful `visible()` query additionally records a directed `visible_from` relationship from target to viewer.
32
+
33
+ Moving an object is explicit: `world.move("Chair", x=1.0)` or `world.update_transform("Chair", transform)`. Those methods only invalidate and refresh graph edges incident to the changed object.
34
+
35
+ ## Result contract
36
+
37
+ `PredicateResult` has `value`, `measurement`, `units`, `reason`, `evidence`, and `objects`. `distance` is an alias for `measurement`, making this ergonomic:
38
+
39
+ ```python
40
+ result = world.distance("Chair", "Table")
41
+ assert result.value == result.distance
42
+ ```
43
+
44
+ Evidence always includes the world-space bounds involved. The immutable mapping prevents a caller accidentally altering an already-returned result.
45
+
46
+ For a visibility result, evidence additionally contains `visibility_fraction`, `occluding_objects`, and `sample_count`; the first two are surfaced as convenience properties.
47
+
48
+ ## Snapshots, branches, and consequences
49
+
50
+ ```python
51
+ before = world.snapshot()
52
+ future = world.branch()
53
+ future.move("Shelf", x=1.0)
54
+ future.rotate("Shelf", z=0.25)
55
+ future.scale("Shelf", x=1.1)
56
+
57
+ report = future.consequences()
58
+ for consequence in report:
59
+ print(consequence)
60
+
61
+ payload = report.to_dict()
62
+ json_text = report.to_json()
63
+ ```
64
+
65
+ `move` and `rotate` are additive; `scale` is multiplicative. Each call records an ordered, UTC-timestamped change with old/new transforms and the supplied parameters. An unchanged object returned by a branch is the same immutable `WorldObject` instance as in the snapshot. A changed object is a new value object that retains the same opaque mesh reference.
66
+
67
+ `world.compare(branch_a, branch_b)` compares sibling branches. It rejects branches from another world lineage.
68
+
69
+ ## Agents and navigation
70
+
71
+ ```python
72
+ person = world.agent(
73
+ name="Person",
74
+ position=(0.0, 0.0, 0.0),
75
+ height=1.75,
76
+ radius=0.30,
77
+ step_height=0.15,
78
+ )
79
+
80
+ path = person.path_to("Exit")
81
+ reachability = world.reachable("Person", "Exit")
82
+ passage = person.can_pass("Door")
83
+ clearance = person.clearance_to("Exit")
84
+ ```
85
+
86
+ `PathResult` contains `reachable`, path `points`, `distance`, `minimum_clearance`, `narrowest_point`, `blocked_by`, `reason`, and evidence. Path minimum clearance is free space from the agent body to the nearest inflated obstacle. `ReachabilityResult` adds required diameter and estimated available corridor width. Passage checks compare agent diameter and height with the opening AABB. Results expose `value` aliases where predicate-style use is convenient.
87
+
88
+ Agent category names have no behavioral meaning. Only dimensions and optional movement constraints affect navigation.
89
+
90
+ ## Articulation
91
+
92
+ `World.articulate`, `can_open`, `can_extend`, and the `ArticulatedObject` handle return a
93
+ `MotionResult` with requested/maximum motion, blockers, units, reason, samples, and
94
+ evidence. Configuration is explicit, deterministic metadata. `reality.load` reads the
95
+ same schema from a `.reality.json` sidecar, glTF/GLB `extras.reality`, or an explicit
96
+ `metadata=` mapping. The schema supports `units`, `objects.<name>.articulation`, and
97
+ `objects.<name>.physics`; malformed or unknown fields raise `SceneMetadataError` rather
98
+ than being guessed or ignored. The object reference must resolve to a unique loaded
99
+ object. Later metadata sources override earlier articulation/physics fields; `units`
100
+ labels coordinates and never triggers implicit rescaling.
101
+
102
+ ## Physics
103
+
104
+ `PhysicalProperties` describes mass, static/dynamic state, box collision shape,
105
+ friction, restitution, and center-of-mass offset. `simulate`, `drop`, `push`, `contacts`,
106
+ and `stable` return backend-neutral typed results. Simulation-observed consequences are
107
+ labeled separately from direct and downstream deterministic consequences. MuJoCo uses
108
+ oriented boxes built from local bounds and maps dynamic position and orientation back
109
+ to `Transform`. It caches immutable compiled topology per world/backend and creates a
110
+ fresh simulation state for every call, preserving branch isolation. Performance timing
111
+ and cache reuse are reported in `SimulationResult.evidence`.
112
+
113
+ ## Branch batches
114
+
115
+ `World.branches(count)` returns a `BranchBatch`; `randomize("Object.position", ...)`
116
+ stores compact translation deltas and `evaluate(predicates=("collision",))` runs the CPU
117
+ reference batch. CUDA selection is capability-checked and never silently falls back.
118
+
119
+ `World.futures(count)` returns the named `Futures` form for large alternate-world search:
120
+
121
+ ```python
122
+ from reality.predicates import collision, distance, maximize, no_collision
123
+
124
+ futures = world.futures(10_000).randomize_position(
125
+ "Table", x=(-1.0, 1.0), y=(-0.5, 0.5), z=(0.0, 0.0), seed=7
126
+ )
127
+ evaluation = futures.evaluate([collision("Table", "Chair"), distance("Table", "Chair")])
128
+ ranked = evaluation.rank(
129
+ constraints=[no_collision("Table", "Chair")],
130
+ objectives=[maximize(distance("Table", "Chair"))],
131
+ )
132
+ candidate = ranked.best(1)[0]
133
+ branch = candidate.materialize()
134
+ ```
135
+
136
+ `PredicateSpec` values are typed and reusable. `where()` applies hard `Condition`
137
+ constraints; `rank()` applies weighted `Objective` values; candidates stay compact until
138
+ `materialize()` or `consequences()` is called. `collision` and `distance` use world AABBs,
139
+ and batch `visibility` is a deterministic AABB ray experiment. Batched rotations/scales
140
+ are accepted and retained for future kernels, but currently raise `NotImplementedError`
141
+ when evaluated with non-default values. `BatchEvaluation.to_dict()` and
142
+ `RankedFutures.to_dict()` provide machine-readable summaries.
143
+
144
+ ## Exact exploration
145
+
146
+ `World.explore()` is a convenience layer over `Futures`; it does not introduce a second
147
+ optimizer or different predicate semantics.
148
+
149
+ ```python
150
+ result = world.explore(
151
+ possibilities=100_000,
152
+ changes=[reality.position("Shelf", x=(-1.0, 1.0))],
153
+ constraints=[no_collision("Shelf", "Door")],
154
+ objectives=[maximize(distance("Shelf", "Door"))],
155
+ seed=42,
156
+ best=10,
157
+ )
158
+ ```
159
+
160
+ `PositionSearchChange` declares inclusive coordinate ranges. Candidate sampling is
161
+ deterministic for a seed, constraints are exact hard filters, and objective ties are
162
+ broken by candidate index. `ExplorationResult` exposes backend, counts, scores, compact
163
+ deltas, predicate evidence, `best()`, `to_dict()`, and `to_json()`. Returned candidates
164
+ remain lazy `FutureCandidate` values until `materialize()` is called.
165
+
166
+ `backend="auto"` selects CUDA only after the accelerator capability check succeeds;
167
+ `backend="cpu"` forces the NumPy reference path. CUDA evaluates the same documented
168
+ AABB semantics as CPU. Any future learned prioritizer is experimental, opt-in, and may
169
+ only order candidates before exact validation; it never changes valid/invalid results.
@@ -0,0 +1,118 @@
1
+ # Architecture
2
+
3
+ ```
4
+ public API: reality.load, World, WorldObject, Transform, Bounds, PredicateResult
5
+ |
6
+ backend-neutral core
7
+ |
8
+ RealityGraph (edges reference WorldObjects)
9
+ |
10
+ snapshots -> branch delta/graph overlay -> consequences
11
+ |
12
+ Trimesh loader adapter (today)
13
+ ```
14
+
15
+ `_models.py` contains immutable data/value objects. `World` owns lookup indexes and evaluates spatial predicates using the world-space axis-aligned bounds of its objects. `_loaders.py` is the only module that imports Trimesh; it turns a Trimesh scene graph into `WorldObject` instances while retaining the source mesh as an opaque reference.
16
+
17
+ This split means a future USD, Omniverse, renderer, or physics adapter can produce the same core objects without changing application code. Exact mesh queries should arrive as explicitly named capabilities rather than silently changing the existing AABB semantics.
18
+
19
+ The Z axis is vertical for `above` and `below`. The default coordinate unit is metres (`m`), configurable when constructing a `World`.
20
+
21
+ ## Reality Graph and updates
22
+
23
+ `World.graph` is a `RealityGraph` built from known deterministic spatial facts. `Relationship` stores references to the already-loaded `WorldObject` instances, never copied mesh data. `world.relationships("Cup")` returns all incident graph edges.
24
+
25
+ The graph indexes each edge by both object ids. `World.update_transform()` and `World.move()` invalidate only edges incident to the changed object, then recompute that object against the rest of the scene. Relationships entirely between unaffected objects stay in place. Visibility edges are query-driven and are invalidated with either involved object; they are deliberately not eagerly recomputed.
26
+
27
+ Visibility casts rays from the viewer AABB centre to the target centre and corners, treating all other world AABBs as occluders. It returns the visible sample fraction and the objects that blocked at least one ray. This is deterministic but conservative/approximate compared with future mesh-exact visibility.
28
+
29
+ ## Snapshots and persistent branches
30
+
31
+ `World.snapshot()` returns an immutable `WorldSnapshot`. Its object tuple, lookup indexes, relationships, and known visibility results are stable views. Because `WorldObject`, transforms, and bounds are immutable, snapshots safely retain references to existing objects and opaque mesh data instead of copying geometry.
32
+
33
+ `World.branch()` creates a `WorldBranch` over a cached snapshot. The branch maintains:
34
+
35
+ - an object-id-to-replacement delta for changed objects;
36
+ - an ordered `ChangeSet` containing `MoveObject`, `RotateObject`, and `ScaleObject` records;
37
+ - a `RealityGraph` overlay that points at snapshot edges and stores only recalculated edges;
38
+ - `GraphUpdateStats` for predicates present before changes, invalidated, recalculated, and reused.
39
+
40
+ On a transform change, only pairs involving the changed object are recalculated. Base graph edges between unchanged objects remain the same Python objects. Known visibility queries are recalculated because any moved object may become or cease to be an occluder; such a result is classified as downstream when neither visibility endpoint moved.
41
+
42
+ Branches use the exact snapshot they were created from, so later mutations to the source `World` cannot alter an existing branch.
43
+
44
+ ## Consequence comparison
45
+
46
+ `WorldBranch.consequences()` compares its current state with its base snapshot. It evaluates distance and existing graph predicates only across the union of changed-object dependency frontiers, then compares known visibility results. `World.compare(a, b)` applies the same engine to two sibling branches.
47
+
48
+ `ConsequenceSet` contains typed `Consequence` records plus the branch `ChangeSet` and recomputation instrumentation. `to_dict()` and `to_json()` intentionally serialize object identity and geometric evidence without attempting to serialize backend mesh instances.
49
+
50
+ ## Navigation backend
51
+
52
+ The initial navigation backend is deliberately replaceable and CPU-only. Each query projects relevant world AABBs onto an XY occupancy grid, expands obstacles by the querying agent’s radius, and runs deterministic 8-connected A*. Z is up; the agent position’s Z value is its foot/ground elevation. Geometry blocks movement when it overlaps the volume between step height and agent height.
53
+
54
+ The grid covers the start/target rectangle plus `World.navigation_margin` (2 m by default), at `World.navigation_resolution` (0.25 m by default). The target object is treated as a destination marker and excluded from obstacles. This finite query envelope is an explicit assumption: callers needing larger detours should increase the margin.
55
+
56
+ `max_slope` is retained in the agent model and evidence, but the current projected grid is flat and does not yet evaluate terrain slope. `can_pass()` interprets an opening object’s largest horizontal AABB extent as aperture width and its Z extent as aperture height.
57
+
58
+ Navigation queries are lazy and cached by agent/target id. Their `reachable_by`, `unreachable_by`, and `blocks_path_of` edges are stored in the Reality Graph only after a query. Any object move invalidates known navigation queries because any object may become an obstacle; only those known queries are recalculated. Branch consequence analysis compares their reachability and minimum-clearance results as downstream state.
59
+
60
+ `PathResult.export_debug()` writes a standalone SVG: green is query-local walkable space, red rectangles are radius-inflated obstacle regions, the blue polyline is the path, and a dashed line indicates a blocked direct route.
61
+
62
+ ## Articulation and replaceable physics
63
+
64
+ `_metadata.py` validates the portable, explicit Reality metadata schema. `_loaders.py`
65
+ collects glTF/GLB `extras.reality`, an optional `.reality.json` sidecar, and caller
66
+ metadata in that precedence order. It applies validated articulation and physical
67
+ properties after geometry loading. This keeps mesh import backend-neutral and avoids
68
+ inventing physical semantics from names or topology.
69
+
70
+ `_articulation.py` stores explicit revolute/prismatic joints. It samples swept
71
+ world-AABBs at 1 degree or 0.01 m by default and binary-refines the first collision to
72
+ 0.01 degree or 0.0001 m. Conservative AABBs can produce mesh-shape false positives;
73
+ features thinner than a sampling interval can be missed. Known motion queries are lazy
74
+ graph dependencies and are recalculated after relevant geometry changes.
75
+
76
+ `backends/base.py` defines Reality's narrow `PhysicsBackend` protocol.
77
+ `backends/mujoco.py` is the CPU reference: explicit properties become headless MuJoCo
78
+ oriented box rigid bodies, including transform rotation and center-of-mass offsets.
79
+ Compiled topology is cached in the world-local backend; every run creates new MuJoCo
80
+ state and initializes dynamic body poses, so cached models never share branch state.
81
+ When a solve changes several bodies, `RealityGraph.refresh_objects()` updates their
82
+ combined dependency frontier once instead of recalculating changed/changed pairs and
83
+ lazy query invalidation per body. Current limitations include box-only collision shapes,
84
+ a z=0 plane, no simulated joints, and no literal restitution-to-MuJoCo mapping.
85
+
86
+ ## Batched branch memory layout and CUDA boundary
87
+
88
+ `_batch.py` keeps one shared snapshot, immutable base bounds, and one dense
89
+ `branch_count x 3` float64 translation array per changed object. It never builds a
90
+ complete `World` per alternative. `World.futures()` is the large-search spelling;
91
+ `World.branches()` remains compatible with the earlier API. Future candidates are lazy
92
+ views and selected candidates alone materialize copy-on-write `WorldBranch` instances.
93
+ Vectorized CPU collision, AABB distance, and deterministic bounding-volume visibility
94
+ are implemented, with typed predicate specifications, constraints, and ranking.
95
+ `_warp_ops.py` adds custom Warp kernels for branch/object transforms, AABB overlap, AABB
96
+ distance, and centre-to-centre AABB visibility, each with a separate NumPy oracle and
97
+ explicit CUDA synchronization. `_accelerators.py` probes optional Warp lazily. CUDA is
98
+ considered validated only after launches and CPU/GPU parity tests succeed on that host;
99
+ the audit reports `PARTIAL` when CUDA is absent rather than inferring a result. The
100
+ visibility kernel deliberately has the same conservative AABB semantics as the CPU
101
+ batch path—it is not triangle-mesh ray tracing. Graph and explanation logic remains
102
+ CPU-resident by design.
103
+
104
+ ## Exact search and optional learning
105
+
106
+ `_explore.py` composes the existing compact `Futures` representation: it samples one
107
+ deterministic delta matrix per declared change, invokes typed predicates in a batch,
108
+ applies exact conditions, ranks stable objective scores, and returns lazy candidates.
109
+ No candidate branch or mesh copy exists until a selected `FutureCandidate` is
110
+ materialized. GPU predicate arrays currently transfer per evaluation; immutable scene
111
+ arrays are not yet retained across independent calls, and ranking/filter reduction stays
112
+ on CPU so its evidence remains inspectable. Those are measured limitations, not hidden
113
+ fallbacks.
114
+
115
+ `reality.experimental` contains an optional scikit-learn prioritizer. Dataset generation
116
+ uses Reality's exact results as ground truth. The predictor can only propose a candidate
117
+ order; downstream code must run `Futures.evaluate()`/`World.explore()` exact validation
118
+ before accepting a result.
@@ -0,0 +1,17 @@
1
+ # Changelog
2
+
3
+ All notable changes are documented here. This project follows Semantic Versioning from
4
+ its first public release.
5
+
6
+ ## 0.1.0 — Unreleased
7
+
8
+ - Deterministic world loading and AABB spatial predicates.
9
+ - Reality Graph, visibility evidence, snapshots, copy-on-write branches, and consequences.
10
+ - Navigation, articulation, metadata ingestion, and optional CPU MuJoCo simulation.
11
+ - Compact Futures plus `World.explore()` exact layout search.
12
+ - Optional Warp kernels with CPU-oracle validation and optional learned candidate prioritization.
13
+
14
+ ## Release policy
15
+
16
+ Public APIs documented in `API_DESIGN.md` are additive within the 0.1 series. Geometry and
17
+ visibility semantics remain explicit: AABB predicates never silently become mesh-exact.
@@ -0,0 +1,24 @@
1
+ # Contributing
2
+
3
+ Thanks for improving `reality`. This project uses Python 3.11+ and a `src/` layout.
4
+
5
+ ## Setup
6
+
7
+ ```bash
8
+ git clone https://github.com/reality-python/reality.git
9
+ cd reality
10
+ python -m pip install -e ".[dev]"
11
+ ```
12
+
13
+ Before opening a pull request, run:
14
+
15
+ ```bash
16
+ ruff format --check .
17
+ ruff check .
18
+ python -m mypy src/reality
19
+ pytest
20
+ ```
21
+
22
+ Keep public APIs typed and documented. Add focused tests for changes in geometric semantics, including result measurements and evidence. Preserve the backend-neutral public model: imports of a backend belong in an adapter, not `World` or the value objects.
23
+
24
+ By contributing, you agree that contributions are provided under the Apache-2.0 license.
@@ -0,0 +1,56 @@
1
+ # Futures audit
2
+
3
+ Status: **PARTIAL**
4
+
5
+ This report was generated by `python tools/futures_audit.py --full --output FUTURES_AUDIT.md`.
6
+
7
+ ## Reproducibility
8
+
9
+ - Revision: `e15e0dc390792784295ce0de8fc89c766119f1fa`
10
+ - Python: `3.11.9`
11
+ - Platform: `Windows-10-10.0.26200-SP0`
12
+ - Scene objects: `1000`
13
+ - Futures: `10000`
14
+ - CUDA: `CUDA driver/device is unavailable.`
15
+
16
+ ## GPU Validation
17
+
18
+ - CUDA available: `False`
19
+ - CUDA device: `unavailable`
20
+ - Custom Warp kernels tested: `none`
21
+ - CPU/GPU parity status: **NOT_RUN**
22
+ - GPU test count/pass count: `0` / `0`
23
+ - GPU execution actually used: `False`
24
+
25
+ CUDA validation could not be performed: CUDA driver/device is unavailable.
26
+
27
+ ## Compact state evidence
28
+
29
+ - Shared snapshot: `True`
30
+ - Measured NumPy delta bytes: `240000`
31
+ - Logical float64 delta payload: `240000`
32
+ - 10k evaluation seconds: `0.659171`
33
+ - Candidates without collision: `10000`
34
+
35
+ ## Scaling
36
+
37
+ | futures | creation seconds | distance seconds | delta bytes |
38
+ |---:|---:|---:|---:|
39
+ | 100 | 0.001881 | 0.000137 | 2400 |
40
+ | 1000 | 0.001212 | 0.000225 | 24000 |
41
+ | 10000 | 0.001903 | 0.002073 | 240000 |
42
+ | 50000 | 0.002214 | 0.010108 | 1200000 |
43
+ | 100000 | 0.005615 | 0.030814 | 2400000 |
44
+
45
+ ## CPU/GPU boundary
46
+
47
+ Visibility is a deterministic AABB bounding-volume experiment, not exact mesh occlusion.
48
+
49
+ Future GPU work should keep immutable bounds resident, batch ray and broad-phase kernels, and
50
+ perform filtering/ranking reductions before transferring selected candidates to Python.
51
+
52
+ ## Limitations
53
+
54
+ - CUDA validation could not be performed: CUDA driver/device is unavailable.
55
+ - Visibility uses deterministic AABB ray tests, not exact triangle-mesh rays.
56
+ - Batched rotation and scale are stored but predicate evaluation is not implemented yet.
@@ -0,0 +1,92 @@
1
+ {
2
+ "status": "PARTIAL",
3
+ "revision": "e15e0dc390792784295ce0de8fc89c766119f1fa",
4
+ "python": "3.11.9",
5
+ "platform": "Windows-10-10.0.26200-SP0",
6
+ "cuda": {
7
+ "installed": true,
8
+ "version": "1.17.0",
9
+ "cuda_available": false,
10
+ "devices": [
11
+ "cpu"
12
+ ],
13
+ "reason": "CUDA driver/device is unavailable."
14
+ },
15
+ "gpu_validation": {
16
+ "cuda_available": false,
17
+ "device": null,
18
+ "custom_warp_kernels_tested": [],
19
+ "kernel_parity_count": 0,
20
+ "kernel_parity_pass_count": 0,
21
+ "gpu_test_count": 0,
22
+ "gpu_pass_count": 0,
23
+ "cpu_gpu_parity": "NOT_RUN",
24
+ "gpu_execution_used": false,
25
+ "failures": [],
26
+ "pytest": {
27
+ "status": "NOT_RUN",
28
+ "count": 0,
29
+ "passed": 0,
30
+ "failed": 0,
31
+ "skipped": 0
32
+ }
33
+ },
34
+ "scene_objects": 1000,
35
+ "futures": 10000,
36
+ "delta_bytes": 240000,
37
+ "logical_delta_bytes": 240000,
38
+ "evaluation_seconds": 0.6591709999920567,
39
+ "selected_without_collision": 10000,
40
+ "shared_snapshot": true,
41
+ "predicates": [
42
+ "collision",
43
+ "distance",
44
+ "visibility"
45
+ ],
46
+ "visibility_is_bounding_volume": true,
47
+ "limitations": [
48
+ "CUDA validation could not be performed: CUDA driver/device is unavailable.",
49
+ "Visibility uses deterministic AABB ray tests, not exact triangle-mesh rays.",
50
+ "Batched rotation and scale are stored but predicate evaluation is not implemented yet."
51
+ ],
52
+ "gpu_acceleration_next": [
53
+ "Keep AABB centers/extents resident on GPU across many candidate batches.",
54
+ "Move visibility ray batches and broad-phase pair culling to Warp kernels.",
55
+ "Add GPU reduction kernels for filtering and ranking to reduce host transfers."
56
+ ],
57
+ "scaling": [
58
+ {
59
+ "futures": 100,
60
+ "creation_seconds": 0.0018807000014930964,
61
+ "distance_seconds": 0.00013670000771526247,
62
+ "delta_bytes": 2400
63
+ },
64
+ {
65
+ "futures": 1000,
66
+ "creation_seconds": 0.0012117000005673617,
67
+ "distance_seconds": 0.00022480000916402787,
68
+ "delta_bytes": 24000
69
+ },
70
+ {
71
+ "futures": 10000,
72
+ "creation_seconds": 0.0019033999997191131,
73
+ "distance_seconds": 0.0020733999990625307,
74
+ "delta_bytes": 240000
75
+ },
76
+ {
77
+ "futures": 50000,
78
+ "creation_seconds": 0.002214100008131936,
79
+ "distance_seconds": 0.010108400005265139,
80
+ "delta_bytes": 1200000
81
+ },
82
+ {
83
+ "futures": 100000,
84
+ "creation_seconds": 0.005615399990347214,
85
+ "distance_seconds": 0.030813899997156113,
86
+ "delta_bytes": 2400000
87
+ }
88
+ ],
89
+ "cpu_distance_oracle": [
90
+ 1.0
91
+ ]
92
+ }