diff options
Diffstat (limited to 'vicn/core/scheduling_algebra.py')
-rw-r--r-- | vicn/core/scheduling_algebra.py | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/vicn/core/scheduling_algebra.py b/vicn/core/scheduling_algebra.py new file mode 100644 index 00000000..207856c0 --- /dev/null +++ b/vicn/core/scheduling_algebra.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2017 Cisco and/or its affiliates. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +def SchedulingAlgebra(cls, concurrent_mixin=object, composition_mixin=object, + sequential_mixin=object): # allow_none = True + + class BaseElement(cls): + def __default__(cls, *elements): + elts = [e for e in elements + if e is not None and not isinstance(e, Empty)] + if len(elts) == 0: + # The first is always Empty + assert len(elements) != 0 + return elements[0] + elif len(elts) == 1: + return elts[0] + return cls(*elts) + + def __concurrent__(*elements): + return BaseElement.__default__(Concurrent, *elements) + + def __composition__(*elements): + return BaseElement.__default__(Composition, *elements) + + def __sequential__(*elements): + return BaseElement.__default__(Sequential, *elements) + + # Operator: | + __or__ = __concurrent__ + + # Operator: > + __gt__ = __sequential__ + + # Operator: @ + __matmul__ = __composition__ + + class Element(BaseElement): + def __iter__(self): + yield self + + class Operator(BaseElement): + def __init__(self, *elements): + super().__init__() + self._elements = list(elements) + + def __iter__(self): + yield self + for element in self._elements: + for x in element: + yield x + + class Concurrent(Operator, concurrent_mixin): + # Algebraic rule : ((A // B) // C) ~ (A // B // C) + def __concurrent__(self, other): + self._elements.append(other) + return self + + def __repr__(self): + return '<Concurrent {}>'.format(self._elements) + + class Composition(Operator, composition_mixin): + def __repr__(self): + return '<Composition {}>'.format(self._elements) + + class Sequential(Operator, sequential_mixin): + def __repr__(self): + return '<Sequential {}>'.format(self._elements) + + class Empty(Element): + def __concurrent__(self, other): + return other + + def __composition__(self, other): + return other + + def __sequential__(self, other): + return other + + def __repr__(self): + return '<Empty>' + + return Element, Empty |