示例#1
0
    def parse2(self):
        self.op_stack = Stack()
        self.val_stack = Stack()
        self.node_stack = Stack()

        self.op_stack.push('$')
        self.val_stack.push('$')
        try:
            ret = self.parse_token_list_rec(self.op_priority['$'])
        except Exception as e:
            raise e
    
        return ret
示例#2
0
    def __init__(self, id_, component, parent=None):
        Reflective.__init__(self)

        self.uid = Runnable.uid_count
        Runnable.uid_count += 1

        self.id = id_
        self.component = component
        self.parent = parent

        self.time_step = 0
        self.time_completed = 0
        self.time_total = 0

        self.plastic = True

        self.state_stack = Stack()

        self.children = {}
        self.uchildren = {}
        self.groups = []

        self.recorded_variables = []

        self.event_out_ports = []
        self.event_in_ports = []

        self.event_out_callbacks = {}
        self.event_in_counters = {}

        self.attachments = {}

        self.new_regime = ''
        self.current_regime = ''
        self.last_regime = ''
        self.regimes = {}
示例#3
0
    def __init__(self, id_, component, parent = None):
        Reflective.__init__(self)

        self.uid = Runnable.uid_count
        Runnable.uid_count += 1

        self.id = id_
        self.component = component
        self.parent = parent

        self.time_step = 0
        self.time_completed = 0
        self.time_total = 0

        self.plastic = True

        self.state_stack = Stack()

        self.children = {}
        self.uchildren = {}
        self.groups = []

        self.recorded_variables = []

        self.event_out_ports = []
        self.event_in_ports = []

        self.event_out_callbacks = {}
        self.event_in_counters = {}

        self.attachments = {}

        self.new_regime = ''
        self.current_regime = ''
        self.last_regime = ''
        self.regimes = {}
示例#4
0
class ExprParser(LEMSBase):
    """
    Parser class for parsing an expression and generating a parse tree.
    """
    
    debug = False

    op_priority = {
        '$':-5,
        'func':8,
        '+':5,
        '-':5,
        '*':6,
        '/':6,
        '^':7,
        '~':8,
        'exp':8,
        '.and.':1,
        '.or.':1,
        '.gt.':2,
        '.ge.':2,
        '.geq.':2,
        '.lt.':2,
        '.le.':2,
        '.eq.':2,
        '.neq.':2,
        '.ne.':2}  # .neq. is preferred!

    depth = 0

    """ Dictionary mapping operators to their priorities.
    @type: dict(string -> Integer) """

    def __init__(self, parse_string):
        """
        Constructor.

        @param parse_string: Expression to be parsed.
        @type parse_string: string
        """

        self.parse_string = parse_string
        """ Expression to be parsed.
        @type: string """

        self.token_list = None
        """ List of tokens from the expression to be parsed.
        @type: list(string) """

    def is_op(self, str):
        """
        Checks if a token string contains an operator.

        @param str: Token string to be checked.
        @type str: string

        @return: True if the token string contains an operator.
        @rtype: Boolean
        """

        return str in self.op_priority

    def is_func(self, str):
        """
        Checks if a token string contains a function.

        @param str: Token string to be checked.
        @type str: string

        @return: True if the token string contains a function.
        @rtype: Boolean
        """

        return str in known_functions

    def is_sym(self, str):
        """
        Checks if a token string contains a symbol.

        @param str: Token string to be checked.
        @type str: string

        @return: True if the token string contains a symbol.
        @rtype: Boolean
        """

        return str in ['+', '-', '~', '*', '/', '^', '(', ')']

    def priority(self, op):
        if self.is_op(op):
            return self.op_priority[op]
        elif self.is_func(op):
            return self.op_priority['func']
        else:
            return self.op_priority['$']

    def tokenize(self):
        """
        Tokenizes the string stored in the parser object into a list
        of tokens.
        """

        self.token_list = []
        ps = self.parse_string.strip()

        i = 0
        last_token = None

        while i < len(ps) and ps[i].isspace():
            i += 1

        while i < len(ps):
            token = ''

            if ps[i].isalpha():
                while i < len(ps) and (ps[i].isalnum() or ps[i] == '_'):
                    token += ps[i]
                    i += 1
            elif ps[i].isdigit():
                while i < len(ps) and (ps[i].isdigit() or
                                       ps[i] == '.' or
                                       ps[i] == 'e' or
                                       ps[i] == 'E' or
                                       (ps[i] == '+' and (ps[i-1] == 'e' or ps[i-1] == 'E')) or
                                       (ps[i] == '-' and (ps[i-1] == 'e' or ps[i-1] == 'E'))):
                    token += ps[i]
                    i += 1
            elif ps[i] == '.':
                if ps[i+1].isdigit():
                    while i < len(ps) and (ps[i].isdigit() or ps[i] == '.'):
                        token += ps[i]
                        i += 1
                else:
                    while i < len(ps) and (ps[i].isalpha() or ps[i] == '.'):
                        token += ps[i]
                        i += 1
            else:
                token += ps[i]
                i += 1

            if token == '-' and \
               (last_token == None or last_token == '(' or self.is_op(last_token)):
                token = '~'

            self.token_list += [token]
            last_token = token

            while i < len(ps) and ps[i].isspace():
                i += 1
                
    def make_op_node(self, op, right):
        if self.is_func(op):
            return Func1Node(op, right)
        elif op == '~':
            return OpNode('-', ValueNode('0'), right)
        else:
            left = self.val_stack.pop()
            if left == '$':
                left = self.node_stack.pop()
            else:
                left = ValueNode(left)

            return OpNode(op, left, right)

    def cleanup_stacks(self):
        right = self.val_stack.pop()
        if right == '$':
            right = self.node_stack.pop()
        else:
            right = ValueNode(right)
            
        if self.debug: print('- Cleanup > right: %s'% right)
        
        while self.op_stack.top() != '$':
            if self.debug: print('5> op stack: %s, val stack: %s, node stack: %s'% ( self.op_stack, self.val_stack, self.node_stack))
            op = self.op_stack.pop()

            right = self.make_op_node(op, right)

            if self.debug: print('6> op stack: %s, val stack: %s, node stack: %s'% ( self.op_stack, self.val_stack, self.node_stack))
            if self.debug: print('7> %s'% right)
            #if self.debug: print(''

        return right

    def parse_token_list_rec(self, min_precedence):
        """
        Parses a tokenized arithmetic expression into a parse tree. It calls
        itself recursively to handle bracketed subexpressions.

        @return: Returns a token string.
        @rtype: lems.parser.expr.ExprNode

        @attention: Does not handle unary minuses at the moment. Needs to be
        fixed.
        """

        exit_loop = False

        ExprParser.depth = ExprParser.depth + 1
        if self.debug: print('>>>>> Depth: %i'% ExprParser.depth)

        precedence = min_precedence

        while self.token_list:
            token = self.token_list[0]
            la = self.token_list[1] if len(self.token_list) > 1 else None

            if self.debug: print('0> %s'% self.token_list)
            if self.debug: print('1> Token: %s, next: %s, op stack: %s, val stack: %s, node stack: %s'% (token, la, self.op_stack, self.val_stack, self.node_stack))

            self.token_list = self.token_list[1:]
            
            close_bracket = False
            
            if token == '(':
                np = ExprParser('')
                np.token_list = self.token_list

                nexp = np.parse2()

                self.node_stack.push(nexp)
                self.val_stack.push('$')

                self.token_list = np.token_list
                if self.debug: print('>>> Tokens left: %s'%self.token_list)
                close_bracket = True
            elif token == ')':
                break
            elif self.is_func(token):
                self.op_stack.push(token)
            elif self.is_op(token):
                stack_top = self.op_stack.top()
                if self.debug: print('OP Token: %s (prior: %i), top: %s (prior: %i)'% (token, self.priority(token), stack_top, self.priority(stack_top)))
                if self.priority(token) < self.priority(stack_top):
                    if self.debug: print('  Priority of %s is less than %s'%(token, stack_top))
                    self.node_stack.push(self.cleanup_stacks())
                    self.val_stack.push('$')
                else:
                    if self.debug: print('  Priority of %s is greater than %s'%(token, stack_top))
                

                self.op_stack.push(token)
            else:
                if self.debug: print('Not a bracket func or op...')
                if la == '(':
                    raise Exception("Error parsing expression: %s\nToken: %s is placed like a function but is not recognised!\nKnown functions: %s"%(self.parse_string, token, known_functions))
                stack_top = self.op_stack.top()
                if stack_top == '$':
                    if self.debug: print("option a")
                    self.node_stack.push(ValueNode(token))
                    self.val_stack.push('$')
                else:
                    if (self.is_op(la) and
                        self.priority(stack_top) < self.priority(la)):
                        if self.debug: print("option b")

                        self.node_stack.push(ValueNode(token))
                        self.val_stack.push('$')
                    else:
                        if self.debug: print("option c, nodes: %s"% self.node_stack)
                        op = self.op_stack.pop()

                        right = ValueNode(token)
                        op_node = self.make_op_node(op,right)

                        self.node_stack.push(op_node)
                        self.val_stack.push('$')
                        
            if close_bracket:
                stack_top = self.op_stack.top()
                if self.debug: print("+ Closing bracket, op stack: %s, node stack: %s la: %s"%(self.op_stack, self.node_stack, la))
                if self.debug: print('>>> Tokens left: %s'%self.token_list)
                
                if stack_top == '$':
                    if self.debug: print("+ option a")
                    '''
                    self.node_stack.push(ValueNode(token))
                    self.val_stack.push('$')'''
                else:
                    la = self.token_list[0] if len(self.token_list) > 1 else None
                    if (self.is_op(la) and self.priority(stack_top) < self.priority(la)):
                        if self.debug: print("+ option b")
                        #self.node_stack.push(ValueNode(token))
                        #self.val_stack.push('$')
                    else:
                        if self.debug: print("+ option c, nodes: %s"% self.node_stack)
                        if self.debug: print('35> op stack: %s, val stack: %s, node stack: %s'% ( self.op_stack, self.val_stack, self.node_stack))
                        right = self.node_stack.pop()
                        op = self.op_stack.pop()
                        op_node = self.make_op_node(stack_top,right)
                        if self.debug: print("Made op node: %s, right: %s"%(op_node, right))

                        self.node_stack.push(op_node)
                        self.val_stack.push('$')
                        if self.debug: print('36> op stack: %s, val stack: %s, node stack: %s'% ( self.op_stack, self.val_stack, self.node_stack))
                        
            

            if self.debug: print('2> Token: %s, next: %s, op stack: %s, val stack: %s, node stack: %s'% (token, la, self.op_stack, self.val_stack, self.node_stack))
            if self.debug: print('')

        if self.debug: print('3> op stack: %s, val stack: %s, node stack: %s'% ( self.op_stack, self.val_stack, self.node_stack))
        ret = self.cleanup_stacks()

        if self.debug: print('4> op stack: %s, val stack: %s, node stack: %s'% ( self.op_stack, self.val_stack, self.node_stack))
        if self.debug: print('<<<<< Depth: %s, returning: %s'% (ExprParser.depth, ret))
        ExprParser.depth = ExprParser.depth - 1
        if self.debug: print('')
        return ret

    def parse(self):
        """
        Tokenizes and parses an arithmetic expression into a parse tree.

        @return: Returns a token string.
        @rtype: lems.parser.expr.ExprNode
        """
        #print("Parsing: %s"%self.parse_string)
        self.tokenize()
        if self.debug: print("Tokens found: %s"%self.token_list)
        
        try:
            parse_tree = self.parse2()
        except Exception as e:
                raise e
        return parse_tree

    def parse2(self):
        self.op_stack = Stack()
        self.val_stack = Stack()
        self.node_stack = Stack()

        self.op_stack.push('$')
        self.val_stack.push('$')
        try:
            ret = self.parse_token_list_rec(self.op_priority['$'])
        except Exception as e:
            raise e
    
        return ret

    def __str__(self):
        return str(self.token_list)
