Skip to content

Commit fdec634

Browse files
committed
fix workflow, examples
1 parent 73d2425 commit fdec634

8 files changed

Lines changed: 44 additions & 16 deletions

File tree

.github/workflows/bump.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323

2424
- uses: actions/setup-python@v5
2525
with:
26-
python-version: '3.11'
26+
python-version: '3.12'
2727

2828
- name: install bump-my-version
2929
run: |

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050

5151
- uses: actions/setup-python@v5
5252
with:
53-
python-version: '3.11'
53+
python-version: '3.12'
5454

5555
- name: install uv
5656
uses: astral-sh/setup-uv@v3

.github/workflows/test-build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ jobs:
2323
args: "--version"
2424

2525
- name: lint code
26-
run: ruff check --output-format=github --target-version=py311
26+
run: ruff check --output-format=github --target-version=py312
2727

2828
- name: check code formatting
29-
run: ruff format --diff --target-version=py311
29+
run: ruff format --diff --target-version=py312
3030
continue-on-error: true # Remove this once the project is formatted
3131

3232
- name: install uv

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ pip install umbi
1515

1616
## Quick start
1717

18-
A short example where we read a umbfile into an [`ExplicitAts`](umbi/ats/explicit_ats.py) object, modify initial states, and write it back:
18+
A short example where we read a umbfile into an [`SimpleAts`](umbi/ats/explicit_ats.py) object, modify initial states, and write it back:
1919

2020
```python
2121
import umbi
2222
ats = umbi.ats.read("in.umb")
23-
ats.set_initial_states([ats.num_states - 1])
23+
ats.initial_states = [ats.num_states - 1]
2424
umbi.ats.write(ats, "out.umb")
2525
```
2626

@@ -34,15 +34,15 @@ More examples can be found in the [examples](./examples) folder.
3434

3535
**[`ExplicitUmb`](umbi/umb/explicit_umb.py)** - in-memory representation of a typical umbfile. Attributes are standard Python objects (lists, dicts, dataclasses) providing a deserialized view of the file contents.
3636

37-
**[`ExplicitAts`](umbi/ats/explicit_ats.py)** - format-agnostic abstraction for annotated transition systems (states, transitions, annotations). Recommended for most use cases: easiest to use programmatically and remains stable across UMB format changes. See [umbi.ats.examples](./umbi/ats/examples/) for usage examples.
37+
**[`SimpleAts`](umbi/ats/simple_ats.py)** - format-agnostic abstraction for annotated transition systems (states, transitions, annotations, etc.). Recommended for most use cases: easiest to use programmatically and remains stable across UMB format changes. See [umbi.ats.examples](./umbi/ats/examples/) for usage examples.
3838

3939
## CLI
4040

4141
`umbi` provides a basic CLI for umbfile manipulation.
4242

4343
**Options:**
4444
- `--import-umb <path>` - import umbfile as `ExplicitUmb`
45-
- `--import-ats <path>` - import umbfile as `ExplicitAts`
45+
- `--import-ats <path>` - import umbfile as `SimpleAts`
4646
- `--export <path>` - export to umbfile (requires `--import-umb` or `--import-ats`)
4747
- `--log-level <LEVEL>` - set logging level: `DEBUG`, `INFO` (default), `WARNING`, `ERROR`, `CRITICAL`
4848

examples/demo/ats.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/env python3
2-
"""Demonstration of umbfile manipulation via ExplicitAts."""
2+
"""Demonstration of umbfile manipulation via SimpleAts."""
33

44
import pathlib
55

@@ -31,11 +31,11 @@ def main(input: pathlib.Path, output: pathlib.Path):
3131

3232
print("Adding custom rewards...")
3333
annotation_name = "state_index"
34-
reward_annotation = ats.add_reward_annotation(
34+
reward_annotation = ats.new_reward_annotation(
3535
name=annotation_name,
3636
description="Reward annotation for states, equal to the state index",
3737
)
38-
reward_annotation.set_state_values(list(ats.states))
38+
reward_annotation.state_values = list(ats.states)
3939

4040
print(f"Writing modified ATS to {output}...")
4141
umbi.ats.write(ats, output)

examples/misc/ats_smg_to_prism.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import pathlib
99

1010
import umbi
11+
import umbi.ats
1112

1213
log = logging.getLogger(__name__)
1314

examples/misc/value_iteration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212

1313
def reachability_vi(
14-
model: umbi.ats.ExplicitAts,
14+
model: umbi.ats.SimpleAts,
1515
goal_states: set[int],
1616
maximizing_players: set[int],
1717
stopping_criterion=1e-6,

umbi/ats/choices_mixin.py

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import logging
2-
from collections.abc import Sequence
2+
from collections.abc import Callable, Iterable, Sequence
33
from dataclasses import dataclass, field
44

55
from umbi.datatypes import Numeric, is_numeric_a_probability
66

7-
from .base_mixin import BaseMixin, CompositeMixin
87
from .entity_space import EntityMapping
98
from .entity_space_mixins import HasBranchSpace, HasChoiceSpace, HasStateSpace
109

@@ -155,12 +154,24 @@ def validate(self) -> None:
155154
# TODO check that probabilities sum to 1
156155
super().validate()
157156

158-
def new_state_choice(self, state: int) -> int:
159-
"""Add a choice to the given state."""
157+
def new_state_choice(
158+
self,
159+
state: int,
160+
targets: Iterable[int] | None = None,
161+
target_prob: Callable[[int], Numeric | None] | None = None,
162+
) -> int:
163+
"""Add a choice to the given state.
164+
:param state: source state for the new choice
165+
:param targets: optional iterable of target states for the branches of the new choice
166+
:param target_prob: optional function mapping target states to branch probabilities
167+
:return: the new choice index
168+
"""
160169
# self.state_space._check_entity(state)
161170
choice = self._new_choice()
162171
self.state_to_choices[state].append(choice)
163172
self._choice_to_state[choice] = state
173+
if targets is not None and target_prob is not None:
174+
self.new_choice_branches(choice, targets=targets, target_prob=target_prob)
164175
return choice
165176

166177
def remove_choice(self, choice: int) -> list[int]:
@@ -196,6 +207,22 @@ def new_choice_branch(self, choice: int, target: int | None = None, prob: Numeri
196207
self._branch_to_probability[new_branch] = prob
197208
return new_branch
198209

210+
def new_choice_branches(
211+
self, choice: int, targets: Iterable[int], target_prob: Callable[[int], Numeric | None]
212+
) -> list[int]:
213+
"""Add branches to the given choice for multiple targets.
214+
:param choice: choice to add branches to
215+
:param targets: target states for the new branches
216+
:param target_prob: function mapping target states to branch probabilities
217+
:return: list of new branches added
218+
"""
219+
new_branches = []
220+
for target in targets:
221+
prob = target_prob(target)
222+
branch = self.new_choice_branch(choice, target=target, prob=prob)
223+
new_branches.append(branch)
224+
return new_branches
225+
199226
def remove_branch(self, branch: int) -> None:
200227
self._branch_space.check_entity(branch)
201228
choice = self._branch_to_choice[branch]

0 commit comments

Comments
 (0)