Skip to content

Introducing PartialOrder #288

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 33 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
0aca75d
introducing Plan
beverlylytle Apr 1, 2021
da4fe74
lint
beverlylytle Apr 1, 2021
b7d8835
docstrings, inherit from compas.base.Base, safety checks
beverlylytle Apr 6, 2021
1c92c81
add tests, and some fixes
beverlylytle Apr 8, 2021
031e3a9
more tests
beverlylytle Apr 8, 2021
87c1a67
Update src/compas_fab/datastructures/plan.py
beverlylytle Apr 8, 2021
6824321
Update src/compas_fab/datastructures/plan.py
beverlylytle Apr 8, 2021
ed26c84
Update src/compas_fab/datastructures/plan.py
beverlylytle Apr 8, 2021
b79cb47
add alias for ironpython
beverlylytle Apr 8, 2021
f44387f
more ipy aliases
beverlylytle Apr 8, 2021
e00f63c
Update CHANGELOG.rst
beverlylytle Apr 12, 2021
e5a685a
Use compas.json_<load/dump>
beverlylytle Apr 12, 2021
164a68d
Inherit from Base rather than Datastructure
beverlylytle Apr 12, 2021
a88c502
remove extraneous from_data
beverlylytle Apr 12, 2021
ccbca4b
Add module level docstring
beverlylytle Apr 12, 2021
55ee2e8
Merge branch 'main' into dag
gonzalocasas Apr 12, 2021
2adbd02
Merge branch 'dag' of https://github.com/compas-dev/compas_fab into dag
beverlylytle Apr 12, 2021
d89ee63
use compas.datastructures.Graph
beverlylytle Apr 15, 2021
93f3952
locally import networkx to make ipy happy
beverlylytle Apr 15, 2021
9651875
fix changelog
beverlylytle Apr 15, 2021
f05da6f
extend test
beverlylytle Apr 15, 2021
8c8d637
better test
beverlylytle Apr 16, 2021
d4941f5
update to newest compas version
beverlylytle Apr 20, 2021
744ccba
Merge branch 'main' into dag
beverlylytle May 25, 2021
4fcb952
Rename Plan to PartialOrder
beverlylytle May 25, 2021
829926c
Rename more stuff
beverlylytle May 25, 2021
ab10364
Change test to make ironpython happy
beverlylytle May 26, 2021
23ae475
Add wikipedia link
beverlylytle May 26, 2021
07268fd
Added first draft of accept methods
beverlylytle May 26, 2021
a5341ad
Yeah, I remember how my code works
beverlylytle May 26, 2021
d28fb49
Update src/compas_fab/datastructures/partial_order.py
beverlylytle May 26, 2021
31b963a
Merge branch 'main' into dag
beverlylytle May 27, 2021
a9e96ab
Merge branch 'dag' of https://github.com/compas-dev/compas_fab into dag
beverlylytle May 27, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Unreleased
**Added**

* Added support for MoveIt on ROS Noetic
* In`compas.datastructures`, added `Plan`, `PlannedAction`, `Action` and `IntegerIdGenerator`

**Changed**

Expand Down
14 changes: 14 additions & 0 deletions src/compas_fab/datastructures/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from .plan import (
Action,
IntegerIdGenerator,
Plan,
PlannedAction
)


__all__ = [
'Action',
'IntegerIdGenerator',
'Plan',
'PlannedAction',
]
130 changes: 130 additions & 0 deletions src/compas_fab/datastructures/plan.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from collections import OrderedDict
from itertools import count

from compas.utilities import DataEncoder
from compas.utilities import DataDecoder


__all__ = [
'Action',
'IntegerIdGenerator',
'Plan',
'PlannedAction',
]


class IntegerIdGenerator(object):
Copy link
Member

@gonzalocasas gonzalocasas Apr 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to make this thread-safe, like the SequenceCounter in rrc?
EDIT: https://github.com/compas-rrc/compas_rrc/blob/main/src/compas_rrc/client.py#L25

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this new version better?

def __init__(self, start_value=1):
self._generator = count(start_value)

def __next__(self):
yield next(self._generator)


class Plan(object):
def __init__(self, planned_actions=None, id_generator=None):
self.planned_actions = OrderedDict({pa.id: pa for pa in planned_actions})
if id_generator is None:
start_value = max(self.planned_actions.keys()) + 1 if self.planned_actions else 1
id_generator = IntegerIdGenerator(start_value)
self._id_generator = id_generator

def plan_action(self, action, dependency_ids, namespace=None):
action_id = self._get_next_action_id()
planned_action = PlannedAction(action_id, action, dependency_ids, namespace)
self.planned_actions[action_id] = planned_action
return action_id

def append_action(self, action, namespace=None):
dependency_ids = set()
if self.planned_actions:
last_action_id = self._get_last_action_id()
dependency_ids = {last_action_id}
return self.plan_action(action, dependency_ids, namespace)

def remove_action_by_id(self, action_id):
planned_action = self.planned_actions.pop(action_id)
for pa in self.planned_actions.values():
pa.dependency_ids.discard(action_id)
return planned_action.action

def _get_last_action_id(self):
last_action_id, last_action = self.planned_actions.popitem()
self.planned_actions[last_action_id] = last_action
return last_action_id

def _get_next_action_id(self):
return next(self._id_generator)

def get_namespaces(self):
return set(a.namespace for a in self.planned_actions.values())

@property
def data(self):
return dict(
planned_actions=[p.to_data() for p in self.planned_actions.values()]
)

@classmethod
def from_data(cls, data):
return cls([PlannedAction.from_data(d) for d in data['planned_actions']])

def to_data(self):
return self.data


class PlannedAction(object):
def __init__(self, action_id, action, dependency_ids, namespace=None):
self.id = action_id
self.action = action
self.dependency_ids = set(dependency_ids)
self.namespace = namespace

def __str__(self):
return 'PlannedAction<id={}, action={}, namespace={}>'.format(self.id, self.action, self.namespace)

@property
def data(self):
return dict(
id=self.id,
action=self.action.to_data(),
dependency_ids=self.dependency_ids,
namespace=self.namespace,
)

@classmethod
def from_data(cls, data):
return cls(data['id'], Action.from_data(data['action']), data['dependency_ids'], data['namespace'])

def to_data(self):
return self.data


class Action(object):
def __init__(self, name, parameters=None):
self.name = name
self.parameters = parameters or {}

def __str__(self):
return 'Action<name={}>'.format(self.name)

@property
def data(self):
return dict(
name=self.name,
parameters={param_key: DataEncoder().default(p) if hasattr(p, 'to_data') else p for param_key, p in
self.parameters.items()},
)

@classmethod
def from_data(cls, data):
return cls(data['name'],
{param_key: DataDecoder().object_hook(p) if hasattr(p, '__iter__') else p for param_key, p in
data['parameters'].items()})

def to_data(self):
return self.data