示例#5
0
    def copy(self):
        """
        Make a copy of this runnable.

        @return: Copy of this runnable.
        @rtype: lems.sim.runnable.Runnable
        """
        if self.debug: print("Coping....." + self.id)
        r = Runnable(self.id, self.component, self.parent)
        copies = dict()

        # Copy simulation time parameters
        r.time_step = self.time_step
        r.time_completed = self.time_completed
        r.time_total = self.time_total

        # Plasticity and state stack (?)
        r.plastic = self.plastic
        r.state_stack = Stack()

        # Copy variables (GG - Faster using the add_* methods?)
        for v in self.instance_variables:
            r.instance_variables.append(v)
            r.__dict__[v] = self.__dict__[v]
            r.__dict__[v + '_shadow'] = self.__dict__[v + '_shadow']

        for v in self.derived_variables:
            r.derived_variables.append(v)
            r.__dict__[v] = self.__dict__[v]
            r.__dict__[v + '_shadow'] = self.__dict__[v + '_shadow']

        # Copy array elements
        for child in self.array:
            child_copy = child.copy()
            child_copy.parent = r
            r.array.append(child_copy)
            copies[child.uid] = child_copy

        # Copy attachment def
        for att in self.attachments:
            atn = self.attachments[att]
            r.attachments[att] = atn
            r.__dict__[atn] = []

        # Copy children
        for uid in self.uchildren:
            child = self.uchildren[uid]
            child_copy = child.copy()
            child_copy.parent = r
            copies[child.uid] = child_copy

            r.add_child(child_copy.id, child_copy)

            # For typerefs
            try:
                idx = [k for k in self.__dict__
                       if self.__dict__[k] == child][0]
                r.__dict__[idx] = child_copy
            except:
                pass

            # For groups and attachments:
            try:
                idx = [k for k in self.__dict__
                       if child in self.__dict__[k]][0]
                if idx not in r.__dict__:
                    r.__dict__[idx] = []
                r.__dict__[idx].append(child_copy)

            except:
                pass

        # Copy event ports
        for port in self.event_in_ports:
            r.event_in_ports.append(port)
            r.event_in_counters[port] = 0

        for port in self.event_out_ports:
            r.event_out_ports.append(port)
            r.event_out_callbacks[port] = self.event_out_callbacks[port]

        for ec in r.component.structure.event_connections:
            if self.debug:
                print("--- Fixing event_connection: %s in %s" %
                      (ec.toxml(), id(r)))

            source = r.parent.resolve_path(ec.from_)
            target = r.parent.resolve_path(ec.to)

            if ec.receiver:
                # Will throw error...
                receiver_template = self.build_runnable(ec.receiver, target)
                #receiver = copy.deepcopy(receiver_template)
                receiver = receiver_template.copy()
                receiver.id = "{0}__{1}__".format(component.id,
                                                  receiver_template.id)

                if ec.receiver_container:
                    target.add_attachment(receiver, ec.receiver_container)
                target.add_child(receiver_template.id, receiver)
                target = receiver
            else:
                source = r.resolve_path(ec.from_)
                target = r.resolve_path(ec.to)

            source_port = ec.source_port
            target_port = ec.target_port

            if not source_port:
                if len(source.event_out_ports) == 1:
                    source_port = source.event_out_ports[0]
                else:
                    raise SimBuildError(("No source event port "
                                         "uniquely identifiable"
                                         " in '{0}'").format(source.id))
            if not target_port:
                if len(target.event_in_ports) == 1:
                    target_port = target.event_in_ports[0]
                else:
                    raise SimBuildError(("No destination event port "
                                         "uniquely identifiable "
                                         "in '{0}'").format(target))

            if self.debug:
                print(
                    "register_event_out_callback\n   Source: %s, %s (port: %s) \n   -> %s, %s (port: %s)"
                    % (source, id(source), source_port, target, id(target),
                       target_port))
            source.register_event_out_callback(\
                source_port, lambda: target.inc_event_in(target_port))

        # Copy methods
        if getattr(self, "update_kinetic_scheme", None):
            r.update_kinetic_scheme = self.update_kinetic_scheme
        if getattr(self, "run_startup_event_handlers", None):
            r.run_startup_event_handlers = self.run_startup_event_handlers
        if getattr(self, "run_preprocessing_event_handlers", None):
            r.run_preprocessing_event_handlers = self.run_preprocessing_event_handlers
        if getattr(self, "run_postprocessing_event_handlers", None):
            r.run_postprocessing_event_handlers = self.run_postprocessing_event_handlers

        if getattr(self, "update_state_variables", None):
            r.update_state_variables = self.update_state_variables
        if getattr(self, "update_derived_variables", None):
            r.update_derived_variables = self.update_derived_variables
        #r.update_shadow_variables = self.update_shadow_variables
        if getattr(self, "update_derived_parameters", None):
            r.update_derived_parameters = self.update_derived_parameters

        for rn in self.regimes:
            r.add_regime(self.regimes[rn])
        r.current_regime = self.current_regime

        # Copy groups
        for gn in self.groups:
            g = self.__dict__[gn]
            for c in g:
                if c.uid in copies:
                    r.add_child_to_group(gn, copies[c.uid])
                else:
                    c2 = c.copy()
                    c2.parent = r
                    copies[c.uid] = c2
                    r.add_child_to_group(gn, c2)

        # Copy remaining runnable references.
        for k in self.__dict__:
            if k == 'parent':
                continue
            c = self.__dict__[k]
            if isinstance(c, Runnable):
                if c.uid in copies:
                    r.__dict__[k] = copies[c.uid]
                else:
                    c2 = c.copy()
                    c2.parent = r
                    copies[c.uid] = c2
                    r.__dict__[k] = c2

        # Copy text fields
        for k in self.__dict__:
            if not k in r.__dict__:
                c = self.__dict__[k]
                if self.debug:
                    print("Adding remaining field: %s = %s" % (k, c))
                r.__dict__[k] = c

        if self.debug:
            print('########################################')
            keys = list(self.__dict__.keys())
            keys.sort()
            print(len(keys))
            for k in keys:
                print(k, self.__dict__[k])
            print('----------------------------------------')
            keys = list(r.__dict__.keys())
            keys.sort()
            print(len(keys))
            for k in keys:
                print(k, r.__dict__[k])
            print('########################################')
            print('')
            print('')
            print('')
            print('')

        if self.debug: print("Finished coping..." + self.id)

        return r
示例#6
0
class Runnable(Reflective):
    uid_count = 0

    def __init__(self, id_, component, parent=None):
        Reflective.__init__(self)

        self.uid = Runnable.uid_count
        Runnable.uid_count += 1

        self.id = id_
        self.component = component
        self.parent = parent

        self.time_step = 0
        self.time_completed = 0
        self.time_total = 0

        self.plastic = True

        self.state_stack = Stack()

        self.children = {}
        self.uchildren = {}
        self.groups = []

        self.recorded_variables = []

        self.event_out_ports = []
        self.event_in_ports = []

        self.event_out_callbacks = {}
        self.event_in_counters = {}

        self.attachments = {}

        self.new_regime = ''
        self.current_regime = ''
        self.last_regime = ''
        self.regimes = {}

    def __str__(self):
        return 'Runnable, id: {0} ({1}, {2}), component: ({3})'.format(
            self.id, self.uid, id(self), self.component)

    def __repr__(self):
        return self.__str__()

    def add_child(self, id_, runnable):
        self.uchildren[runnable.uid] = runnable

        self.children[id_] = runnable
        self.children[runnable.id] = runnable

        self.__dict__[id_] = runnable
        self.__dict__[runnable.id] = runnable

        runnable.configure_time(self.time_step, self.time_total)

        runnable.parent = self

    def add_child_typeref(self, typename, runnable):
        self.__dict__[typename] = runnable

    def add_child_to_group(self, group_name, child):
        #print("add_child_to_group in %s; grp: %s; child: %s "%(self.id, group_name, child))
        if group_name not in self.__dict__:
            self.__dict__[group_name] = []
            self.groups.append(group_name)
        self.__dict__[group_name].append(child)
        child.parent = self

    def make_attachment(self, type_, name):
        self.attachments[type_] = name
        self.__dict__[name] = []

    def add_attachment(self, runnable, container=None):
        for ctype in runnable.component.types:
            if ctype in self.attachments:
                name = self.attachments[ctype]
                if container is not None and container != name:
                    continue

                if name not in self.__dict__:
                    raise SimBuildError(
                        'Cannot attach {0} to {1} in {2}'.format(
                            runnable.id, name, self.id))

                runnable.id = runnable.id + str(len(self.__dict__[name]))

                self.__dict__[name].append(runnable)
                runnable.parent = self

                return

        raise SimBuildError(
            'Unable to find appropriate attachment for {0} in {1}',
            runnable.id, self.id)

    def add_event_in_port(self, port):
        self.event_in_ports.append(port)
        if port not in self.event_in_counters:
            self.event_in_counters[port] = 0

    def inc_event_in(self, port):
        self.event_in_counters[port] += 1
        if self.debug:
            print("\n--- Event in to %s (%s, %s) on port: %s" %
                  (self.id, id(self), self.__class__, port))
            print("EIC (%s): %s" % (id(self), self.event_in_counters))

    def add_event_out_port(self, port):
        self.event_out_ports.append(port)
        if port not in self.event_out_callbacks:
            self.event_out_callbacks[port] = []

    def register_event_out_link(self, port, runnable, remote_port):
        self.event_out_callbacks[port].append((runnable, remote_port))

    def register_event_out_callback(self, port, callback):
        if self.debug:
            print("register_event_out_callback on %s, port: %s, callback: %s" %
                  (self.id, port, callback))
        if port in self.event_out_callbacks:
            self.event_out_callbacks[port].append(callback)
        else:
            raise SimBuildError('No event out port \'{0}\' in '
                                'component \'{1}\''.format(port, self.id))
        if self.debug: print("EOC: " + str(self.event_out_callbacks))

    def add_regime(self, regime):
        self.regimes[regime.name] = regime

    def resolve_path(self, path):
        if self.debug: print("Resolving path: %s in %s" % (path, self))
        if path == '':
            return self
        if path == 'this':
            return self
        if path[0] == '/':
            return self.parent.resolve_path(path)
        elif path.find('../') == 0:
            return self.parent.resolve_path(path[3:])
        elif path.find('..') == 0:
            return self.parent
        elif path == 'parent':
            return self.parent
        else:
            if path.find('/') >= 1:
                (child, new_path) = path.split('/', 1)
            else:
                child = path
                new_path = ''

            idxbegin = child.find('[')
            idxend = child.find(']')
            if idxbegin != 0 and idxend > idxbegin:
                idx = int(child[idxbegin + 1:idxend])
                child = child[:idxbegin]
            else:
                idx = -1

            if child in self.children:
                childobj = self.children[child]
                if idx != -1:
                    childobj = childobj.array[idx]
            elif child in self.component.parameters:
                ctx = self.component
                p = ctx.parameters[child]
                return self.resolve_path('../' + p.value)
            elif child in self.__dict__.keys():
                child_resolved = self.__dict__[child]
                #print("Think it's a link from %s to %s"%(child, child_resolved))
                return self.resolve_path('../' + child_resolved)
            else:
                if self.debug:
                    keys = list(self.__dict__.keys())
                    keys.sort()
                    prefix = "--- "
                    print('{0}    Keys for {1}'.format(prefix, self.id))
                    for k in keys:
                        key_str = str(self.__dict__[k])
                        if len(
                                key_str
                        ) > 0 and not key_str == "[]" and not key_str == "{}":
                            print('{0}       {1} -> {2}'.format(
                                prefix, k, key_str))

                raise SimBuildError('Unable to find child \'{0}\' in '
                                    '\'{1}\''.format(child, self.id))

            if new_path == '':
                return childobj
            else:
                return childobj.resolve_path(new_path)

    def add_variable_recorder(self, data_output, recorder):
        self.add_variable_recorder2(data_output, recorder, recorder.quantity)

    def add_variable_recorder2(self, data_output, recorder, path):
        if path[0] == '/':
            self.parent.add_variable_recorder2(data_output, recorder, path)
        elif path.find('../') == 0:
            self.parent.add_variable_recorder2(data_output, recorder, path[3:])
        elif path.find('/') >= 1:
            (child, new_path) = path.split('/', 1)

            idxbegin = child.find('[')
            idxend = child.find(']')
            if idxbegin != 0 and idxend > idxbegin:
                idx = int(child[idxbegin + 1:idxend])
                child = child[:idxbegin]
            else:
                idx = -1

            if child in self.children:
                childobj = self.children[child]
                if idx == -1:
                    childobj.add_variable_recorder2(data_output, recorder,
                                                    new_path)
                else:
                    childobj.array[idx].add_variable_recorder2(
                        data_output, recorder, new_path)
            elif child in self.component.children:
                cdef = self.component.children[child]
                childobj = None
                for cid in self.children:
                    c = self.children[cid]
                    if cdef.type in c.component.types:
                        childobj = c
                if childobj:
                    childobj.add_variable_recorder2(data_output, recorder,
                                                    new_path)
                else:
                    raise SimBuildError('Unable to find child \'{0}\' in '
                                        '\'{1}\''.format(child, self.id))
            else:
                raise SimBuildError('Unable to find child \'{0}\' in '
                                    '\'{1}\''.format(child, self.id))
        else:
            self.recorded_variables.append(
                Recording(path, data_output, recorder))

    def configure_time(self, time_step, time_total):
        self.time_step = time_step
        self.time_total = time_total

        for cn in self.uchildren:
            self.uchildren[cn].configure_time(self.time_step, self.time_total)

        for c in self.array:
            c.configure_time(self.time_step, self.time_total)

        ## for type_ in self.attachments:
        ##     components = self.__dict__[self.attachments[type_]]
        ##     for component in components:
        ##         component.configure_time(self.time_step, self.time_total)

    def reset_time(self):
        self.time_completed = 0

        for cid in self.uchildren:
            self.uchildren[cid].reset_time()

        for c in self.array:
            c.reset_time()

        ## for type_ in self.attachments:
        ##     components = self.__dict__[self.attachments[type_]]
        ##     for component in components:
        ##         component.reset_time()

    def single_step(self, dt):
        #return self.single_step2(dt)

        # For debugging
        try:
            return self.single_step2(dt)
        #except Ex1 as e:
        #    print self.rate
        #    print self.midpoint
        #    print self.scale
        #    print self.parent.parent.parent.parent.v
        #    # rate * exp((v - midpoint)/scale)
        #    sys.exit(0)
        except KeyError as e:
            r = self
            name = r.id
            while r.parent:
                r = r.parent
                name = "{0}.{1}".format(r.id, name)

            print("Error in '{0} ({1})': {2}".format(name, self.component.type,
                                                     e))
            print(e)

            prefix = "- "
            if self.instance_variables:
                print('Instance variables'.format(prefix))
                for vn in self.instance_variables:
                    print('{0}      {1} = {2}'.format(prefix, vn,
                                                      self.__dict__[vn]))
            if self.derived_variables:
                print('{0}    Derived variables'.format(prefix))
                for vn in self.derived_variables:
                    print('{0}      {1} = {2}'.format(prefix, vn,
                                                      self.__dict__[vn]))

            keys = list(self.__dict__.keys())
            keys.sort()
            for k in keys:
                print('{0} -> {1}'.format(k, str(self.__dict__[k])))
            print('')
            print('')

            if isinstance(e, ArithmeticError):
                print(('This is an arithmetic error. Consider reducing the '
                       'integration time step.'))

            sys.exit(0)

    def single_step2(self, dt):
        for cid in self.uchildren:
            self.uchildren[cid].single_step(dt)

        for child in self.array:
            child.single_step(dt)
        '''
        Regime transition now happens below...
        if self.new_regime != '':
            self.current_regime = self.new_regime
            self.new_regime = ''' ''

        if getattr(self, "update_kinetic_scheme", None):
            self.update_kinetic_scheme(self, dt)

        #if self.time_completed == 0:
        #    self.run_startup_event_handlers(self)

        if getattr(self, "run_preprocessing_event_handlers", None):
            self.run_preprocessing_event_handlers(self)
        if getattr(self, "update_shadow_variables", None):
            self.update_shadow_variables()

        if getattr(self, "update_derived_variables", None):
            self.update_derived_variables(self)
        if getattr(self, "update_shadow_variables", None):
            self.update_shadow_variables()

        if getattr(self, "update_state_variables", None):
            self.update_state_variables(self, dt)
        if getattr(self, "update_shadow_variables", None):
            self.update_shadow_variables()

        #if self.time_completed == 0:
        #    self.update_derived_parameters(self)

        if getattr(self, "run_postprocessing_event_handlers", None):
            self.run_postprocessing_event_handlers(self)
        if getattr(self, "update_shadow_variables", None):
            self.update_shadow_variables()

        if False:  #self.id == 'hhpop__hhcell__0':
            print('1', self.uid, self.v)
        if False:  #self.id == 'reverseRate':
            print('2', self.parent.parent.parent.parent.uid,
                  self.parent.parent.parent.parent.v)

        if self.current_regime != '':
            if self.debug: print("In reg: " + self.current_regime)
            regime = self.regimes[self.current_regime]

            #if getattr(self, "xxx", None):
            if getattr(regime, "update_kinetic_scheme", None):
                regime.update_kinetic_scheme(self, dt)

            if getattr(regime, "run_preprocessing_event_handlers", None):
                regime.run_preprocessing_event_handlers(self)
            if getattr(self, "update_shadow_variables", None):
                self.update_shadow_variables()

            if getattr(regime, "update_derived_variables", None):
                regime.update_derived_variables(self)
            if getattr(self, "update_shadow_variables", None):
                self.update_shadow_variables()

            if getattr(regime, "update_state_variables", None):
                regime.update_state_variables(self, dt)
            if getattr(self, "update_shadow_variables", None):
                self.update_shadow_variables()

            if getattr(regime, "run_postprocessing_event_handlers", None):
                regime.run_postprocessing_event_handlers(self)
            if getattr(self, "update_shadow_variables", None):
                self.update_shadow_variables()

            if self.new_regime != '':
                self.current_regime = self.new_regime
                self.new_regime = ''
                regime = self.regimes[self.current_regime]
                if getattr(regime, "run_preprocessing_event_handlers", None):
                    regime.run_preprocessing_event_handlers(self)
                if getattr(self, "update_shadow_variables", None):
                    self.update_shadow_variables()

            if self.debug: print("In reg: " + self.current_regime)

        self.record_variables()

        self.time_completed += dt
        if self.time_completed >= self.time_total:
            return 0
        else:
            return dt

    def do_startup(self):

        if self.debug and False:
            print("  Doing startup: " + self.id)
            for iv in self.instance_variables:
                print("%s = %s" % (iv, self.__dict__[iv]))
            for dv in self.derived_variables:
                print("%s = %s" % (dv, self.__dict__[dv]))

        for cid in self.uchildren:
            self.uchildren[cid].do_startup()

        for child in self.array:
            child.do_startup()

        #if getattr(self, "xxx", None):
        if getattr(self, "run_startup_event_handlers", None):
            self.run_startup_event_handlers(self)
        if getattr(self, "update_derived_parameters", None):
            self.update_derived_parameters(self)

        try:
            if getattr(self, "update_derived_variables", None):
                self.update_derived_variables(self)
        except Exception as e:
            print(
                "Problem setting initial value of DerivedVariable in %s: %s" %
                (self.id, e))
            print("Continuing...")

        for cid in self.uchildren:
            self.uchildren[cid].do_startup()

        for child in self.array:
            child.do_startup()

    def record_variables(self):
        for recording in self.recorded_variables:
            recording.add_value(self.time_completed,
                                self.__dict__[recording.variable])

    def push_state(self):
        vars = []
        for varname in self.instance_variables:
            vars += [
                self.__dict__[varname], self.__dict__[varname + '_shadow']
            ]
        self.state_stack.push(vars)

        for cid in self.uchildren:
            self.uchildren[cid].push_state()

        for c in self.array:
            c.push_state()

    def pop_state(self):
        vars = self.state_stack.pop()
        for varname in self.instance_variables:
            self.__dict_[varname] = vars[0]
            self.__dict_[varname + '_shadow'] = vars[1]
            vars = vars[2:]

        for cid in self.uchildren:
            self.uchildren[cid].pop_state()

        for c in self.array:
            c.pop_state()

    def update_shadow_variables(self):
        if self.plastic:
            for var in self.instance_variables:
                self.__dict__[var + '_shadow'] = self.__dict__[var]
            for var in self.derived_variables:
                self.__dict__[var + '_shadow'] = self.__dict__[var]

    def __lt__(self, other):
        return self.id < other.id

    def copy(self):
        """
        Make a copy of this runnable.

        @return: Copy of this runnable.
        @rtype: lems.sim.runnable.Runnable
        """
        if self.debug: print("Coping....." + self.id)
        r = Runnable(self.id, self.component, self.parent)
        copies = dict()

        # Copy simulation time parameters
        r.time_step = self.time_step
        r.time_completed = self.time_completed
        r.time_total = self.time_total

        # Plasticity and state stack (?)
        r.plastic = self.plastic
        r.state_stack = Stack()

        # Copy variables (GG - Faster using the add_* methods?)
        for v in self.instance_variables:
            r.instance_variables.append(v)
            r.__dict__[v] = self.__dict__[v]
            r.__dict__[v + '_shadow'] = self.__dict__[v + '_shadow']

        for v in self.derived_variables:
            r.derived_variables.append(v)
            r.__dict__[v] = self.__dict__[v]
            r.__dict__[v + '_shadow'] = self.__dict__[v + '_shadow']

        # Copy array elements
        for child in self.array:
            child_copy = child.copy()
            child_copy.parent = r
            r.array.append(child_copy)
            copies[child.uid] = child_copy

        # Copy attachment def
        for att in self.attachments:
            atn = self.attachments[att]
            r.attachments[att] = atn
            r.__dict__[atn] = []

        # Copy children
        for uid in self.uchildren:
            child = self.uchildren[uid]
            child_copy = child.copy()
            child_copy.parent = r
            copies[child.uid] = child_copy

            r.add_child(child_copy.id, child_copy)

            # For typerefs
            try:
                idx = [k for k in self.__dict__
                       if self.__dict__[k] == child][0]
                r.__dict__[idx] = child_copy
            except:
                pass

            # For groups and attachments:
            try:
                idx = [k for k in self.__dict__
                       if child in self.__dict__[k]][0]
                if idx not in r.__dict__:
                    r.__dict__[idx] = []
                r.__dict__[idx].append(child_copy)

            except:
                pass

        # Copy event ports
        for port in self.event_in_ports:
            r.event_in_ports.append(port)
            r.event_in_counters[port] = 0

        for port in self.event_out_ports:
            r.event_out_ports.append(port)
            r.event_out_callbacks[port] = self.event_out_callbacks[port]

        for ec in r.component.structure.event_connections:
            if self.debug:
                print("--- Fixing event_connection: %s in %s" %
                      (ec.toxml(), id(r)))

            source = r.parent.resolve_path(ec.from_)
            target = r.parent.resolve_path(ec.to)

            if ec.receiver:
                # Will throw error...
                receiver_template = self.build_runnable(ec.receiver, target)
                #receiver = copy.deepcopy(receiver_template)
                receiver = receiver_template.copy()
                receiver.id = "{0}__{1}__".format(component.id,
                                                  receiver_template.id)

                if ec.receiver_container:
                    target.add_attachment(receiver, ec.receiver_container)
                target.add_child(receiver_template.id, receiver)
                target = receiver
            else:
                source = r.resolve_path(ec.from_)
                target = r.resolve_path(ec.to)

            source_port = ec.source_port
            target_port = ec.target_port

            if not source_port:
                if len(source.event_out_ports) == 1:
                    source_port = source.event_out_ports[0]
                else:
                    raise SimBuildError(("No source event port "
                                         "uniquely identifiable"
                                         " in '{0}'").format(source.id))
            if not target_port:
                if len(target.event_in_ports) == 1:
                    target_port = target.event_in_ports[0]
                else:
                    raise SimBuildError(("No destination event port "
                                         "uniquely identifiable "
                                         "in '{0}'").format(target))

            if self.debug:
                print(
                    "register_event_out_callback\n   Source: %s, %s (port: %s) \n   -> %s, %s (port: %s)"
                    % (source, id(source), source_port, target, id(target),
                       target_port))
            source.register_event_out_callback(\
                source_port, lambda: target.inc_event_in(target_port))

        # Copy methods
        if getattr(self, "update_kinetic_scheme", None):
            r.update_kinetic_scheme = self.update_kinetic_scheme
        if getattr(self, "run_startup_event_handlers", None):
            r.run_startup_event_handlers = self.run_startup_event_handlers
        if getattr(self, "run_preprocessing_event_handlers", None):
            r.run_preprocessing_event_handlers = self.run_preprocessing_event_handlers
        if getattr(self, "run_postprocessing_event_handlers", None):
            r.run_postprocessing_event_handlers = self.run_postprocessing_event_handlers

        if getattr(self, "update_state_variables", None):
            r.update_state_variables = self.update_state_variables
        if getattr(self, "update_derived_variables", None):
            r.update_derived_variables = self.update_derived_variables
        #r.update_shadow_variables = self.update_shadow_variables
        if getattr(self, "update_derived_parameters", None):
            r.update_derived_parameters = self.update_derived_parameters

        for rn in self.regimes:
            r.add_regime(self.regimes[rn])
        r.current_regime = self.current_regime

        # Copy groups
        for gn in self.groups:
            g = self.__dict__[gn]
            for c in g:
                if c.uid in copies:
                    r.add_child_to_group(gn, copies[c.uid])
                else:
                    c2 = c.copy()
                    c2.parent = r
                    copies[c.uid] = c2
                    r.add_child_to_group(gn, c2)

        # Copy remaining runnable references.
        for k in self.__dict__:
            if k == 'parent':
                continue
            c = self.__dict__[k]
            if isinstance(c, Runnable):
                if c.uid in copies:
                    r.__dict__[k] = copies[c.uid]
                else:
                    c2 = c.copy()
                    c2.parent = r
                    copies[c.uid] = c2
                    r.__dict__[k] = c2

        # Copy text fields
        for k in self.__dict__:
            if not k in r.__dict__:
                c = self.__dict__[k]
                if self.debug:
                    print("Adding remaining field: %s = %s" % (k, c))
                r.__dict__[k] = c

        if self.debug:
            print('########################################')
            keys = list(self.__dict__.keys())
            keys.sort()
            print(len(keys))
            for k in keys:
                print(k, self.__dict__[k])
            print('----------------------------------------')
            keys = list(r.__dict__.keys())
            keys.sort()
            print(len(keys))
            for k in keys:
                print(k, r.__dict__[k])
            print('########################################')
            print('')
            print('')
            print('')
            print('')

        if self.debug: print("Finished coping..." + self.id)

        return r
示例#7
0
class Runnable(Reflective):
    uid_count = 0

    def __init__(self, id_, component, parent = None):
        Reflective.__init__(self)

        self.uid = Runnable.uid_count
        Runnable.uid_count += 1

        self.id = id_
        self.component = component
        self.parent = parent

        self.time_step = 0
        self.time_completed = 0
        self.time_total = 0

        self.plastic = True

        self.state_stack = Stack()

        self.children = {}
        self.uchildren = {}
        self.groups = []

        self.recorded_variables = []

        self.event_out_ports = []
        self.event_in_ports = []

        self.event_out_callbacks = {}
        self.event_in_counters = {}

        self.attachments = {}

        self.new_regime = ''
        self.current_regime = ''
        self.last_regime = ''
        self.regimes = {}
        
        
    def __str__(self):
        return 'Runnable, id: {0} ({1}, {2}), component: ({3})'.format(self.id, self.uid, id(self), self.component)
    
    def __repr__(self):
        return self.__str__()
            

    def add_child(self, id_, runnable):
        self.uchildren[runnable.uid] = runnable
        
        self.children[id_] = runnable
        self.children[runnable.id] = runnable

        self.__dict__[id_] = runnable
        self.__dict__[runnable.id] = runnable

        runnable.configure_time(self.time_step, self.time_total)

        runnable.parent = self

    def add_child_typeref(self, typename, runnable):
        self.__dict__[typename] = runnable

    def add_child_to_group(self, group_name, child):
        #print("add_child_to_group in %s; grp: %s; child: %s "%(self.id, group_name, child))
        if group_name not in self.__dict__:
            self.__dict__[group_name] = []
            self.groups.append(group_name)
        self.__dict__[group_name].append(child)
        child.parent = self

    def make_attachment(self, type_, name):
        self.attachments[type_] = name
        self.__dict__[name] = []

    def add_attachment(self, runnable, container = None):
        for ctype in runnable.component.types:
            if ctype in self.attachments:
                name = self.attachments[ctype]
                if container is not None and container != name:
                    continue
                
                if name not in self.__dict__:
                    raise SimBuildError('Cannot attach {0} to {1} in {2}'.format(
                        runnable.id, name, self.id))
                                                                                 
                runnable.id = runnable.id + str(len(self.__dict__[name]))

                self.__dict__[name].append(runnable)
                runnable.parent = self

                return

        raise SimBuildError('Unable to find appropriate attachment for {0} in {1}',
                            runnable.id, self.id)

    def add_event_in_port(self, port):
        self.event_in_ports.append(port)
        if port not in self.event_in_counters:
            self.event_in_counters[port] = 0

    def inc_event_in(self, port):
        self.event_in_counters[port] += 1
        if self.debug: 
            print("\n--- Event in to %s (%s, %s) on port: %s"%(self.id, id(self), self.__class__, port))
            print("EIC (%s): %s"%(id(self),self.event_in_counters))

    def add_event_out_port(self, port):
        self.event_out_ports.append(port)
        if port not in self.event_out_callbacks:
            self.event_out_callbacks[port] = []

    def register_event_out_link(self, port, runnable, remote_port):
        self.event_out_callbacks[port].append((runnable, remote_port))

    def register_event_out_callback(self, port, callback):
        if self.debug: print("register_event_out_callback on %s, port: %s, callback: %s"%(self.id, port, callback))
        if port in self.event_out_callbacks:
            self.event_out_callbacks[port].append(callback)
        else:
            raise SimBuildError('No event out port \'{0}\' in '
                                'component \'{1}\''.format(port, self.id))
        if self.debug: print("EOC: "+str(self.event_out_callbacks))

    def add_regime(self, regime):
        self.regimes[regime.name] = regime

    def resolve_path(self, path):
        if self.debug: print("Resolving path: %s in %s"%(path, self))
        if path == '':
            return self
        if path == 'this':
            return self
        if path[0] == '/':
            return self.parent.resolve_path(path)
        elif path.find('../') == 0:
            return self.parent.resolve_path(path[3:])
        elif path.find('..') == 0:
            return self.parent
        elif path == 'parent':
            return self.parent
        else:
            if path.find('/') >= 1:
                (child, new_path) = path.split('/', 1)
            else:
                child = path
                new_path = ''

            idxbegin = child.find('[')
            idxend = child.find(']')
            if idxbegin != 0 and idxend > idxbegin:
                idx = int(child[idxbegin+1:idxend])
                child = child[:idxbegin]
            else:
                idx = -1

            if child in self.children:
                childobj = self.children[child]
                if idx != -1:
                    childobj = childobj.array[idx]
            elif child in self.component.parameters:
                ctx = self.component
                p = ctx.parameters[child]
                return self.resolve_path('../' + p.value)
            elif child in self.__dict__.keys():
                child_resolved = self.__dict__[child]
                #print("Think it's a link from %s to %s"%(child, child_resolved))
                return self.resolve_path('../' + child_resolved)
            else:
                if self.debug:
                    keys = list(self.__dict__.keys())
                    keys.sort()
                    prefix = "--- "
                    print('{0}    Keys for {1}'.format(prefix, self.id))
                    for k in keys:
                        key_str = str(self.__dict__[k])
                        if len(key_str) > 0 and not key_str == "[]" and not key_str == "{}":
                            print('{0}       {1} -> {2}'.format(prefix, k, key_str))
                        
                raise SimBuildError('Unable to find child \'{0}\' in '
                                    '\'{1}\''.format(child, self.id))

            if new_path == '':
                return childobj
            else:
                return childobj.resolve_path(new_path)

    def add_variable_recorder(self, data_output, recorder):
        self.add_variable_recorder2(data_output, recorder, recorder.quantity)

    def add_variable_recorder2(self, data_output, recorder, path):
        if path[0] == '/':
            self.parent.add_variable_recorder2(data_output, recorder, path)
        elif path.find('../') == 0:
            self.parent.add_variable_recorder2(data_output, recorder, path[3:])
        elif path.find('/') >= 1:
            (child, new_path) = path.split('/', 1)

            idxbegin = child.find('[')
            idxend = child.find(']')
            if idxbegin != 0 and idxend > idxbegin:
                idx = int(child[idxbegin+1:idxend])
                child = child[:idxbegin]
            else:
                idx = -1

            if child in self.children:
                childobj = self.children[child]
                if idx == -1:
                    childobj.add_variable_recorder2(data_output,
                                                    recorder,
                                                    new_path)
                else:
                    childobj.array[idx].add_variable_recorder2(data_output,
                                                               recorder,
                                                               new_path)
            elif child in self.component.children:
                cdef = self.component.children[child]
                childobj = None
                for cid in self.children:
                    c = self.children[cid]
                    if cdef.type in c.component.types:
                        childobj = c
                if childobj:
                    childobj.add_variable_recorder2(data_output,
                                                    recorder,
                                                    new_path)
                else:                    
                    raise SimBuildError('Unable to find child \'{0}\' in '
                                        '\'{1}\''.format(child, self.id))
            else:
                raise SimBuildError('Unable to find child \'{0}\' in '
                                    '\'{1}\''.format(child, self.id))
        else:
            self.recorded_variables.append(Recording(path, data_output, recorder))


    def configure_time(self, time_step, time_total):
        self.time_step = time_step
        self.time_total = time_total

        for cn in self.uchildren:
            self.uchildren[cn].configure_time(self.time_step, self.time_total)

        for c in self.array:
            c.configure_time(self.time_step, self.time_total)

        ## for type_ in self.attachments:
        ##     components = self.__dict__[self.attachments[type_]]
        ##     for component in components:
        ##         component.configure_time(self.time_step, self.time_total)


    def reset_time(self):
        self.time_completed = 0

        for cid in self.uchildren:
            self.uchildren[cid].reset_time()

        for c in self.array:
            c.reset_time()

        ## for type_ in self.attachments:
        ##     components = self.__dict__[self.attachments[type_]]
        ##     for component in components:
        ##         component.reset_time()

    def single_step(self, dt):
        #return self.single_step2(dt)

        # For debugging
        try:
            return self.single_step2(dt)
        #except Ex1 as e:
        #    print self.rate
        #    print self.midpoint
        #    print self.scale
        #    print self.parent.parent.parent.parent.v
        #    # rate * exp((v - midpoint)/scale)
        #    sys.exit(0)
        except KeyError as e:
            r = self
            name = r.id
            while r.parent:
                r = r.parent
                name = "{0}.{1}".format(r.id, name)

            print("Error in '{0} ({1})': {2}".format(name,
                                                         self.component.type, 
                                                         e))
            print(e)
            
            prefix = "- "
            if self.instance_variables:
                print('Instance variables'.format(prefix))
                for vn in self.instance_variables:
                    print('{0}      {1} = {2}'.format(prefix, vn, self.__dict__[vn]))
            if self.derived_variables:
                print('{0}    Derived variables'.format(prefix))
                for vn in self.derived_variables:
                    print('{0}      {1} = {2}'.format(prefix, vn, self.__dict__[vn]))
            
            keys = list(self.__dict__.keys())
            keys.sort()
            for k in keys:
                print('{0} -> {1}'.format(k, str(self.__dict__[k])))
            print('')
            print('')

            if isinstance(e, ArithmeticError):
                print(('This is an arithmetic error. Consider reducing the '
                       'integration time step.'))

            sys.exit(0)

    def single_step2(self, dt):
        for cid in self.uchildren:
            self.uchildren[cid].single_step(dt)

        for child in self.array:
            child.single_step(dt)
            
        '''
        Regime transition now happens below...
        if self.new_regime != '':
            self.current_regime = self.new_regime
            self.new_regime = '''''
        
        if getattr(self, "update_kinetic_scheme", None): self.update_kinetic_scheme(self, dt)

        #if self.time_completed == 0:
        #    self.run_startup_event_handlers(self)

        if getattr(self, "run_preprocessing_event_handlers", None): self.run_preprocessing_event_handlers(self)
        if getattr(self, "update_shadow_variables", None): self.update_shadow_variables()

        if getattr(self, "update_derived_variables", None): self.update_derived_variables(self)
        if getattr(self, "update_shadow_variables", None): self.update_shadow_variables()
                
        if getattr(self, "update_state_variables", None): self.update_state_variables(self, dt)
        if getattr(self, "update_shadow_variables", None): self.update_shadow_variables()
        
        #if self.time_completed == 0:
        #    self.update_derived_parameters(self)

        if getattr(self, "run_postprocessing_event_handlers", None): self.run_postprocessing_event_handlers(self)
        if getattr(self, "update_shadow_variables", None): self.update_shadow_variables()

        if False:#self.id == 'hhpop__hhcell__0':
            print('1', self.uid, self.v)
        if False:#self.id == 'reverseRate':
            print('2', self.parent.parent.parent.parent.uid, self.parent.parent.parent.parent.v)

        if self.current_regime != '':
            if self.debug: print("In reg: "+self.current_regime)
            regime = self.regimes[self.current_regime]

            #if getattr(self, "xxx", None): 
            if getattr(regime, "update_kinetic_scheme", None): regime.update_kinetic_scheme(self, dt)

            if getattr(regime, "run_preprocessing_event_handlers", None): regime.run_preprocessing_event_handlers(self)
            if getattr(self, "update_shadow_variables", None): self.update_shadow_variables()

            if getattr(regime, "update_derived_variables", None): regime.update_derived_variables(self)
            if getattr(self, "update_shadow_variables", None): self.update_shadow_variables()

            if getattr(regime, "update_state_variables", None): regime.update_state_variables(self, dt)
            if getattr(self, "update_shadow_variables", None): self.update_shadow_variables()

            if getattr(regime, "run_postprocessing_event_handlers", None): regime.run_postprocessing_event_handlers(self)
            if getattr(self, "update_shadow_variables", None): self.update_shadow_variables()
            
            if self.new_regime != '':
                self.current_regime = self.new_regime
                self.new_regime = ''
                regime = self.regimes[self.current_regime]
                if getattr(regime, "run_preprocessing_event_handlers", None): regime.run_preprocessing_event_handlers(self)
                if getattr(self, "update_shadow_variables", None): self.update_shadow_variables()
                
            if self.debug: print("In reg: "+self.current_regime)
                

        self.record_variables()

        self.time_completed += dt
        if self.time_completed >= self.time_total:
            return 0
        else:
            return dt

    def do_startup(self):
        
        if self.debug and False:
            print("  Doing startup: "+self.id)
            for iv in self.instance_variables: print("%s = %s"%(iv,self.__dict__[iv]))
            for dv in self.derived_variables: print("%s = %s"%(dv,self.__dict__[dv]))
        
        for cid in self.uchildren:
            self.uchildren[cid].do_startup()

        for child in self.array:
            child.do_startup()
        
        #if getattr(self, "xxx", None): 
        if getattr(self, "run_startup_event_handlers", None): self.run_startup_event_handlers(self)
        if getattr(self, "update_derived_parameters", None): self.update_derived_parameters(self)
        
        try:
            if getattr(self, "update_derived_variables", None): self.update_derived_variables(self)
        except Exception as e:
            print("Problem setting initial value of DerivedVariable in %s: %s"%(self.id,e))
            print("Continuing...")
      
        for cid in self.uchildren:
            self.uchildren[cid].do_startup()

        for child in self.array:
            child.do_startup()
             

    def record_variables(self):
        for recording in self.recorded_variables:
            recording.add_value(self.time_completed,
                               self.__dict__[recording.variable])

    def push_state(self):
        vars = []
        for varname in self.instance_variables:
            vars += [self.__dict__[varname],
                     self.__dict__[varname + '_shadow']]
        self.state_stack.push(vars)

        for cid in self.uchildren:
            self.uchildren[cid].push_state()

        for c in self.array:
            c.push_state()

    def pop_state(self):
        vars = self.state_stack.pop()
        for varname in self.instance_variables:
            self.__dict_[varname] = vars[0]
            self.__dict_[varname + '_shadow'] = vars[1]
            vars = vars[2:]

        for cid in self.uchildren:
            self.uchildren[cid].pop_state()

        for c in self.array:
            c.pop_state()

    def update_shadow_variables(self):
        if self.plastic:
            for var in self.instance_variables:
                self.__dict__[var + '_shadow'] = self.__dict__[var]
            for var in self.derived_variables:
                self.__dict__[var + '_shadow'] = self.__dict__[var]

    def __lt__(self, other):
        return self.id < other.id

    def copy(self):
        """
        Make a copy of this runnable.

        @return: Copy of this runnable.
        @rtype: lems.sim.runnable.Runnable
        """
        if self.debug: print("Coping....."+self.id)
        r = Runnable(self.id, self.component, self.parent)
        copies = dict()

        # Copy simulation time parameters
        r.time_step = self.time_step
        r.time_completed = self.time_completed
        r.time_total = self.time_total

        # Plasticity and state stack (?)
        r.plastic = self.plastic
        r.state_stack = Stack()
        
        # Copy variables (GG - Faster using the add_* methods?)
        for v in self.instance_variables:
            r.instance_variables.append(v)
            r.__dict__[v] = self.__dict__[v]
            r.__dict__[v + '_shadow'] = self.__dict__[v + '_shadow']
        
        for v in self.derived_variables:
            r.derived_variables.append(v)
            r.__dict__[v] = self.__dict__[v]
            r.__dict__[v + '_shadow'] = self.__dict__[v + '_shadow']
        
        # Copy array elements
        for child in self.array:
            child_copy = child.copy()
            child_copy.parent = r
            r.array.append(child_copy)
            copies[child.uid] = child_copy
            
        # Copy attachment def
        for att in self.attachments:
            atn = self.attachments[att]
            r.attachments[att] = atn
            r.__dict__[atn] = []

        # Copy children
        for uid in self.uchildren:
            child = self.uchildren[uid]
            child_copy = child.copy()
            child_copy.parent = r
            copies[child.uid] = child_copy
            
            r.add_child(child_copy.id, child_copy)

            # For typerefs
            try:
                idx = [k for k in self.__dict__ if self.__dict__[k] == child][0]
                r.__dict__[idx] = child_copy
            except:
                pass

            # For groups and attachments:
            try:
                idx = [k for k in self.__dict__ if child in self.__dict__[k]][0]
                if idx not in r.__dict__:
                    r.__dict__[idx] = []
                r.__dict__[idx].append(child_copy)

            except:
                pass
               
        # Copy event ports
        for port in self.event_in_ports:
            r.event_in_ports.append(port)
            r.event_in_counters[port] = 0

        for port in self.event_out_ports:
            r.event_out_ports.append(port)
            r.event_out_callbacks[port] = self.event_out_callbacks[port]
        
        for ec in r.component.structure.event_connections:
            if self.debug: print("--- Fixing event_connection: %s in %s"%(ec.toxml(), id(r)))
            
            source = r.parent.resolve_path(ec.from_)
            target = r.parent.resolve_path(ec.to)
            
            if ec.receiver:
                # Will throw error...
                receiver_template = self.build_runnable(ec.receiver, target)                                
                #receiver = copy.deepcopy(receiver_template)
                receiver = receiver_template.copy()
                receiver.id = "{0}__{1}__".format(component.id,
                                                  receiver_template.id)

                if ec.receiver_container:
                    target.add_attachment(receiver, ec.receiver_container)
                target.add_child(receiver_template.id, receiver)
                target = receiver
            else:
                source = r.resolve_path(ec.from_)
                target = r.resolve_path(ec.to)

            source_port = ec.source_port
            target_port = ec.target_port

            if not source_port:
                if len(source.event_out_ports) == 1:
                    source_port = source.event_out_ports[0]
                else:
                    raise SimBuildError(("No source event port "
                                         "uniquely identifiable"
                                         " in '{0}'").format(source.id))
            if not target_port:
                if len(target.event_in_ports) == 1:
                    target_port = target.event_in_ports[0]
                else:
                    raise SimBuildError(("No destination event port "
                                         "uniquely identifiable "
                                         "in '{0}'").format(target))
             
            if self.debug: print("register_event_out_callback\n   Source: %s, %s (port: %s) \n   -> %s, %s (port: %s)"%(source, id(source), source_port, target, id(target), target_port))
            source.register_event_out_callback(\
                source_port, lambda: target.inc_event_in(target_port))
            
        
            

        # Copy methods
        if getattr(self, "update_kinetic_scheme", None): r.update_kinetic_scheme = self.update_kinetic_scheme
        if getattr(self, "run_startup_event_handlers", None): r.run_startup_event_handlers = self.run_startup_event_handlers
        if getattr(self, "run_preprocessing_event_handlers", None): r.run_preprocessing_event_handlers = self.run_preprocessing_event_handlers
        if getattr(self, "run_postprocessing_event_handlers", None): r.run_postprocessing_event_handlers = self.run_postprocessing_event_handlers
        
        if getattr(self, "update_state_variables", None): r.update_state_variables = self.update_state_variables
        if getattr(self, "update_derived_variables", None): r.update_derived_variables = self.update_derived_variables
        #r.update_shadow_variables = self.update_shadow_variables
        if getattr(self, "update_derived_parameters", None): r.update_derived_parameters = self.update_derived_parameters

        for rn in self.regimes:
            r.add_regime(self.regimes[rn])
        r.current_regime = self.current_regime

        # Copy groups
        for gn in self.groups:
            g = self.__dict__[gn]
            for c in g:
                if c.uid in copies:
                    r.add_child_to_group(gn, copies[c.uid])
                else:
                    c2 = c.copy()
                    c2.parent = r
                    copies[c.uid] = c2
                    r.add_child_to_group(gn, c2)
                    

        # Copy remaining runnable references.
        for k in self.__dict__:
            if k == 'parent':
                continue
            c = self.__dict__[k]
            if isinstance(c, Runnable):
                if c.uid in copies:
                    r.__dict__[k] = copies[c.uid]
                else:
                    c2 = c.copy()
                    c2.parent = r
                    copies[c.uid] = c2
                    r.__dict__[k] = c2
           
        # Copy text fields
        for k in self.__dict__:          
            if not k in r.__dict__:
                c = self.__dict__[k]
                if self.debug: print("Adding remaining field: %s = %s"%(k,c))
                r.__dict__[k] = c
                
        if self.debug:
            print('########################################')
            keys = list(self.__dict__.keys())
            keys.sort()
            print(len(keys))
            for k in keys:
                print(k, self.__dict__[k])
            print('----------------------------------------')
            keys = list(r.__dict__.keys())
            keys.sort()
            print(len(keys))
            for k in keys:
                print(k, r.__dict__[k])
            print('########################################')
            print('')
            print('')
            print('')
            print('')
            
        if self.debug: print("Finished coping..."+self.id)
        
        return r