icon

pyspect

  • Home
Tutorials
  • Getting Started
  • Creating Sets
Paper Examples
  • Examples for CDC '25
Implementations
  • hj_reachability
  • ZonoOpt
Helper Implementations
  • Base
  • Axes
  • Plotly
  • Debug
Reference
  • Set Builders
  • Logic Fragments
  • Temporal Logic Trees
  • TLT Primitives

Creating Sets

Previous Next

Creating Sets¶

Learn how to describe regions in space with SetBuilders, evaluate them on a backend grid, and plot the result.

Run the Setup cell first, then each section in order. You can copy the code into your own scripts.


What you will learn¶

  1. What a SetBuilder is and how out = S(impl) produces a grid array
  2. Basic shapes: HalfSpaceSet, AlignedBoxSet, and combinations
  3. How to visualize results with plot3d / plot2d helpers

Not covered here: temporal logic (TLT), BallSet, CylinderSet.


Workflow (every example)¶

Step Action Example
1 Describe S = AlignedBoxSet(...)
2 Realize out = S(impl)
3 Visualize plot3d(out, title='...')

Setup¶

Goal: create a backend (TVHJImpl) and small helpers (plot3d, plot2d) used in the examples below.

  • The state grid is (t, x, y, yaw) with Air3d dynamics.
  • When you only constrain x and y, the set does not depend on yaw.
  • 3D plots use axes (x, y, yaw) - the shape looks like a prism along yaw.
In [1]:
Copied!
from math import pi

import numpy as np
from pyspect import Inter, Union, Compl
from pyspect.set_builder import AlignedBoxSet, HalfSpaceSet
from pyspect.impls.static import StaticImpl

AXES = [
    dict(name='x', bounds=[-5, +5], points=25),
    dict(name='y', bounds=[-5, +5], points=25),
    dict(name='z', bounds=[-5, +5], points=25),
]
impl = StaticImpl(AXES)

print('Axes |', ', '.join([f'{impl.axis_name(i)}: {n}'
                           for i, n in zip(range(impl.ndim), impl._shape)]))
from math import pi import numpy as np from pyspect import Inter, Union, Compl from pyspect.set_builder import AlignedBoxSet, HalfSpaceSet from pyspect.impls.static import StaticImpl AXES = [ dict(name='x', bounds=[-5, +5], points=25), dict(name='y', bounds=[-5, +5], points=25), dict(name='z', bounds=[-5, +5], points=25), ] impl = StaticImpl(AXES) print('Axes |', ', '.join([f'{impl.axis_name(i)}: {n}' for i, n in zip(range(impl.ndim), impl._shape)]))
Axes | x: 25, y: 25, z: 25

Warm-up: your first shape¶

Goal: run the full three-step workflow once before the detailed sections.

Takeaway: a SetBuilder is a description; S(impl) turns it into a boolean array on the grid that you can plot.

In [2]:
Copied!
# Step 1 - describe
S = AlignedBoxSet(x=(-2, 2), y=(-1, 1))

# Step 2 - realize
out = S(impl)

# Step 3 - visualize

print('Requires  |', ', '.join(S.__require__))
print('out.shape |', ', '.join([f'{s}: {n}' for s, n in zip(impl._axis_name, out.shape)]))

impl.plot(out, layout_title='AlignedBoxSet: x in [-2, 2], y in [-1, 1]')
# Step 1 - describe S = AlignedBoxSet(x=(-2, 2), y=(-1, 1)) # Step 2 - realize out = S(impl) # Step 3 - visualize print('Requires |', ', '.join(S.__require__)) print('out.shape |', ', '.join([f'{s}: {n}' for s, n in zip(impl._axis_name, out.shape)])) impl.plot(out, layout_title='AlignedBoxSet: x in [-2, 2], y in [-1, 1]')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
File ~/work/pyspect/pyspect/src/pyspect/set_builder.py:142, in AppliedSet.__call__(self, impl, **m)
    141 try:
--> 142     func = getattr(impl, self.func)
    143 except AttributeError as e:

AttributeError: 'StaticImpl' object has no attribute 'box'

The above exception was the direct cause of the following exception:

AttributeError                            Traceback (most recent call last)
Cell In[2], line 5
      1 # Step 1 - describe
      2 S = AlignedBoxSet(x=(-2, 2), y=(-1, 1))
      3 
      4 # Step 2 - realize
----> 5 out = S(impl)
      6 
      7 # Step 3 - visualize
      8 

File ~/work/pyspect/pyspect/src/pyspect/set_builder.py:144, in AppliedSet.__call__(self, impl, **m)
    142         func = getattr(impl, self.func)
    143     except AttributeError as e:
--> 144         raise AttributeError(f'Impl {impl.__class__.__name__} does not support "{self.func}".') from e
    146 args = []
    147 for i, arg in enumerate(self.args):

AttributeError: Impl StaticImpl does not support "box".

1. HalfSpaceSet - one half-plane¶

Goal: keep points on one side of a line (one linear inequality).

Parameters:

  • normal - vector pointing into the allowed region
  • offset - any point on the boundary line
  • axes - which coordinates are constrained (here x and y only)

Takeaway: one HalfSpaceSet = one wall / one linear constraint.

In [3]:
Copied!
# Example A - vertical wall: x >= 0
H = HalfSpaceSet(normal=[1, 0, 0], offset=[0, 0, 0], axes=['x', 'y', 'z'])
out = H(impl)
impl.plot(out, layout_title='HalfSpaceSet: x >= 0')
# Example A - vertical wall: x >= 0 H = HalfSpaceSet(normal=[1, 0, 0], offset=[0, 0, 0], axes=['x', 'y', 'z']) out = H(impl) impl.plot(out, layout_title='HalfSpaceSet: x >= 0')
In [4]:
Copied!
# Example B - oblique wall: x >= 2y  (normal [1, -2])
H = HalfSpaceSet(normal=[1, -2, 0], offset=[0, 0, 0], axes=['x', 'y', 'z'])
out = H(impl)
impl.plot(out, layout_title='HalfSpaceSet: x >= 2y')
# Example B - oblique wall: x >= 2y (normal [1, -2]) H = HalfSpaceSet(normal=[1, -2, 0], offset=[0, 0, 0], axes=['x', 'y', 'z']) out = H(impl) impl.plot(out, layout_title='HalfSpaceSet: x >= 2y')

2. AlignedBoxSet - axis-aligned box¶

Goal: describe a rectangle with simple bounds - the most common shape.

Takeaway: use AlignedBoxSet when bounds align with the grid axes. Internally it is built from half-spaces (see section 6).

In [5]:
Copied!
BOX = AlignedBoxSet(x=(-2, 2), y=(-1, 1))
out = BOX(impl)
impl.plot(out, layout_title='AlignedBoxSet: x in [-2, 2], y in [-1, 1]')
BOX = AlignedBoxSet(x=(-2, 2), y=(-1, 1)) out = BOX(impl) impl.plot(out, layout_title='AlignedBoxSet: x in [-2, 2], y in [-1, 1]')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
File ~/work/pyspect/pyspect/src/pyspect/set_builder.py:142, in AppliedSet.__call__(self, impl, **m)
    141 try:
--> 142     func = getattr(impl, self.func)
    143 except AttributeError as e:

AttributeError: 'StaticImpl' object has no attribute 'box'

The above exception was the direct cause of the following exception:

AttributeError                            Traceback (most recent call last)
Cell In[5], line 2
      1 BOX = AlignedBoxSet(x=(-2, 2), y=(-1, 1))
----> 2 out = BOX(impl)
      3 impl.plot(out, layout_title='AlignedBoxSet: x in [-2, 2], y in [-1, 1]')

File ~/work/pyspect/pyspect/src/pyspect/set_builder.py:144, in AppliedSet.__call__(self, impl, **m)
    142         func = getattr(impl, self.func)
    143     except AttributeError as e:
--> 144         raise AttributeError(f'Impl {impl.__class__.__name__} does not support "{self.func}".') from e
    146 args = []
    147 for i, arg in enumerate(self.args):

AttributeError: Impl StaticImpl does not support "box".

3. Combining shapes - Inter, Union, Compl¶

Goal: build richer regions from simple pieces.

Operator Meaning
Inter(A, B) inside both A and B
Union(A, B) inside either A or B
Compl(A) outside A

On TVHJImpl, Inter and Union take two builders at a time - nest them for three or more. The complement operator is named Compl (not Complement).

3a. Inter - trim a box (x <= 1)¶

Takeaway: intersection = keep only points that satisfy every constraint.

In [6]:
Copied!
base = AlignedBoxSet(x=(-3, 3), y=(-3, 3))
cut = HalfSpaceSet(normal=[-1, 0], offset=[1, 0], axes=['x', 'y'])  # x <= 1
out = Inter(base, cut)(impl)
impl.plot(out, layout_title='Inter(box, x <= 1)')
base = AlignedBoxSet(x=(-3, 3), y=(-3, 3)) cut = HalfSpaceSet(normal=[-1, 0], offset=[1, 0], axes=['x', 'y']) # x <= 1 out = Inter(base, cut)(impl) impl.plot(out, layout_title='Inter(box, x <= 1)')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
File ~/work/pyspect/pyspect/src/pyspect/set_builder.py:142, in AppliedSet.__call__(self, impl, **m)
    141 try:
--> 142     func = getattr(impl, self.func)
    143 except AttributeError as e:

AttributeError: 'StaticImpl' object has no attribute 'box'

The above exception was the direct cause of the following exception:

AttributeError                            Traceback (most recent call last)
File ~/work/pyspect/pyspect/src/pyspect/set_builder.py:150, in AppliedSet.__call__(self, impl, **m)
    149 try:
--> 150     args.append(arg(impl, **m))
    151 except Exception as e:

File ~/work/pyspect/pyspect/src/pyspect/set_builder.py:144, in AppliedSet.__call__(self, impl, **m)
    143     except AttributeError as e:
--> 144         raise AttributeError(f'Impl {impl.__class__.__name__} does not support "{self.func}".') from e
    146 args = []

AttributeError: Impl StaticImpl does not support "box".

The above exception was the direct cause of the following exception:

AttributeError                            Traceback (most recent call last)
Cell In[6], line 3
      1 base = AlignedBoxSet(x=(-3, 3), y=(-3, 3))
      2 cut = HalfSpaceSet(normal=[-1, 0], offset=[1, 0], axes=['x', 'y'])  # x <= 1
----> 3 out = Inter(base, cut)(impl)
      4 impl.plot(out, layout_title='Inter(box, x <= 1)')

File ~/work/pyspect/pyspect/src/pyspect/set_builder.py:153, in AppliedSet.__call__(self, impl, **m)
    151     except Exception as e:
    152         E = type(e)
--> 153         raise E(f'When applying "{self.func}" on argument {i}, received: {e!s}') from e
    154 else:
    155     args.append(arg)

AttributeError: When applying "intersect" on argument 0, received: Impl StaticImpl does not support "box".

3b. Union - two separate boxes¶

Takeaway: union = a point is allowed if it lies in either region.

In [7]:
Copied!
left = AlignedBoxSet(x=(-3, -1), y=(-2, 2))
right = AlignedBoxSet(x=(1, 3), y=(-2, 2))
out = Union(left, right)(impl)
impl.plot(out, layout_title='Union(left box, right box)')
left = AlignedBoxSet(x=(-3, -1), y=(-2, 2)) right = AlignedBoxSet(x=(1, 3), y=(-2, 2)) out = Union(left, right)(impl) impl.plot(out, layout_title='Union(left box, right box)')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
File ~/work/pyspect/pyspect/src/pyspect/set_builder.py:142, in AppliedSet.__call__(self, impl, **m)
    141 try:
--> 142     func = getattr(impl, self.func)
    143 except AttributeError as e:

AttributeError: 'StaticImpl' object has no attribute 'box'

The above exception was the direct cause of the following exception:

AttributeError                            Traceback (most recent call last)
File ~/work/pyspect/pyspect/src/pyspect/set_builder.py:150, in AppliedSet.__call__(self, impl, **m)
    149 try:
--> 150     args.append(arg(impl, **m))
    151 except Exception as e:

File ~/work/pyspect/pyspect/src/pyspect/set_builder.py:144, in AppliedSet.__call__(self, impl, **m)
    143     except AttributeError as e:
--> 144         raise AttributeError(f'Impl {impl.__class__.__name__} does not support "{self.func}".') from e
    146 args = []

AttributeError: Impl StaticImpl does not support "box".

The above exception was the direct cause of the following exception:

AttributeError                            Traceback (most recent call last)
Cell In[7], line 3
      1 left = AlignedBoxSet(x=(-3, -1), y=(-2, 2))
      2 right = AlignedBoxSet(x=(1, 3), y=(-2, 2))
----> 3 out = Union(left, right)(impl)
      4 impl.plot(out, layout_title='Union(left box, right box)')

File ~/work/pyspect/pyspect/src/pyspect/set_builder.py:153, in AppliedSet.__call__(self, impl, **m)
    151     except Exception as e:
    152         E = type(e)
--> 153         raise E(f'When applying "{self.func}" on argument {i}, received: {e!s}') from e
    154 else:
    155     args.append(arg)

AttributeError: When applying "union" on argument 0, received: Impl StaticImpl does not support "box".

3c. Compl - box with a hole¶

Takeaway: Compl removes an inner region; combine with Inter to cut holes.

In [8]:
Copied!
outer = AlignedBoxSet(x=(-3, 3), y=(-3, 3))
obstacle = AlignedBoxSet(x=(-1, 1), y=(-1, 1))
out = Inter(outer, Compl(obstacle))(impl)
impl.plot(out, layout_title='Inter(box, Compl(obstacle)): box with hole')
outer = AlignedBoxSet(x=(-3, 3), y=(-3, 3)) obstacle = AlignedBoxSet(x=(-1, 1), y=(-1, 1)) out = Inter(outer, Compl(obstacle))(impl) impl.plot(out, layout_title='Inter(box, Compl(obstacle)): box with hole')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
File ~/work/pyspect/pyspect/src/pyspect/set_builder.py:142, in AppliedSet.__call__(self, impl, **m)
    141 try:
--> 142     func = getattr(impl, self.func)
    143 except AttributeError as e:

AttributeError: 'StaticImpl' object has no attribute 'box'

The above exception was the direct cause of the following exception:

AttributeError                            Traceback (most recent call last)
File ~/work/pyspect/pyspect/src/pyspect/set_builder.py:150, in AppliedSet.__call__(self, impl, **m)
    149 try:
--> 150     args.append(arg(impl, **m))
    151 except Exception as e:

File ~/work/pyspect/pyspect/src/pyspect/set_builder.py:144, in AppliedSet.__call__(self, impl, **m)
    143     except AttributeError as e:
--> 144         raise AttributeError(f'Impl {impl.__class__.__name__} does not support "{self.func}".') from e
    146 args = []

AttributeError: Impl StaticImpl does not support "box".

The above exception was the direct cause of the following exception:

AttributeError                            Traceback (most recent call last)
Cell In[8], line 3
      1 outer = AlignedBoxSet(x=(-3, 3), y=(-3, 3))
      2 obstacle = AlignedBoxSet(x=(-1, 1), y=(-1, 1))
----> 3 out = Inter(outer, Compl(obstacle))(impl)
      4 impl.plot(out, layout_title='Inter(box, Compl(obstacle)): box with hole')

File ~/work/pyspect/pyspect/src/pyspect/set_builder.py:153, in AppliedSet.__call__(self, impl, **m)
    151     except Exception as e:
    152         E = type(e)
--> 153         raise E(f'When applying "{self.func}" on argument {i}, received: {e!s}') from e
    154 else:
    155     args.append(arg)

AttributeError: When applying "intersect" on argument 0, received: Impl StaticImpl does not support "box".

4. Slab - band between two parallel walls¶

Goal: model a corridor with fixed width along one direction.

A slab is an Inter of two opposing half-spaces. Here: -1 <= x <= 1.

Takeaway: two parallel HalfSpaceSet walls form an infinite strip / band.

In [9]:
Copied!
SLAB = Inter(
    HalfSpaceSet(normal=[1, 0, 0], offset=[-1, 0, 0], axes=['x', 'y', 'z']),
    HalfSpaceSet(normal=[-1, 0, 0], offset=[1, 0, 0], axes=['x', 'y', 'z']),
)
out = SLAB(impl)
impl.plot(out, layout_title='Slab: -1 <= x <= 1')
SLAB = Inter( HalfSpaceSet(normal=[1, 0, 0], offset=[-1, 0, 0], axes=['x', 'y', 'z']), HalfSpaceSet(normal=[-1, 0, 0], offset=[1, 0, 0], axes=['x', 'y', 'z']), ) out = SLAB(impl) impl.plot(out, layout_title='Slab: -1 <= x <= 1')

5. 2D plot - flat slice in (x, y)¶

Goal: view the shape in the plane instead of a 3D isosurface.

Takeaway: use method='bitmap' with axes=('x', 'y') for a top-down 2D view.

In [10]:
Copied!
out = AlignedBoxSet(x=(-2, 2), y=(-1, 1))(impl)
impl.plot(out, method='bitmap', axes=('x', 'y'), layout_title='AlignedBoxSet - 2D bitmap')
out = AlignedBoxSet(x=(-2, 2), y=(-1, 1))(impl) impl.plot(out, method='bitmap', axes=('x', 'y'), layout_title='AlignedBoxSet - 2D bitmap')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
File ~/work/pyspect/pyspect/src/pyspect/set_builder.py:142, in AppliedSet.__call__(self, impl, **m)
    141 try:
--> 142     func = getattr(impl, self.func)
    143 except AttributeError as e:

AttributeError: 'StaticImpl' object has no attribute 'box'

The above exception was the direct cause of the following exception:

AttributeError                            Traceback (most recent call last)
Cell In[10], line 1
----> 1 out = AlignedBoxSet(x=(-2, 2), y=(-1, 1))(impl)
      2 impl.plot(out, method='bitmap', axes=('x', 'y'), layout_title='AlignedBoxSet - 2D bitmap')

File ~/work/pyspect/pyspect/src/pyspect/set_builder.py:144, in AppliedSet.__call__(self, impl, **m)
    142         func = getattr(impl, self.func)
    143     except AttributeError as e:
--> 144         raise AttributeError(f'Impl {impl.__class__.__name__} does not support "{self.func}".') from e
    146 args = []
    147 for i, arg in enumerate(self.args):

AttributeError: Impl StaticImpl does not support "box".

6. Under the hood - AlignedBoxSet as four half-spaces¶

Goal: understand how AlignedBoxSet relates to HalfSpaceSet (optional section).

A box x in [-2, 2], y in [-2, 2] is exactly the Inter of four HalfSpaceSet walls. The numeric check below should print 0.0.

In [11]:
Copied!
box_aligned = AlignedBoxSet(x=(-2, 2), y=(-2, 2))(impl)

box_manual = Inter(
    HalfSpaceSet(normal=[1, 0], offset=[-2, 0], axes=['x', 'y']),
    Inter(
        HalfSpaceSet(normal=[-1, 0], offset=[2, 0], axes=['x', 'y']),
        Inter(
            HalfSpaceSet(normal=[0, 1], offset=[0, -2], axes=['x', 'y']),
            HalfSpaceSet(normal=[0, -1], offset=[0, 2], axes=['x', 'y']),
        ),
    ),
)(impl)

diff = float(np.max(np.abs(box_aligned - box_manual)))
print(f'max |AlignedBoxSet - Inter(4 HalfSpaceSet)| = {diff:.6f}')
assert diff == 0.0, 'Expected exact match'
print('OK - AlignedBoxSet is built from half-spaces internally.')
box_aligned = AlignedBoxSet(x=(-2, 2), y=(-2, 2))(impl) box_manual = Inter( HalfSpaceSet(normal=[1, 0], offset=[-2, 0], axes=['x', 'y']), Inter( HalfSpaceSet(normal=[-1, 0], offset=[2, 0], axes=['x', 'y']), Inter( HalfSpaceSet(normal=[0, 1], offset=[0, -2], axes=['x', 'y']), HalfSpaceSet(normal=[0, -1], offset=[0, 2], axes=['x', 'y']), ), ), )(impl) diff = float(np.max(np.abs(box_aligned - box_manual))) print(f'max |AlignedBoxSet - Inter(4 HalfSpaceSet)| = {diff:.6f}') assert diff == 0.0, 'Expected exact match' print('OK - AlignedBoxSet is built from half-spaces internally.')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
File ~/work/pyspect/pyspect/src/pyspect/set_builder.py:142, in AppliedSet.__call__(self, impl, **m)
    141 try:
--> 142     func = getattr(impl, self.func)
    143 except AttributeError as e:

AttributeError: 'StaticImpl' object has no attribute 'box'

The above exception was the direct cause of the following exception:

AttributeError                            Traceback (most recent call last)
Cell In[11], line 1
----> 1 box_aligned = AlignedBoxSet(x=(-2, 2), y=(-2, 2))(impl)
      2 
      3 box_manual = Inter(
      4     HalfSpaceSet(normal=[1, 0], offset=[-2, 0], axes=['x', 'y']),

File ~/work/pyspect/pyspect/src/pyspect/set_builder.py:144, in AppliedSet.__call__(self, impl, **m)
    142         func = getattr(impl, self.func)
    143     except AttributeError as e:
--> 144         raise AttributeError(f'Impl {impl.__class__.__name__} does not support "{self.func}".') from e
    146 args = []
    147 for i, arg in enumerate(self.args):

AttributeError: Impl StaticImpl does not support "box".
Getting Started Examples for CDC '25
Menu
Home
Tutorials
Getting Started Creating Sets
Paper Examples
Examples for CDC '25
Implementations
hj_reachability ZonoOpt
Helper Implementations
Base Axes Plotly Debug
Reference
Set Builders Logic Fragments Temporal Logic Trees TLT Primitives

On This Page

What you will learn Workflow (every example) Setup Warm-up: your first shape 1. HalfSpaceSet - one half-plane 2. AlignedBoxSet - axis-aligned box 3. Combining shapes - , , 3a. Inter - trim a box (x <= 1) 3b. Union - two separate boxes 3c. Compl - box with a hole 4. Slab - band between two parallel walls 5. 2D plot - flat slice in (x, y) 6. Under the hood - AlignedBoxSet as four half-spaces
Built by Kaj Munhoz Arfvidsson — shadcn theme provided by @asiffer