compas_fab icon indicating copy to clipboard operation
compas_fab copied to clipboard

Add partial order plan datastructure

Open gonzalocasas opened this issue 3 years ago • 3 comments

Create a partial order plan data structure that is compatible with RRC execution, and flexible enough to represent generic fabrication processes as a directed acyclic graph (ie tasks connected by their dependencies). This data structure could be used both for task generation and assembly sequencing.

gonzalocasas avatar Sep 14 '20 08:09 gonzalocasas

Prototype available in https://github.com/dbt-ethz/A032-CE3DP/blob/master/CE3DP%20slicer/cSlicer/partial_order_plan.py

gonzalocasas avatar Mar 02 '21 09:03 gonzalocasas

where'd the prototype run off to?

beverlylytle avatar Mar 09 '21 07:03 beverlylytle

Ouh sorry, I totally missed your previous comment in a sea of notification emails. Looks like the link is private, here's a code snippet of the class:

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


class ProductionData(object):
    def __init__(self, actions=[]):
        self.actions = {action.id: action for action in actions}

    def append_action(self, namespace, action, action_id=None, dependency_ids=None):
        action_id = self.get_next_action_id() or action_id
        dependency_ids = [action_id - 1] if dependency_ids is None else dependency_ids
        partial_order_action = PartialOrderAction(action_id, namespace, action, dependency_ids)
        self.actions[action_id] = partial_order_action
    
    def get_next_action_id(self):
        if len(self.actions) == 0:
            return 1
        return sorted(self.actions.keys())[-1] + 1

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

    @property
    def data(self):
        return dict(
            actions=[p.to_data() for p in self.actions.values()]
        )
    
    @classmethod
    def from_data(cls, data):
        return cls([PartialOrderAction.from_data(d) for d in data['actions']])
    
    def to_data(self):
        return self.data

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

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

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

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

    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  

gonzalocasas avatar Mar 29 '21 12:03 gonzalocasas