Commit b85deb77 authored by Alexandr Sokolov's avatar Alexandr Sokolov

Merge branch 'pars' into 'dev'

Парсер aDOT формата в рамках pycomsdk See merge request !1
parents 1b6fe950 8ad596ce
import unittest
from copy import deepcopy
import subprocess
import os
import random
import sys
from test_funcs.simplest import *
import comsdk.parser as pars
from comsdk.graph import *
from comsdk.edge import Edge
prsr = pars.Parser(tocpp=True)
data = {"a":10, "b":0}
gr = prsr.parse_file(sys.argv[1])
if sys.argv[2] !="":
prsr.generate_cpp(sys.argv[2])
else:
prsr.generate_cpp()
...@@ -8,7 +8,7 @@ import json ...@@ -8,7 +8,7 @@ import json
from stat import S_ISDIR from stat import S_ISDIR
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
from comsdk.aux import load_function_from_module from comsdk.comaux import load_function_from_module
class Host(object): class Host(object):
''' '''
......
from comsdk.aux import find_dir_by_named_regexp from comsdk.comaux import find_dir_by_named_regexp
from functools import partial from functools import partial
import os import os
......
import comsdk.aux as aux import comsdk.comaux as aux
from comsdk.communication import CommunicationError from comsdk.communication import CommunicationError
from comsdk.graph import Func
from mako.template import Template from mako.template import Template
import os import os
...@@ -26,43 +27,53 @@ class InOutMapping(object): ...@@ -26,43 +27,53 @@ class InOutMapping(object):
class Edge(object): class Edge(object):
__slots__ = [ __slots__ = [
'_predicate', 'pred_f',
'_morphism', 'morph_f',
'_io_mapping', '_io_mapping',
'preprocess', 'preprocess',
'postprocess', 'postprocess',
'order',
'comment'
] ]
def __init__(self, predicate, morphism, def __init__(self, predicate, morphism,
io_mapping=InOutMapping(), io_mapping=InOutMapping(),
order=0,
comment=""
): ):
self._predicate = predicate self.pred_f = predicate
self._morphism = morphism self.morph_f = morphism
self._io_mapping = io_mapping self._io_mapping = io_mapping
self.preprocess = lambda pd: None self.preprocess = lambda pd: None
self.postprocess = lambda pd: None self.postprocess = lambda pd: None
self.order = int(0 if order is None else order)
self.comment = comment
def predicate(self, data, dynamic_keys_mapping={}): def predicate(self, data, dynamic_keys_mapping={}):
proxy_data = self._io_mapping.build_proxy_data(data, dynamic_keys_mapping) proxy_data = self._io_mapping.build_proxy_data(data, dynamic_keys_mapping)
return self._predicate(proxy_data) return self.pred_f.func(proxy_data)
def morph(self, data, dynamic_keys_mapping={}): def morph(self, data, dynamic_keys_mapping={}):
#print(dynamic_keys_mapping) # print(self.pred_name, self.morph_name, self.order)
proxy_data = self._io_mapping.build_proxy_data(data, dynamic_keys_mapping) proxy_data = self._io_mapping.build_proxy_data(data, dynamic_keys_mapping)
#print(proxy_data) # print(proxy_data)
self.preprocess(data) self.preprocess(data)
self._morphism(proxy_data) self.morph_f.func(proxy_data)
self.postprocess(data) self.postprocess(data)
class DummyEdge(Edge):
def __init__(self):
super().__init__(None, None)
def predicate(self, data, dynamic_keys_mapping={}): # class DummyEdge(Edge):
return True # def __init__(self):
# super().__init__(None, None)
#
# def predicate(self, data, dynamic_keys_mapping={}):
# return True
#
# def morph(self, data, dynamic_keys_mapping={}):
# self.preprocess(data)
# self.postprocess(data)
def morph(self, data, dynamic_keys_mapping={}): def DummyEdge():
self.preprocess(data) return Edge(Func(), Func())
self.postprocess(data)
class ExecutableProgramEdge(Edge): class ExecutableProgramEdge(Edge):
''' '''
......
...@@ -2,59 +2,68 @@ import collections ...@@ -2,59 +2,68 @@ import collections
import os import os
from enum import Enum, auto from enum import Enum, auto
from functools import partial from functools import partial
import importlib as imp
import comsdk.aux as aux
import comsdk.comaux as aux
ImplicitParallelizationInfo = collections.namedtuple('ImplicitParallelizationInfo', ['array_keys_mapping', 'branches_number', 'branch_i']) ImplicitParallelizationInfo = collections.namedtuple('ImplicitParallelizationInfo', ['array_keys_mapping', 'branches_number', 'branch_i'])
class Morphism: class Func():
def __init__(self, edge, output_state): __slots__ = (
'module',
'func',
'comment',
'name'
)
def __init__(self, module="", name="", dummy=False,func=None, comment=''):
self.module = module
self.name = name
self.comment=comment.replace("\0", " ") if comment is not None else ""
if module =="" or name =="" or module is None or name is None:
dummy = True
if func is not None:
self.func = func
elif dummy:
self.func = lambda data: data
else:
print("LOADING function {} from {} module".format(name, module) )
try:
self.func = getattr(imp.import_module(module), name)
except Exception:
raise Exception("Could not load function {} from {} module".format(name, module))
def __str__(self):
if self.module =="" or self.name =="":
return ''
return "{}_{}".format(self.module, self.name)
class Selector(Func):
def __init__(self, ntransf, module="", name="", dummy=False):
if module=="" and name =="":
dummy = True
self.dummy = dummy
super().__init__(module, name, func=(lambda x: [True for i in range(ntransf)]) if dummy else None)
def __str__(self):
if self.module =="" or self.name =="":
return ''
return "{}_{}".format(self.module, self.name)
class Transfer:
def __init__(self, edge, output_state, order=0, comment = None):
self.edge = edge self.edge = edge
self.output_state = output_state self.output_state = output_state
self.order = order
def morph(self, data, dynamic_keys_mapping={}): def transfer(self, data, dynamic_keys_mapping={}):
#print(dynamic_keys_mapping)
self.edge.morph(data, dynamic_keys_mapping) self.edge.morph(data, dynamic_keys_mapping)
#return self.output_state, None
return self.output_state return self.output_state
class IdleRunType(Enum): class IdleRunType(Enum):
INIT = auto() INIT = auto()
CLEANUP = auto() CLEANUP = auto()
class GraphFactory:
def __init__(self):
pass
def create_state():
pass
def create_edge():
# Here we should somehow pass the argument for "special" edges
# Essentially, we change only io_mapping
pass
def make_graph():
pass
class PluralGraphFactory:
def __init__(self, plural_keys_mappings, parallel_graphs_number):
self.plural_keys_mappings = plural_keys_mappings
self.parallel_graphs_number = parallel_graphs_number
self.init_state = None
def create_state(state):
if self.init_state == None:
self.init_state = state
def create_edge():
# Here we should somehow pass the argument for "special" edges
# Essentially, we change only io_mapping
pass
def make_graph():
pass
class PluralState: class PluralState:
def __init__(self, states): def __init__(self, states):
self.states = states self.states = states
...@@ -62,7 +71,7 @@ class PluralState: ...@@ -62,7 +71,7 @@ class PluralState:
def connect_to(self, term_states, edge): def connect_to(self, term_states, edge):
for init_state, term_state in zip(self.states, term_states): for init_state, term_state in zip(self.states, term_states):
init_state.output_morphisms.append(Morphism(edge, term_state)) init_state.transfers.append(Transfer(edge, term_state))
class Graph: class Graph:
''' '''
...@@ -93,18 +102,18 @@ class Graph: ...@@ -93,18 +102,18 @@ class Graph:
while cur_state is not None: while cur_state is not None:
# print('1) In main loop', implicit_parallelization_info) # print('1) In main loop', implicit_parallelization_info)
# morph = _run_state(cur_state, data, implicit_parallelization_info) # morph = _run_state(cur_state, data, implicit_parallelization_info)
morph, implicit_parallelization_info = _run_state(cur_state, data, implicit_parallelization_info) transfer_f, implicit_parallelization_info = _run_state(cur_state, data, implicit_parallelization_info)
# print('2) In main loop', implicit_parallelization_info) # print('2) In main loop', implicit_parallelization_info)
if '__EXCEPTION__' in data: if '__EXCEPTION__' in data:
return False return False
# cur_state, implicit_parallelization_info = morph(data) # cur_state, implicit_parallelization_info = morph(data)
cur_state = morph(data) cur_state = transfer_f(data)
# print(morph) # print(morph)
if '__EXCEPTION__' in data: if '__EXCEPTION__' in data:
return False return False
return True return True
def init_graph(self, data): def init_graph(self, data={}):
if not self._initialized: if not self._initialized:
self.init_state.idle_run(IdleRunType.INIT, [self.init_state.name]) self.init_state.idle_run(IdleRunType.INIT, [self.init_state.name])
self._initialized = True self._initialized = True
...@@ -114,41 +123,53 @@ class Graph: ...@@ -114,41 +123,53 @@ class Graph:
if not '__WORKING_DIR__' in data: if not '__WORKING_DIR__' in data:
data['__WORKING_DIR__'] = data['__CURRENT_WORKING_DIR__'] data['__WORKING_DIR__'] = data['__CURRENT_WORKING_DIR__']
class State: class State:
__slots__ = [ __slots__ = [
'name', 'name',
'input_edges_number', 'input_edges_number', #output_edges_number == len(transfers)
'looped_edges_number', 'looped_edges_number',
'activated_input_edges_number', 'activated_input_edges_number',
'output_morphisms', 'transfers',
'parallelization_policy', 'parallelization_policy',
'selection_policy', 'selector',
'is_term_state', 'is_term_state',
'array_keys_mapping', 'array_keys_mapping',
'_branching_states_history', '_branching_states_history',
'_proxy_state', '_proxy_state',
'possible_branches',
'comment'
] ]
def __init__(self, name, def __init__(self, name,
parallelization_policy=None, parallelization_policy=None,
selection_policy=None, selector=None,
array_keys_mapping=None, # if array_keys_mapping is not None, we have implicit parallelization in this state array_keys_mapping=None, # if array_keys_mapping is not None, we have implicit parallelization in this state
): ):
self.name = name self.name = name
self.parallelization_policy = SerialParallelizationPolicy() if parallelization_policy is None else parallelization_policy self.parallelization_policy = SerialParallelizationPolicy() if parallelization_policy is None else parallelization_policy
self.selection_policy = OnlyOneSelectionPolicy() if selection_policy is None else selection_policy self.selector = Selector(1) if selector is None else selector
self.array_keys_mapping = array_keys_mapping self.array_keys_mapping = array_keys_mapping
self.input_edges_number = 0 self.input_edges_number = 0
self.looped_edges_number = 0 self.looped_edges_number = 0
self.activated_input_edges_number = 0 self.activated_input_edges_number = 0
self.output_morphisms = [] self.transfers = []
self.possible_branches=[]
self.is_term_state=False self.is_term_state=False
self._branching_states_history = None self._branching_states_history = None
self._proxy_state=None self._proxy_state=None
self.comment = None
def idle_run(self, idle_run_type, branching_states_history): def idle_run(self, idle_run_type, branching_states_history):
def __sort_by_order(tr):
return tr.edge.order
self.transfers.sort(key = __sort_by_order)
# print(self.name)
# for t in self.transfers:
# print("\t", t.edge.order, t.edge.pred_name, t.edge.morph_name)
if self._proxy_state is not None: if self._proxy_state is not None:
return self._proxy_state.idle_run(idle_run_type, branching_states_history) return self._proxy_state.idle_run(idle_run_type, branching_states_history)
# print('{} {} -> '.format(self.name, branching_states_history), end='')
if idle_run_type == IdleRunType.INIT: if idle_run_type == IdleRunType.INIT:
self.input_edges_number += 1 self.input_edges_number += 1
if self.input_edges_number != 1: if self.input_edges_number != 1:
...@@ -159,66 +180,66 @@ class State: ...@@ -159,66 +180,66 @@ class State:
self._branching_states_history = branching_states_history self._branching_states_history = branching_states_history
elif idle_run_type == IdleRunType.CLEANUP: elif idle_run_type == IdleRunType.CLEANUP:
self.activated_input_edges_number = 0 self.activated_input_edges_number = 0
# print('\tCLEANUP STATE {}, active: {}, branches_story: {}'.format(self.name, self.activated_input_edges_number, self._branching_states_history))
if self._branching_states_history is not None and self._is_looped_branch(branching_states_history): if self._branching_states_history is not None and self._is_looped_branch(branching_states_history):
# print('\tqwer')
self._branching_states_history = None self._branching_states_history = None
return return
if self._branching_states_history is None: if self._branching_states_history is None:
self._branching_states_history = branching_states_history self._branching_states_history = branching_states_history
else: else:
self.activated_input_edges_number += 1 # BUG: here we need to choose somehow whether we proceed or not self.activated_input_edges_number += 1 # BUG: here we need to choose somehow whether we proceed or not
# if len(self.output_edges) == 0: # if len(self.transfers) == 0:
# print('Terminate state found') # print('Terminate state found')
if len(self.output_morphisms) == 1: if len(self.transfers) == 1:
self.output_morphisms[0].output_state.idle_run(idle_run_type, branching_states_history) self.transfers[0].output_state.idle_run(idle_run_type, branching_states_history)
else: else:
for i, morphism in enumerate(self.output_morphisms): for i, transfer in enumerate(self.transfers):
next_state = morphism.output_state next_state = transfer.output_state
next_state.idle_run(idle_run_type, branching_states_history + [next_state.name]) next_state.idle_run(idle_run_type, branching_states_history + [next_state.name])
def connect_to(self, term_state, edge): def connect_to(self, term_state, edge=None, comment=None):
self.output_morphisms.append(Morphism(edge, term_state)) if comment is not None or comment != "":
self.comment = comment
self.transfers.append(Transfer(edge, term_state))
self.selector = Selector(len(self.transfers))
# edge.set_output_state(term_state) # edge.set_output_state(term_state)
# self.output_edges.append(edge) # self.output_edges.append(edge)
def replace_with_graph(self, graph): def replace_with_graph(self, graph):
self._proxy_state = graph.init_state self._proxy_state = graph.init_state
graph.term_state.output_morphisms = self.output_morphisms graph.term_state.transfers = self.transfers
graph.term_state.selector = self.selector
def run(self, data, implicit_parallelization_info=None): def run(self, data, implicit_parallelization_info=None):
print('STATE {}, just entered, implicit_parallelization_info: {}'.format(self.name, implicit_parallelization_info)) print('STATE {}\n\tjust entered, implicit_parallelization_info: {}'.format(self.name, implicit_parallelization_info))
# print('\t{}'.format(data))
if self._proxy_state is not None: if self._proxy_state is not None:
return self._proxy_state.run(data, implicit_parallelization_info) return self._proxy_state.run(data, implicit_parallelization_info)
self._activate_input_edge(implicit_parallelization_info) self._activate_input_edge(implicit_parallelization_info)
#self.activated_input_edges_number += 1 #self.activated_input_edges_number += 1
print('STATE {}, required input: {}, active: {}, looped: {}'.format(self.name, self.input_edges_number, self.activated_input_edges_number, self.looped_edges_number)) print('\trequired input: {}, active: {}, looped: {}'.format(self.input_edges_number, self.activated_input_edges_number, self.looped_edges_number))
# print('qwer') # print('qwer')
if not self._ready_to_morph(implicit_parallelization_info): if not self._ready_to_transfer(implicit_parallelization_info):
return None, None # it means that this state waits for some incoming edges (it is a point of collision of several edges) return None, None # it means that this state waits for some incoming edges (it is a point of collision of several edges)
self._reset_activity(implicit_parallelization_info) self._reset_activity(implicit_parallelization_info)
if self.is_term_state: if self.is_term_state:
implicit_parallelization_info = None implicit_parallelization_info = None
#print(self.name) if len(self.transfers) == 0:
if len(self.output_morphisms) == 0: return transfer_to_termination, None
return morphism_to_termination, None
predicate_values = []
dynamic_keys_mapping = build_dynamic_keys_mapping(implicit_parallelization_info) dynamic_keys_mapping = build_dynamic_keys_mapping(implicit_parallelization_info)
for morphism in self.output_morphisms: selected_edges = self.selector.func(data)
predicate_values.append(morphism.edge.predicate(data, dynamic_keys_mapping)) if not selected_edges:
selected_edge_indices = self.selection_policy.select(predicate_values)
if not selected_edge_indices:
raise GraphUnexpectedTermination( raise GraphUnexpectedTermination(
'State {}: Predicate values {} do not conform selection policy'.format(self.name, predicate_values)) "STATE {}: error in selector: {} ".format(self.name, selected_edges))
selected_morphisms = [self.output_morphisms[i] for i in selected_edge_indices] selected_transfers = [self.transfers[i] for i, _ in enumerate(selected_edges) if selected_edges[i]==True]
return self.parallelization_policy.make_morphism(selected_morphisms, for transf in selected_transfers:
if not transf.edge.predicate(data, dynamic_keys_mapping):
raise Exception("\tERROR: predicate {} returns {} running from state {}\n data{}".format(transf.edge.pred_f.name,transf.edge.predicate(data, dynamic_keys_mapping), self.name, data))
return self.parallelization_policy.make_transfer_func(selected_transfers,
array_keys_mapping=self.array_keys_mapping, array_keys_mapping=self.array_keys_mapping,
implicit_parallelization_info=implicit_parallelization_info,), \ implicit_parallelization_info=implicit_parallelization_info, state=self), \
implicit_parallelization_info implicit_parallelization_info
# return self.parallelization_policy.make_morphism(selected_morphisms,
# array_keys_mapping=self.array_keys_mapping,
# implicit_parallelization_info=implicit_parallelization_info,)
def _activate_input_edge(self, implicit_parallelization_info=None): def _activate_input_edge(self, implicit_parallelization_info=None):
if implicit_parallelization_info is None or self.is_term_state: if implicit_parallelization_info is None or self.is_term_state:
...@@ -228,7 +249,7 @@ class State: ...@@ -228,7 +249,7 @@ class State:
self.activated_input_edges_number = [0 for i in range(implicit_parallelization_info.branches_number)] self.activated_input_edges_number = [0 for i in range(implicit_parallelization_info.branches_number)]
self.activated_input_edges_number[implicit_parallelization_info.branch_i] += 1 self.activated_input_edges_number[implicit_parallelization_info.branch_i] += 1
def _ready_to_morph(self, implicit_parallelization_info=None): def _ready_to_transfer(self, implicit_parallelization_info=None):
required_activated_input_edges_number = self.input_edges_number - self.looped_edges_number required_activated_input_edges_number = self.input_edges_number - self.looped_edges_number
if implicit_parallelization_info is not None: if implicit_parallelization_info is not None:
if self.is_term_state: if self.is_term_state:
...@@ -247,7 +268,7 @@ class State: ...@@ -247,7 +268,7 @@ class State:
def _reset_activity(self, implicit_parallelization_info=None): def _reset_activity(self, implicit_parallelization_info=None):
self._branching_states_history = None self._branching_states_history = None
if self._ready_to_morph(implicit_parallelization_info) and self._has_loop(): if self._ready_to_transfer(implicit_parallelization_info) and self._has_loop():
if implicit_parallelization_info is None or self.is_term_state: if implicit_parallelization_info is None or self.is_term_state:
self.activated_input_edges_number -= 1 self.activated_input_edges_number -= 1
else: else:
...@@ -265,7 +286,8 @@ class State: ...@@ -265,7 +286,8 @@ class State:
def _has_loop(self): def _has_loop(self):
return self.looped_edges_number != 0 return self.looped_edges_number != 0
def morphism_to_termination(data):
def transfer_to_termination(data):
return None return None
class SerialParallelizationPolicy: class SerialParallelizationPolicy:
...@@ -274,59 +296,12 @@ class SerialParallelizationPolicy: ...@@ -274,59 +296,12 @@ class SerialParallelizationPolicy:
def __init__(self): def __init__(self):
pass pass
# def make_morphism(self, morphisms, array_keys_mapping=None, implicit_parallelization_info=None): def make_transfer_func(self, morphisms, array_keys_mapping=None, implicit_parallelization_info=None, state=None):
# def _morph(data):
# if array_keys_mapping is None:
# dynamic_keys_mapping = build_dynamic_keys_mapping(implicit_parallelization_info)
# next_morphs = [partial(morphism.morph, dynamic_keys_mapping=dynamic_keys_mapping) for morphism in morphisms]
# next_impl_para_infos = [implicit_parallelization_info for _ in morphisms]
# # print('\t\t {}'.format(implicit_parallelization_infos))
# else:
# if len(morphisms) != 1:
# raise BadGraphStructure('Impossible to create implicit paralleilzation in the state with {} output edges'.format(len(morphisms)))
# dynamic_keys_mapping = build_dynamic_keys_mapping(implicit_parallelization_info)
# proxy_data = aux.ProxyDict(data, keys_mappings=array_keys_mapping)
# anykey = next(iter(array_keys_mapping.keys()))
# implicit_branches_number = len(proxy_data[anykey])
# next_morphs = []
# next_impl_para_infos = []
# for branch_i in range(implicit_branches_number):
# implicit_parallelization_info_ = ImplicitParallelizationInfo(array_keys_mapping, implicit_branches_number, branch_i)
# dynamic_keys_mapping = build_dynamic_keys_mapping(implicit_parallelization_info_)
# next_morphs.append(partial(morphisms[0].morph, dynamic_keys_mapping=dynamic_keys_mapping))
# next_impl_para_infos.append(implicit_parallelization_info_)
# cur_morphs = []
# cur_impl_para_infos = []
# while len(next_morphs) != 1:
# cur_morphs[:] = next_morphs[:]
# cur_impl_para_infos[:] = next_impl_para_infos[:]
# del next_morphs[:]
# del next_impl_para_infos[:]
# # WE DO NOT UPDATE implicit_parallelization_infos !!!
# for morph, impl_para_info in zip(cur_morphs, cur_impl_para_infos):
# next_state, _ = morph(data)
## print('\t next_state: {}, with impl para info: {}'.format(next_state.name, impl_para_info))
# if next_state is None:
# return None, None
# next_morph = _run_state(next_state, data, impl_para_info)
## print('\t next_morph: {}'.format(next_morph))
# if '__EXCEPTION__' in data:
# return None, None
# if next_morph is not None:
# next_morphs.append(next_morph)
# next_impl_para_infos.append(impl_para_info)
# #print(len(next_morphs))
## print('\t last morph: {}'.format(next_morphs[0]))
# next_state, _ = next_morphs[0](data)
# print(next_state.name, next_impl_para_infos[0])
# return next_state, next_impl_para_infos[0]
# return _morph
def make_morphism(self, morphisms, array_keys_mapping=None, implicit_parallelization_info=None):
def _morph(data): def _morph(data):
# print("MORPHING FROM {}".format(state.name))
if array_keys_mapping is None: if array_keys_mapping is None:
dynamic_keys_mapping = build_dynamic_keys_mapping(implicit_parallelization_info) dynamic_keys_mapping = build_dynamic_keys_mapping(implicit_parallelization_info)
next_morphs = [partial(morphism.morph, dynamic_keys_mapping=dynamic_keys_mapping) for morphism in morphisms] next_morphs = [partial(morphism.transfer, dynamic_keys_mapping=dynamic_keys_mapping) for morphism in morphisms]
next_impl_para_infos = [implicit_parallelization_info for _ in morphisms] next_impl_para_infos = [implicit_parallelization_info for _ in morphisms]
# print('\t\t {}'.format(implicit_parallelization_infos)) # print('\t\t {}'.format(implicit_parallelization_infos))
else: else:
...@@ -349,7 +324,7 @@ class SerialParallelizationPolicy: ...@@ -349,7 +324,7 @@ class SerialParallelizationPolicy:
#while len(next_morphs) != 1 or _is_implicitly_parallelized(next_impl_para_infos): #while len(next_morphs) != 1 or _is_implicitly_parallelized(next_impl_para_infos):
while len(next_morphs) != 1 or _requires_joint_of_implicit_parallelization(array_keys_mapping, next_impl_para_infos): while len(next_morphs) != 1 or _requires_joint_of_implicit_parallelization(array_keys_mapping, next_impl_para_infos):
if next_impl_para_infos == []: if next_impl_para_infos == []:
raise Exception(str(len(next_morphs))) raise Exception("Morphs count on state {} is {}".format(state.name, str(len(next_morphs))))
# print(array_keys_mapping, next_impl_para_infos) # print(array_keys_mapping, next_impl_para_infos)
cur_morphs[:] = next_morphs[:] cur_morphs[:] = next_morphs[:]
cur_impl_para_infos[:] = next_impl_para_infos[:] cur_impl_para_infos[:] = next_impl_para_infos[:]
...@@ -376,26 +351,6 @@ class SerialParallelizationPolicy: ...@@ -376,26 +351,6 @@ class SerialParallelizationPolicy:
return _morph return _morph
class OnlyOneSelectionPolicy:
def __init__(self):
pass
def select(self, predicate_values):
trues_indices = _get_trues(predicate_values)
if len(trues_indices) != 1:
return None
return trues_indices
class AllSelectionPolicy:
def __init__(self):
pass
def select(self, predicate_values):
trues_indices = _get_trues(predicate_values)
if len(trues_indices) != len(predicate_values):
return None
return trues_indices
class BadGraphStructure(Exception): class BadGraphStructure(Exception):
pass pass
......
import re
import copy
import importlib as imp
from comsdk.graph import Graph, Func, State, Selector
from comsdk.edge import Edge
class Params():
__slots__=(
'module',
'entry_func',
'predicate',
'selector',
'function',
'morphism',
'parallelism',
'comment',
'order',
'subgraph'
)
def __init__(self):
for slot in self.__slots__:
setattr(self, slot, None)
def __str__(self):
stri = ""
for s in self.__slots__:
stri += ((s+": {}, ".format(getattr(self, s))) if getattr(self, s) is not None else "")
return stri
# entities = {}
class GraphFactory():
__slots__ = (
'name',
'states',
'graph',
'issub',
'tocpp',
'entities'
)
def __init__(self, tocpp=False):
self.states = {}
self.entities = {}
self.tocpp = tocpp
self.name = None
self.issub = False
def add_state(self, statename):
if statename not in self.states:
self.states[statename] = State(statename)
if statename in self.entities:
self.states[statename].comment = self.entities[statename].comment
def _create_morphism(self, morphname=None):
comment = ""
if morphname is None:
return Func(), Func(), comment
pred_f, func_f = Func(), Func()
morph = self.entities[morphname]
for m in morph.__slots__:
if getattr(morph,m) is not None:
if m!="predicate" and m!="function" and m!="comment":
raise Exception("ERROR: Morphisms could not have any params exept comment, predicate and function!\n{}".format(morphname))
if m=="comment":
comment=getattr(morph, m).replace("\0", " ")
if m=="predicate":
if getattr(morph,m) not in self.entities:
raise Exception("\tERROR: Predicate {} is not defined!".format(getattr(morph, m)))
pred = self.entities[getattr(morph, m)]
if self.tocpp:
pred_f = Func(pred.module, pred.entry_func, dummy=True, comment=pred.comment)
else:
pred_f = Func(pred.module, pred.entry_func, comment=pred.comment)
if m=="function":
if getattr(morph,m) not in self.entities:
raise Exception("\tERROR: Function: {} is not defined!".format(getattr(morph, m)))
fu = self.entities[getattr(morph, m)]
if self.tocpp:
func_f = Func(fu.module, fu.entry_func, dummy=True, comment=fu.comment)
else:
func_f = Func(fu.module, fu.entry_func,comment=fu.comment)
return pred_f, func_f, comment
def add_connection(self, st1, st2, morphism=None, ordr=0):
pred, entr, comm = self._create_morphism(morphism)
self.states[st1].connect_to(self.states[st2], edge=Edge(pred, entr, order=ordr, comment=comm))
print("{} -> {}".format(st1, st2))
def build(self, nsub):
print("BUILDING {}\nStates:".format(self.name))
for s in self.states:
print("\t"+ s)
if self.issub:
self.graph = Graph(self.states[self.name+str(nsub)+"_"+"__BEGIN__"], self.states[self.name+str(nsub)+"_"+"__END__"])
else:
self.graph = Graph(self.states["__BEGIN__"], self.states["__END__"])
self.graph.init_graph()
if self.issub:
oldkeys = []
for e in self.entities:
oldkeys.append(e)
for old in oldkeys:
if self.entities[old].selector is not None or self.entities[old].subgraph is not None:
self.entities[self.name + str(Parser.subgr_count)+"_"+old] = self.entities[old]
del self.entities[old]
for s in self.states:
if s in self.entities and self.entities[s].selector is not None:
selname = self.entities[s].selector
if self.tocpp:
self.states[s].selector = Selector(len(self.states[s].transfers), self.entities[selname].module, self.entities[selname].entry_func, dummy=True)
else:
self.states[s].selector = Selector(len(self.states[s].transfers), self.entities[selname].module, self.entities[selname].entry_func)
else:
self.states[s].selector = Selector(len(self.states[s].transfers))
if s in self.entities and self.entities[s].subgraph is not None:
print("Replacing state {} with subgraph {}".format(s,self.entities[s].subgraph))
parsr = Parser(subgraph=True, tocpp= self.tocpp)
subgr = parsr.parse_file(self.entities[s].subgraph)
self.states[s].replace_with_graph(subgr)
self.graph = Graph(self.graph.init_state, self.graph.term_state)
return self.graph
class Parser():
__slots__ = (
'fact',
'issub'
)
subgr_count = 0
def __init__(self, tocpp=False, subgraph=False):
self.fact = GraphFactory(tocpp=tocpp)
self.fact.issub = subgraph
self.issub = subgraph
if subgraph:
Parser.subgr_count+=1
def _check_brackets(self, rawfile):
br = { "[":{"line":0, "count":0}, "(":{"line":0, "count":0}, "{":{"line":0, "count":0}, "\"":{"line":0, "count":0}}
line = 1
qu = 0
for char in rawfile:
if char == "[":
br["["]["line"] = line
br["["]["count"] +=1
elif char == "{":
br["{"]["line"] = line
br["{"]["count"] +=1
elif char == "(":
br["("]["line"] = line
br["("]["count"] +=1
elif char == "]":
br["["]["count"] -=1
elif char == "}":
br["{"]["count"] -=1
elif char == ")":
br["("]["count"] -=1
elif char =="\"":
br["\""]["line"] = line
br["\""]["count"] += 1 if br["\""]["count"]==0 else -1
elif char == "\n":
line+=1
expstr= "Brackets or quotes do not match! Missing closing brackets on lines: "
fl = False
for c in br:
if br[c]["count"] != 0:
fl= True
expstr+=str(br[c]["line"])+" "
if fl:
raise Exception(expstr)
def _split_multiple(self,param):
vals = {}
first=True
for s in param.__slots__:
attr = getattr(param,s)
if attr is not None and '\0' in attr:
vals[s] = attr.split('\0')
l=0
for sl in vals:
if l==0:
l=len(vals[sl])
elif l!=len(vals[sl]):
raise Exception("\tERROR: Number of multiple params do not match", l)
res = [copy.copy(param) for i in range(l)]
for sl in vals:
for i, _ in enumerate(res):
setattr(res[i], sl, vals[sl][i])
return res
#Props is line "[proFp=smth, ...]"
def _param_from_props(self,props):
parm = Params()
comment = ""
if props =="":
return parm
props = props.replace("]", '')
if '\"' in props:
m = [m for m in re.finditer(r'\".*\"', props)][0]
comment = props[m.span()[0]+1:m.span()[1]-1]
props=props[:m.span()[0]]+props[m.span()[1]:]
if '(' in props:
mchs = [m for m in re.finditer(r'\((\w+,)*\w+\)', props)]
for m in mchs:
props=props[:m.span()[0]]+(props[m.span()[0]:m.span()[1]]).replace(',','\0')+props[m.span()[1]:]
props = props.replace("(","")
props = props.replace(")","")
rs =props.split(r",") #.split(r", ")
for r in rs:
r=r.split(r"=", 1)
if r[0] in parm.__slots__:
setattr(parm, r[0], r[1])
else:
raise Exception("\tERROR:Unknown parameter: "+ r[0])
if comment != "":
setattr(parm, "comment", comment.replace("\0", " "))
return parm
def _param_from_entln(self, raw):
res = re.split(r"\[", raw, 1)
return res[0], self._param_from_props(res[1])
def _multiple_morphs(self,props, n):
p = self._param_from_props(props)
if p.morphism is None:
return [copy.copy(p) for i in range(n)]
else:
return self._split_multiple(p)
def _topology(self,raw):
spl = re.split(r"\s*(=>|->|\[|\])\s*", raw)
spl = list(filter(lambda x: x!="[" and x!="]" and x!="", spl))
left = spl[0].split(",")
right = spl[2].split(",")
if self.issub:
for i in range(len(left)):
left[i] = self.fact.name + str(Parser.subgr_count) + "_" + left[i]
for i in range(len(right)):
right[i] = self.fact.name + str(Parser.subgr_count) + "_" + right[i]
if (len(left)>1) and (len(right)>1):
raise Exception("ERROR: Ambigious multiple connection in line:\n\t{}".format(raw))
# many to one conection
elif len(left)>1:
if len(spl) < 4:
spl.append("")
morphs = self._multiple_morphs(spl[3], len(left))
if len(morphs)!=len(left):
raise Exception("\tERROR: Count of edges do not match to count of states in many to one connection!\n\t\t{}".format(raw))
self.fact.add_state(right[0])
for i, st in enumerate(left):
self.fact.add_state(st)
self.fact.add_connection(st, right[0], morphs[i].morphism)
# one to many connection, here could be selector
elif len(right)>1:
if len(spl) < 4:
spl.append("")
morphs = self._multiple_morphs(spl[3], len(right))
self.fact.add_state(left[0])
if len(morphs)!=len(right):
raise Exception("\tERROR: Count of edges do not match to count of states in one to many connection!\n\t\t{}".format(raw))
for i, st in enumerate(right):
self.fact.add_state(st)
self.fact.add_connection(left[0], st, morphs[i].morphism, morphs[i].order)
# one to one connection
else:
self.fact.add_state(left[0])
self.fact.add_state(right[0])
if len(spl)==4:
pr =self._param_from_props(spl[3])
self.fact.add_connection(left[0], right[0], pr.morphism, ordr=pr.order if pr.order is not None else 0)
elif len(spl)==3:
self.fact.add_connection(left[0], right[0], None)
def parse_file(self, filename):
# @todo В случае, если на вход будет подан файл в отличной от UTF-8 кодировке программа работать не будет
file = open(filename, encoding='utf-8')# "r")
dot = file.read()
self._check_brackets(dot)
comments = [m for m in re.finditer(r'\".*\"', dot)]
for m in comments:
dot=dot[:m.span()[0]]+(dot[m.span()[0]:m.span()[1]]).replace(' ','\0')+dot[m.span()[1]:]
dot = re.sub(r"[ \t\r]", "", dot) #deleting all spaces
dot = re.sub(r"((digraph)|}|{)", "", dot)
dot = re.sub(r"\/\/.*", "", dot)
dot = re.sub(r"^\n$", "", dot)
dotlines = dot.splitlines()
dotlines = list(filter(None, dotlines))
self.fact.name = dotlines[0]
dotlines = dotlines[1:]
# ent_re - regular expr for edges, states, functions properties
ent_re = re.compile(r"^\w+\[.*\]$")
# top_re - regular expr for topology properties, most time consuming one
top_re = re.compile(r"^(\w+,?)+(->|=>)(\w+,?)+(\[(\w+=(\(?\w+,?\)?)+,?)+\])?")
# (r"^\w[\w\s,]*(->|=>)\s*\w[\w\s,=\[\]()]*$")
for i, ln in enumerate(dotlines):
if ent_re.match(ln):
name, parm = self._param_from_entln(ln)
self.fact.entities[name] = parm
elif top_re.match(ln):
self._topology(ln)
return self.fact.build(Parser.subgr_count)
checked=[]
bushes = {}
selectorends = {}
def generate_cpp(self, filename=None):
self.fact.graph.init_state.input_edges_number =0
states_to_check = [self.fact.graph.init_state]
while len(states_to_check)!=0:
for st in states_to_check:
self.checked.append(st)
states_to_check.remove(st)
bush = _Bush(st)
bush.grow_bush()
self.bushes[st] = bush
for outs in bush.outstates:
if outs not in states_to_check and outs not in self.checked:
states_to_check.append(outs)
send_token(self.fact.graph.init_state, self.bushes, [])
preds, morphs, sels, st, body = print_graph(self.fact.graph.init_state, self.fact.entities, self.bushes)
from mako.template import Template
if filename is not None:
f = open(filename, "w")
else:
f= open(self.fact.name + ".cpp", "w")
print(Template(filename="./cpp/template.cpp").render(preds=preds, morphs = morphs, sels = sels, states=st, body=body), file=f)
def print_graph(cur_state, entities, bushes):
checked = []
toloadpred = []
toloadmorph = []
toloadsel =[]
tocheck = [cur_state]
body = ""
while len(tocheck) !=0:
cur_state=tocheck[0]
cur_b = bushes[cur_state]
cur_b.token+=1
if cur_b.token < cur_b.state.input_edges_number - cur_b.state.looped_edges_number:
tocheck.remove(cur_state)
tocheck.append(cur_state)
continue
if cur_state in checked:
tocheck.remove(cur_state)
continue
if len(cur_b.branches)>1 or len(cur_b.incomes)>1:
body+="{}:\n".format(cur_state.name)
if len(cur_b.incomes)!=0:
if cur_b.state.comment!="" and cur_b.state.comment is not None:
print("STcomm:", cur_b.state.comment)
body+="//"+cur_b.state.comment+"\n"
stri = "false "
for inc in cur_b.incomes:
stri += "|| SEL_{}[{}] ".format(inc["st"].name, inc["i"])
body+="if (!({}))".format(stri)
body+="{\n\tfor (int seli = 0;"+" seli < {};".format(len(cur_state.transfers))+" seli++)\n"+ "\t\tSEL_{}[seli]=false;".format(cur_state.name)+"\n}"
if cur_state.selector.name != "":
# print(cur_state.name, cur_state.selector)
if cur_state.selector not in toloadsel:
toloadsel.append(cur_state.selector)
body+="else {\n"+ "\tSEL_{} = {}(&data);//{}\n".format(cur_state.name, cur_state.selector, cur_state.selector.comment )+"}\n"
else:
body+="else {\n\tfor (int seli = 0;"+" seli < {};".format(len(cur_state.transfers))+" seli++)\n"+"\t\tSEL_{}[seli]=true;".format(cur_state.name)+"\n}\n"
for i, br in enumerate(cur_b.branches):
body+="if (SEL_{}[{}])".format(cur_state.name, i)+"{\n"
if br[len(br)-1].output_state not in tocheck:
tocheck.append(br[len(br)-1].output_state)
if br[len(br)-1].output_state in checked or br[len(br)-1].output_state is cur_state:
stri, toloadpred, toloadmorph = cur_b.cpp_branch(i, toloadpred, toloadmorph)
body+=stri+"\tgoto {};\n".format(br[len(br)-1].output_state.name)+"}\n"
else:
stri, toloadpred, toloadmorph = cur_b.cpp_branch(i, toloadpred, toloadmorph)
body+=stri+"}\n"
tocheck.remove(cur_state)
checked.append(cur_state)
return _unique(toloadpred), _unique(toloadmorph), _unique(toloadsel), checked, body
def _unique(lst):
for i, el in enumerate(lst):
for el2 in lst[i+1:]:
if el2.module == el.module and el2.name == el.name:
lst.remove(el2)
return lst
def send_token(cur_state, bushes, checked):
cur_b = bushes[cur_state]
if cur_state in checked:
return
if len(cur_b.outstates)==0:
return
if len(cur_b.incomes) == cur_b.state.input_edges_number - cur_b.state.looped_edges_number:
checked.append(cur_state)
for i,br in enumerate(cur_b.branches):
bushes[br[len(br)-1].output_state].incomes.append({"st":cur_state, "i":i})
send_token(br[len(br)-1].output_state,bushes, checked)
class _Bush():
__slots__=(
'state',
'selector',
'branches',
'outstates',
'token',
'incomes',
'selectorfin'
)
def __init__(self, state):
self.state = state
self.selector = state.selector
self.branches = []
self.outstates = []
self.token = 0
self.incomes = []
def grow_bush(self):
for t in self.state.transfers:
branch = [t]
self._gen_branch(t.output_state, branch)
def _gen_branch(self, cur_state, branch):
while len(cur_state.transfers)==1 and cur_state.input_edges_number==1:
if cur_state._proxy_state is not None:
cur_state=cur_state._proxy_state
tr = cur_state.transfers[0]
branch.append(tr)
cur_state = tr.output_state
self.branches.append(branch)
if cur_state not in self.outstates:
self.outstates.append(cur_state)
def cpp_branch(self, i, toloadpred, toloadmorph):
res = ""
for tr in self.branches[i]:
edge = tr.edge
if edge.comment!="":
res+="\t//{}\n".format(edge.comment)
if edge.pred_f.name != "":
if edge.pred_f not in toloadpred:
toloadpred.append(edge.pred_f)
res+="\tcheck_pred({}(&data), \"{}\");".format(edge.pred_f, edge.pred_f)
res+="//{}\n".format(edge.pred_f.comment) if edge.pred_f.comment != "" else "\n"
if edge.morph_f.name != "":
if edge.morph_f not in toloadmorph:
toloadmorph.append(edge.morph_f)
res+="\t{}(&data);".format(edge.morph_f)
res+="//{}\n".format(edge.morph_f.comment) if edge.morph_f.comment != "" else "\n"
return res, toloadpred, toloadmorph
...@@ -2,7 +2,7 @@ import os ...@@ -2,7 +2,7 @@ import os
import pickle import pickle
import shutil import shutil
from datetime import datetime, date from datetime import datetime, date
from comsdk.aux import * from comsdk.comaux import *
from comsdk.communication import * from comsdk.communication import *
from comsdk.distributed_storage import * from comsdk.distributed_storage import *
from comsdk.edge import Edge, dummy_predicate from comsdk.edge import Edge, dummy_predicate
......
digraph CODEOBJECT_GENERATOR
{
// ??????????? ???????-????????????
FUNC_1 [module=case_gen_funcs, entry_func=function_1]
FUNC_2 [module=case_gen_funcs, entry_func=function_2]
FUNC_3 [module=case_gen_funcs, entry_func=function_3]
SAVE_TO_DB [module=case_gen_funcs, entry_func=save_to_db]
SAVE_TO_FILE [module=case_gen_funcs, entry_func=save_to_file]
REPEAT [module=case_gen_funcs, entry_func=repeat]
EXIT [module=case_gen_funcs, entry_func=exit]
CREATE_DUMP [module=case_gen_funcs, entry_func=create_dump]
// ??????????? ???????-??????????
PREDICATE_X [module=predicate_funcs, entry_func=predicate_x]
PREDICATE_Y [module=predicate_funcs, entry_func=predicate_y]
SELECTOR [module=predicate_funcs, entry_func=selector]
// ??????????? ??????? ???????? (????????)
EDGE_1 [predicate=PREDICATE_X, function=FUNC_1]
EDGE_2 [predicate=PREDICATE_Y, function=FUNC_2]
EDGE_3 [predicate=PREDICATE_X, function=FUNC_3]
EDGE_4 [predicate=PREDICATE_Y, function=SAVE_TO_DB]
EDGE_5 [predicate=PREDICATE_X, function=SAVE_TO_FILE]
EDGE_6 [predicate=PREDICATE_Y, function=REPEAT]
EDGE_7 [predicate=PREDICATE_X, function=EXIT]
EDGE_8 [function=EXIT]
EDGE_9 [predicate=CHECK_DUMP, function=EXIT]
EDGE_10 [function=CREATE_DUMP]
// ? ???? ??????? ????????? ?????????????????
CONTENT_SUBSTITUTED [parallelism=threading]
// ??????????? ???????? ??????
__BEGIN__ -> INPUT_READY
INPUT_READY -> TEPMLATE_COPIED [morphism=EDGE_1]
TEPMLATE_COPIED -> NAMES_SUBSTITUTED [morphism=EDGE_2]
NAMES_SUBSTITUTED -> CONTENT_SUBSTITUTED [morphism=EDGE_3]
CONTENT_SUBSTITUTED => DUMP_CREATED [morphism=EDGE_10]
CONTENT_SUBSTITUTED -> RESULT_SAVED [morphism=EDGE_4]
CONTENT_SUBSTITUTED -> RESULT_SAVED [morphism=EDGE_5]
// ? ??????????? ?? ?????? ?????????? SELECTOR ?????????????? ??????? ?? ??????? ??? ??????? ?????
RESULT_SAVED -> INPUT_READY, __END__ [selector=SELECTOR, morphism=(EDGE_6, EDGE_7)]
RESULT_SAVED, DUMP_CREATED -> __END__ [morphism=(EDGE_8, EDGE_9)]
}
\ No newline at end of file
#include <iostream>
#include <anymap.h>
extern "C" {
int PrintHello(com::Anymap) {
std::cout<<"Hello!" << std::endl;
return 0;
}
int PrintBye(com::Anymap) {
std::cout<<"Bye!" << std::endl;
return 0;
}
int PrintA(com::Anymap) {
std::cout<<"A" << std::endl;
return 0;
}
int PrintB(com::Anymap) {
std::cout<<"B" << std::endl;
return 0;
}
bool ReturnTrue(){
return true;
}
bool ReturnFalse(){
return false;
}
std::list<bool> ThreeTrue(){
return false;
}
}
\ No newline at end of file
g++ -c -fPIC ./dev/core/anymap.cpp -o anymap.o -I./dev;
g++ -c -fPIC tests.cpp -o tests.o -I./dev;
# g++ -c -fPIC ./dev/iniparser/iniparser.cpp -o iniparser.o -I./dev;
g++ tests.o anymap.o -shared -o libtest.so; rm tests.o anymap.o;
if g++ $1 -o graph.out -I./dev ./dev/core/anymap.cpp -ldl; then
./graph.out;
else
echo "Not Compiled!";
fi;
\ No newline at end of file
#include <libtools.h>
#include <anymap.h>
#include <iniparser.h>
typedef std::function<int(com::Anymap*)> IntFunc;
typedef std::function<bool(com::Anymap*)> BoolFunc;
typedef std::function<bool*(com::Anymap*)> BoolArrFunc;
IntFunc LoadEntry(std::string lib, std::string func) {
DllHandle handler;
return com::lib::loadFunction<int (com::Anymap*), DllHandle>(lib.c_str(), func.c_str(), handler);
}
BoolFunc LoadPred(std::string lib, std::string func) {
DllHandle handler;
return com::lib::loadFunction<int (com::Anymap*), DllHandle>(lib.c_str(), func.c_str(), handler);
}
BoolArrFunc LoadSelector(std::string lib, std::string func){
DllHandle handler;
return com::lib::loadFunction<bool* (com::Anymap*), DllHandle>(lib.c_str(), func.c_str(), handler);
}
void check_pred(bool predval, std::string predname) {
if (!predval) {
std::cout<<"Predicate "<<predname<<" returned FALSE!"<<std::endl;
exit(-1);
}
}
int main(int argc, char const *argv[])
{
auto data = com::Anymap();
//Predicates
% for pred in preds:
auto ${pred} = LoadPred("${pred.module}", "${pred.name}");
% endfor
//Entry functions
% for morph in morphs:
auto ${str(morph)} = LoadEntry("${morph.module}", "${morph.name}");
% endfor
//Selectors
% for sel in sels:
auto ${str(sel)} = LoadSelector("${sel.module}", "${sel.name}");
% endfor
//Branch tokens
bool* SEL_${states[0].name} = new bool[${len(states[0].transfers)}];
std::fill_n(SEL_${states[0].name}, ${len(states[0].transfers)}, true);
% for st in states[1:]:
bool* SEL_${st.name} = new bool[${len(st.transfers)}];
std::fill_n(SEL_${st.name}, ${len(st.transfers)}, false);
% endfor
${body}
TERM:
std::cout<<"Termination!\n";
return 0;
}
\ No newline at end of file
def dummy_edge(data):
pass
def increment_a_edge(data):
data['a'] += 1
def increment_a_array_edge(data):
for i in range(len(data['a'])):
data['a'][i] += 1
def increment_b_edge(data):
data['b'] += 1
def decrement_a_edge(data):
data['a'] -= 1
def nonzero_predicate(data):
return data['a'] != 0
def positiveness_predicate(data):
return data['a'] > 0
def nonpositiveness_predicate(data):
return data['a'] <= 0
def copy_to_c(data):
data['c'] = data['a']
def selector_a_nonpositive(data):
res = data['a'] <= 0
return [res, not res]
def true_predicate(data):
return True
digraph ADD {
FUNC [module=test_funcs.simplest, entry_func=increment_b_edge]
PRED [module=test_funcs.simplest, entry_func=positiveness_predicate]
MORPH [predicate=PRED, function=FUNC, comment="ADD"]
__BEGIN__ -> ST [morphism = MORPH]
ST -> __END__
}
\ No newline at end of file
digraph SIMPLEST {
FUNCA [module=test_funcs.simplest, entry_func=increment_a_edge]
FUNCB [module=test_funcs.simplest, entry_func=increment_b_edge]
PRED [module=test_funcs.simplest, entry_func=true_predicate]
INCR_A [predicate=PRED, function=FUNCA]
INCR_B [predicate=PRED, function=FUNCB]
__BEGIN__ -> ROOT
ROOT -> BR1, BR2 [morphism=(INCR_A, INCR_B)]
BR1 -> BR1_ST [morphism=INCR_A]
BR2 -> BR2_ST [morphism=INCR_B]
BR1_ST, BR2_ST -> MERGE [morphism=(INCR_A, INCR_B)]
MERGE -> __END__
}
\ No newline at end of file
digraph SIMPLEST {
FUNCA [module=test_funcs.simplest, entry_func=increment_a_edge]
PRED [module=test_funcs.simplest, entry_func=true_predicate]
INCR_A [predicate=PRED, function=FUNCA]
ST1 [subgraph=tests/adot/trivial.adot]
ST2 [subgraph=tests/adot/cycled.adot]
ST3 [subgraph=tests/adot/branching.adot]
__BEGIN__ -> ST1
ST1 -> ST2 [morphism=INCR_A]
ST2 -> ST3 [morphism=INCR_A]
ST3 -> __END__
}
\ No newline at end of file
digraph SIMPLEST {
FUNCA [module=libtest, entry_func=IncA]
FUNCB [module=libtest, entry_func=IncB]
CHECKA [module=libtest, entry_func=CheckAEq4]
CHECKB [module=libtest, entry_func=CheckBEq4]
SETA [module=libtest, entry_func=SetAEq1]
SETB [module=libtest, entry_func=SetBEq1]
PASS [module=libtest, entry_func=PassFunc]
PRED [module=libtest, entry_func=PassPred]
INCR_A [predicate=PRED, function=FUNCA]
INCR_B [predicate=PRED, function=FUNCB]
CH_A [predicate=CHECKA, function = PASS]
SET_A [predicate=PRED, function=SETA]
SET_B [predicate=PRED, function=SETB]
CH_B [predicate=CHECKB, function = PASS]
__BEGIN__ -> ROT [morphism=SET_A]
ROT -> ROOT[morphism=SET_B]
ROOT -> BR1, BR2 [morphism=(INCR_A, INCR_B)]
BR1 -> BR1_ST [morphism=INCR_A]
BR2 -> BR2_ST [morphism=INCR_B]
BR1_ST, BR2_ST -> MERGE [morphism=(INCR_A, INCR_B)]
MERGE -> __END__, __END__ [morphism=(CH_A, CH_B)]
}
\ No newline at end of file
digraph SIMPLEST {
FUNCA [module=test_funcs.simplest, entry_func=increment_a_edge]
PRED [module=test_funcs.simplest, entry_func=true_predicate]
INCR_A [predicate=PRED, function=FUNCA]
ST1 [subgraph=tests/adot/cpptrivial.adot]
ST2 [subgraph=tests/adot/cppcycled.adot]
ST3 [subgraph=tests/adot/cppbranching.adot]
__BEGIN__ -> ST1
ST1 -> ST2
ST2 -> ST3
ST3 -> __END__
}
\ No newline at end of file
digraph CYCLED {
SETA [module=libtest, entry_func=SetAEq10]
FUNC [module=libtest, entry_func=DecA]
PRED [module=libtest, entry_func=PassPred]
SET [predicate=PRED, function=SETA]
MORPH [predicate=PRED, function=FUNC]
SEL [module = libtest, entry_func=SelectorA]
ST2 [selector = SEL]
__BEGIN__ -> ST1 [morphism=SET]
ST1 -> ST2 [morphism=MORPH]
ST2 -> ST1 [order=1]
ST2 -> __END__ [order = 2]
}
\ No newline at end of file
digraph SIMPLE {
FUNC [module=libtest, entry_func=IncA]
PRED [module=libtest, entry_func=PassPred]
MORPH [predicate=PRED, function=FUNC]
__BEGIN__ -> ST1 [morphism = MORPH]
ST1 -> ST2 [morphism = MORPH]
ST2 -> __END__ [morphism = MORPH]
}
\ No newline at end of file
digraph CYCLED {
FUNC [module=test_funcs.simplest, entry_func=decrement_a_edge]
PRED [module=test_funcs.simplest, entry_func=true_predicate]
MORPH [predicate=PRED, function=FUNC]
SEL [module = test_funcs.simplest, entry_func = selector_a_nonpositive]
ST2 [selector = SEL]
__BEGIN__ -> ST1
ST1 -> ST2 [morphism=MORPH]
ST2 -> ST1 [order=2]
ST2 -> __END__ [order = 1]
}
\ No newline at end of file
digraph gcdhom_inverted_model_pso
{
// Определение функций-обработчиков
PASS_PROCESSOR [module=libcomsdk, entry_func=pass_processor]
CHECK_PSO_AGENT_REINIT [module=libgcdfes, entry_func=check_pso_agent_reinit, comment="Проверка о необходимости реинициализации отдельной частицы (смещение частицы) в рое в рамках метода роя частиц."]
CHECK_PSO_SWARM_REINIT [module=libgcdfes, entry_func=check_pso_swarm_reinit, comment="Проверка о необходимости реинициализации всего роя частиц в рамках метода роя частиц."]
PSO_AGENT_REINIT [module=libgcdfes, entry_func=pso_agent_reinit, comment="Реинициализация отдельной частицы (смещение частицы) в рое в рамках метода роя частиц."]
PSO_SWARM_REINIT [module=libgcdfes, entry_func=pso_swarm_reinit, comment="Реинициализация всего роя частиц в рамках метода роя частиц."]
PSO_SWARM_ANALYSING [module=libgcdfes, entry_func=pso_swarm_analysing, comment="Анализ всего роя частиц в рамках метода роя частиц."]
PSO_HOM_AGENT_POSTPROC [module=libgcdfes, entry_func=pso_hom_agent_postproc, comment="Постпроцессинг после решения отдельной задачи методом асимптотического осреднения."]
PSO_TASK_DATA_REINIT [module=libgcdfes, entry_func=pso_task_data_reinit, comment="Реинициализация постановки задачи анализа эффективных характеристик КМ методом асимптотического осреднения."]
PSO_AGENT_INIT [module=libgcdfes, entry_func=pso_agent_init, comment="Инициализация отдельной частицы в рамках метода роя частиц."]
PSO_SWARM_INIT [module=libgcdfes, entry_func=pso_swarm_init, comment="Инициализация роя частиц."]
PSO_INIT [module=libgcdfes, entry_func=pso_swarm_init, comment="Инициализация метода роя частиц."]
// Определение функций-предикатов
PASS_PREDICATE [module=libcomsdk, entry_func=pass_predicate]
// Определение морфизмов
PASS_MORPHISM [predicate=PASS_PREDICATE, function=PASS_PROCESSOR, comment="ПАСС, морфизм."]
PSO_AGENT_REINIT_MORPHISM [predicate=PASS_PREDICATE, function=PSO_AGENT_REINIT]
PSO_SWARM_REINIT_MORPHISM [predicate=PASS_PREDICATE, function=PSO_SWARM_REINIT]
PSO_SWARM_ANALYSING_MORPHISM [predicate=PASS_PREDICATE, function=PSO_SWARM_ANALYSING]
PSO_HOM_AGENT_POSTPROC_MORPHISM [predicate=PASS_PREDICATE, function=PSO_HOM_AGENT_POSTPROC]
PSO_TASK_DATA_REINIT_MORPHISM [predicate=PASS_PREDICATE, function=PSO_TASK_DATA_REINIT]
PSO_AGENT_INIT_MORPHISM [predicate=PASS_PREDICATE, function=PSO_AGENT_INIT]
PSO_SWARM_INIT_MORPHISM [predicate=PASS_PREDICATE, function=PSO_SWARM_INIT]
PSO_INIT_MORPHISM [predicate=PASS_PREDICATE, function=PSO_INIT]
// Определение атрибутов узлов
S_1 [subgraph=gcdhom_preprocessor.adot]
S_5 [subgraph=gcdhom_processor.adot]
S_6 [selector=CHECK_PSO_AGENT_REINIT]
S_7 [selector=CHECK_PSO_SWARM_REINIT]
// Определение топологии графовой модели метода конечных элементов
__BEGIN__ -> S_1
S_1 -> S_2 [morphism=PSO_INIT_MORPHISM]
S_2 -> S_3 [morphism=PSO_SWARM_INIT_MORPHISM]
S_3 -> S_4 [morphism=PSO_AGENT_INIT_MORPHISM]
S_4 -> S_5 [morphism=PSO_TASK_DATA_REINIT_MORPHISM]
S_5 -> S_6 [morphism=PSO_HOM_AGENT_POSTPROC_MORPHISM]
S_6 -> S_4, S_7 [morphism=(PSO_AGENT_REINIT_MORPHISM, PSO_SWARM_ANALYSING_MORPHISM), order=(10,20)]
S_7 -> S_4, S_8 [morphism=(PSO_SWARM_REINIT_MORPHISM, PASS_MORPHISM), order=(30,40)]
S_8 -> __END__ [comment = "Расчет завершён."]
}
digraph SIMPLEST {
FUNCA [module=test_funcs.simplest, entry_func=increment_a_edge]
FUNCB [module=test_funcs.simplest, entry_func=increment_b_edge]
PRED [module=test_funcs.simplest, entry_func=positiveness_predicate]
INCR_A [predicate=PRED, function=FUNCA]
INCR_B [predicate=PRED, function=FUNCB]
__BEGIN__ -> ROOT
ROOT -> BR1, BR2, BR3 [morphism=(INCR_A, INCR_A, INCR_A)]
//BR3 -> SIBL3_BR1, SIBL3_BR2 [morphism=(INCR_A, INCR_A)]
//BR2 -> SIBL2_BR1, SIBL2_BR2 [morphism=(INCR_A, INCR_A)]
//SIBL3_BR1 -> SIBL3_BR1_1, SIBL3_BR1_2 [morphism=(INCR_A, INCR_A)]
//SIBL3_BR1_1, SIBL3_BR1_2 -> TERM [morphism=(INCR_A, INCR_A)]
//BR1, SIBL2_BR1, SIBL2_BR2, TERM, SIBL3_BR2 -> __END__ [morphism=(INCR_A, INCR_A, INCR_A, INCR_A, INCR_A)]
BR1, BR2, BR3 -> __END__ [morphism=(INCR_A, INCR_A, INCR_A)]
}
\ No newline at end of file
digraph TEST_SUB {
FUNC [module=test_funcs.simplest, entry_func=increment_a_edge]
PRED [module=test_funcs.simplest, entry_func=positiveness_predicate]
MORPH [predicate=PRED, function=FUNC]
SEL [module=test_funcs.simplest, entry_func=selector_a_nonpositive]
ST2 [subgraph = tests/adot/file.adot]
ST3 [selector = SEL]
__BEGIN__ -> ST1 [morphism = MORPH]
ST1 -> ST2
ST2 -> ST3
ST3 -> __END__
}
\ No newline at end of file
digraph TRIVIAL {
FUNC [module=test_funcs.simplest, entry_func=increment_a_edge]
PRED [module=test_funcs.simplest, entry_func=true_predicate]
MORPH [predicate=PRED, function=FUNC, comment="ADD"]
__BEGIN__ -> ST1 [morphism = MORPH]
ST1 -> ST2 [morphism = MORPH]
ST2 -> __END__ [morphism = MORPH]
}
\ No newline at end of file
...@@ -230,24 +230,30 @@ class GraphGoodCheck(unittest.TestCase): ...@@ -230,24 +230,30 @@ class GraphGoodCheck(unittest.TestCase):
def _get_trivial_parallel_graph(self, initial_conditions): def _get_trivial_parallel_graph(self, initial_conditions):
''' '''
s_1 -> s_2 -> s_3 -> s_6 s_1 -> s_2 -> s_3 ---------> s6s
-> s_4 -> s_5 -> -> s_4 -> s_4_1 -> s_5
-> s_4_2
p_12 = p_24 = p_13 = p_34 := a not 0 p_12 = p_24 = p_13 = p_34 := a not 0
f_12 = f_24 := a + 1 f_12 = f_24 := a + 1
f_13 = f_34 := b + 1 f_13 = f_34 := b + 1
''' '''
s_1 = State('nonparallel_s_1', selection_policy=AllSelectionPolicy()) s_1 = State('nonparallel_s_1')
s_2 = State('parallel_s_2') s_2 = State('parallel_s_2')
s_3 = State('parallel_s_3') s_3 = State('parallel_s_3')
s_4 = State('parallel_s_4') s_4 = State('parallel_s_4')
s_4_1 = State('parallel_s_4_1')
s_4_2 = State('parallel_s_4_2')
s_5 = State('parallel_s_5') s_5 = State('parallel_s_5')
s_6 = State('nonparallel_s_6') s_6 = State('nonparallel_s_6')
s_1.connect_to(s_2, edge=Edge(nonzero_predicate, increment_a_edge)) s_1.connect_to(s_2, edge=Edge(nonzero_predicate, increment_a_edge))
s_2.connect_to(s_3, edge=Edge(nonzero_predicate, increment_a_edge)) s_2.connect_to(s_3, edge=Edge(nonzero_predicate, increment_a_edge))
s_3.connect_to(s_6, edge=Edge(nonzero_predicate, increment_a_edge)) s_3.connect_to(s_6, edge=Edge(nonzero_predicate, increment_a_edge))
s_1.connect_to(s_4, edge=Edge(nonzero_predicate, increment_b_edge)) s_1.connect_to(s_4, edge=Edge(nonzero_predicate, increment_b_edge))
s_4.connect_to(s_5, edge=Edge(nonzero_predicate, increment_b_edge)) s_4.connect_to(s_4_1, edge=Edge(nonzero_predicate, increment_b_edge))
s_4.connect_to(s_4_2, edge=Edge(nonzero_predicate, increment_b_edge))
s_4_1.connect_to(s_5, edge=Edge(nonzero_predicate, increment_b_edge))
s_4_2.connect_to(s_6, edge=Edge(nonzero_predicate, increment_b_edge))
s_5.connect_to(s_6, edge=Edge(nonzero_predicate, increment_b_edge)) s_5.connect_to(s_6, edge=Edge(nonzero_predicate, increment_b_edge))
correct_outputs = [] correct_outputs = []
for ic in initial_conditions: for ic in initial_conditions:
...@@ -434,14 +440,16 @@ class GraphGoodCheck(unittest.TestCase): ...@@ -434,14 +440,16 @@ class GraphGoodCheck(unittest.TestCase):
f_12 := a + 1 f_12 := a + 1
''' '''
pred = Func(func=dummy_predicate)
morph = Func(func=increment_a_edge)
s_1 = State('s_1') s_1 = State('s_1')
s_2 = State('s_2') s_2 = State('s_2')
s_3 = State('s_3') s_3 = State('s_3')
s_1.connect_to(s_2, edge=Edge(dummy_predicate, increment_a_edge)) s_1.connect_to(s_2, edge=Edge(pred, morph))
s_2.connect_to(s_3, edge=Edge(dummy_predicate, increment_a_edge)) s_2.connect_to(s_3, edge=Edge(pred, morph))
sub_s_1 = State('sub_s_1') sub_s_1 = State('sub_s_1')
sub_s_2 = State('sub_s_2') sub_s_2 = State('sub_s_2')
sub_s_1.connect_to(sub_s_2, edge=Edge(dummy_predicate, increment_a_edge)) sub_s_1.connect_to(sub_s_2, edge=Edge(pred, morph))
s_2.replace_with_graph(Graph(sub_s_1, sub_s_2)) s_2.replace_with_graph(Graph(sub_s_1, sub_s_2))
correct_outputs = [] correct_outputs = []
for ic in initial_conditions: for ic in initial_conditions:
......
import unittest
import subprocess
from comsdk.graph import *
from comsdk.parser import Parser
path_to_comsdk = "/home/lbstr/bmstu/comsdk"
path_to_pycomsdk = "/home/lbstr/bmstu/pycomsdk"
class ParserGoodCheck(unittest.TestCase):
def test_trivial_graph(self):
parsr = Parser()
gr = parsr.parse_file("./tests/adot/trivial.adot")
data = {"a": 1}
gr.run(data)
self.assertEqual(data["a"], 4)
def test_branching_graph(self):
parsr = Parser()
gr = parsr.parse_file("./tests/adot/branching.adot")
data = {"a": 1, "b": 1}
gr.run(data)
self.assertEqual(data["a"], 4)
self.assertEqual(data["b"], 4)
def test_cycled_graph(self):
parsr = Parser()
gr = parsr.parse_file("./tests/adot/cycled.adot")
data = {"a": 10}
gr.run(data)
self.assertEqual(data["a"], 0)
def test_complex_graph(self):
parsr = Parser()
gr = parsr.parse_file("./tests/adot/complex.adot")
data = {"a": 1, "b": 1}
gr.run(data)
self.assertEqual(data["a"], 4)
self.assertEqual(data["b"], 4)
def test_cpp_trivial_graph(self):
parsr = Parser(tocpp=True)
gr = parsr.parse_file("./tests/adot/cpptrivial.adot")
parsr.generate_cpp(path_to_comsdk+"res.cpp")
command = "cd "+path_to_comsdk+"; "+path_to_pycomsdk+"/cpp/run.sh "+path_to_comsdk+"res.cpp"
subprocess.check_output(["bash", "-c", command])
def test_cpp_branching_graph(self):
parsr = Parser(tocpp=True)
gr = parsr.parse_file("./tests/adot/cppbranching.adot")
parsr.generate_cpp(path_to_comsdk+"res.cpp")
command = "cd "+path_to_comsdk+"; "+path_to_pycomsdk+"/cpp/run.sh "+path_to_comsdk+"res.cpp"
subprocess.check_output(["bash", "-c", command])
def test_cpp_cycled_graph(self):
parsr = Parser(tocpp=True)
gr = parsr.parse_file("./tests/adot/cppcycled.adot")
parsr.generate_cpp(path_to_comsdk+"res.cpp")
command = "cd "+path_to_comsdk+"; "+path_to_pycomsdk+"/cpp/run.sh "+path_to_comsdk+"res.cpp"
subprocess.check_output(["bash", "-c", command])
def test_cpp_complex_graph(self):
parsr = Parser(tocpp=True)
gr = parsr.parse_file("./tests/adot/cppcomplex.adot")
parsr.generate_cpp(path_to_comsdk+"res.cpp")
command = "cd "+path_to_comsdk+"; "+path_to_pycomsdk+"/cpp/run.sh "+path_to_comsdk+"res.cpp"
subprocess.check_output(["bash", "-c", command])
if __name__ == '__main__':
unittest.main()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment