def fill_requirements(concepts_file_path, relations_file_path): concepts = pd.read_csv(concepts_file_path) for _, row in concepts.iterrows(): query = "CREATE (:Requirements:%s {name: '%s'})" % (row['label'], row['concept']) conn.query(query, db=db_name) relations = pd.read_csv(relations_file_path) for _, row in relations.iterrows(): c_1_exists = node_exists(row['concept_1']) c_2_exists = node_exists(row['concept_2']) if c_1_exists and c_2_exists: query = ''' MATCH (a:Requirements {name: '%s'}), (b:Requirements {name: '%s'}) CREATE (a)-[:Requirements {name: '%s'}]->(b) ''' % (row['concept_1'], row['concept_2'], row['relation']) elif c_1_exists: query = ''' MATCH (a:Requirements {name: '%s'}) CREATE (a)-[:Requirements {name: '%s'}]->(:Requirements {name: '%s'}) ''' % (row['concept_1'], row['relation'], row['concept_2']) elif c_2_exists: query = ''' MATCH (a:Requirements {name: '%s'}) CREATE (:Requirements {name: '%s'})-[:Requirements {name: '%s'}]->(a) ''' % (row['concept_2'], row['concept_1'], row['relation']) else: query = ''' CREATE (:Requirements {name: '%s'})-[:Requirements {name: '%s'}]->(:Requirements {name: '%s'}) ''' % (row['concept_1'], row['relation'], row['concept_2']) conn.query(query, db=db_name)
def node_exists(name): q_match = '''MATCH (a {name: '%s'}) RETURN a''' % name q_match_res = conn.query(q_match, db=db_name) if len(q_match_res) == 0: return False else: return True
def get_states(): """Получает все доступные состояния""" query = """ MATCH (code:Development:State), (code)-[:Development {name: 'быть реализацией'}]->(solution) RETURN code.codename, solution.name""" res = conn.query(query, db=db_name) return {dict(r)['code.codename']: dict(r)['solution.name'] for r in res}
def get_condition(s_1, s_2): """Получает условие перехода""" query = """ MATCH (state_1:State {name: '%s'}), (state_2:State {name: '%s'}), (t)-[ {name: 'быть переходом из'}]->(state_1), (t)-[ {name: 'быть переходом в'}]->(state_2), (p)-[ {name: 'быть предикатом перехода'}]->(t), (p_code)-[ {name: 'быть реализацией'}]->(p) RETURN p.name, p_code.codename""" % (s_1, s_2) res = conn.query(query, db=db_name) return dict(res[0])['p_code.codename'], dict(res[0])['p.name']
def get_states_to_transit(state_name): """Получает все связанные состояния с заданным""" query = """ MATCH (state_1:State {name: '%s'}), (state_1)-[ {name: 'переходить в'}]->(state_2), (state_2_dev)-[ {name: 'быть реализацией'}]->(state_2) RETURN state_1.name, state_2.name, state_2_dev.name""" % state_name res = conn.query(query, db=db_name) return {dict(i)['state_2_dev.name']: dict(i)['state_2.name'] for i in res}
def get_operations_after_transition(predicate): """Получает все операции, которые необходимо выполнить после перехода""" query = """ MATCH (pr:Predicate {name: '%s'}), (pr)-[ {name: 'быть предикатом перехода'}]->(t), (t)-[ {name: 'вызывать'}]->(p), (p_code)-[ {name: 'быть реализацией'}]->(p) RETURN p.name as name, p_code.codename as codename, labels(p_code) as labels""" % predicate res = conn.query(query, db=db_name) return query_res_to_df(res)
def get_operations_before_transition(state_name): """Получает все операции, которые необходимо выполнить до перехода""" query = """ MATCH (state_1:State {name: '%s'}), (state_1)-[ {name: 'предшествовать'}]->(process_name), (process_code)-[ {name: 'быть реализацией'}]->(process_name) RETURN process_name.name as name, process_code.codename as codename, labels(process_code) as labels """ % state_name res = conn.query(query, db=db_name) return query_res_to_df(res)
def create_transition( state_1, state_2, # состояния predicate, # условие перехода processes_before_t=[], processes_after_t=[ ] # процессы, запускаемые до и после перехода (могут отсутствовать) ): queries = [] # запрос на добавление концепта перехода transition = 'Переход из состояния «{}» в состояние «{}»'.format( state_1, state_2) queries.append(''' CREATE (t:Solutions:Transition {name: '%s'}) ''' % transition) # запрос на добавление связей: # - между состояниями и переходом # - между переходом и его условием queries.append(''' MATCH (state_1:State {name: '%s'}), (state_2:State {name: '%s'}), (t:Solutions:Transition {name: '%s'}) CREATE (t)-[:Solutions {name: 'быть переходом из'}]->(state_1), (t)-[:Solutions {name: 'быть переходом в'}]->(state_2), (state_1)-[:Solutions {name: 'переходить в'}]->(state_2), (:Solutions:Predicate {name: '%s'})-[:Solutions {name: 'быть предикатом перехода'}]->(t) ''' % (state_1, state_2, transition, predicate)) # добавляем информацию о процессах, запускаемых до перехода if len(processes_before_t) != 0: for p in processes_before_t: if node_exists(p): queries.append(''' MATCH (state_1:State {name: '%s'}), (p {name: '%s'}) SET p:Solutions:Transition CREATE (state_1)-[:Solutions {name: 'предшествовать'}]->(p) ''' % (state_1, p)) if not node_exists(p): queries.append(''' MATCH (state_1:State {name: '%s'}) CREATE (state_1)-[:Solutions {name: 'предшествовать'}]->(:Solutions:Process {name: '%s'}) ''' % (state_1, p)) queries.append(''' MATCH (process:Solutions:Process {name: '%s'}), (t:Solutions:Transition {name: '%s'}) CREATE (process)-[:Solutions {name: 'предшествовать'}]->(t) ''' % (p, transition)) # добавляем информацию о процессах, запускаемых после перехода if len(processes_after_t) != 0: for p in processes_after_t: if node_exists(p): queries.append(''' MATCH (t:Solutions:Transition {name: '%s'}), (p {name: '%s'}) SET p:Solutions:Transition CREATE (t)-[:Solutions {name: 'вызывать'}]->(p) ''' % (transition, p)) if not node_exists(p): queries.append(''' MATCH (t:Solutions:Transition {name: '%s'}) CREATE (t)-[:Solutions {name: 'вызывать'}]->(:Solutions:Process {name: '%s'}) ''' % (transition, p)) queries.append(''' MATCH (process:Solutions:Process {name: '%s'}), (state_2:State {name: '%s'}) CREATE (process)-[:Solutions {name: 'предшествовать'}]->(state_2) ''' % (p, state_2)) # реализация правила логического вывода queries.append(''' MATCH (state_1:State {name: '%s'}), (state_2:State {name: '%s'}), (t:Transition {name: '%s'}), (t)-[:Solutions {name: 'быть переходом из'}]->(state_1), (t)-[:Solutions {name: 'быть переходом в'}]->(state_2), (state_1)-[:Solutions {name: 'предшествовать'}]->(x), (t)-[:Solutions {name: 'вызывать'}]->(y) CREATE (x)-[:Solutions {name: 'предшествовать'}]->(y) ''' % (state_1, state_2, transition)) for query in queries: conn.query(query, db=db_name)
def create_dev_entity( concept, # исходный концепт rel_type, # realization, parameter, call outcoming=True, # направление отношение (исходит из добавляемого концепта) concept_labels=[], real_name='', real_codename='', real_notation=''): if real_name == '': if real_codename != '': real_name = real_codename elif real_notation != '': real_name = real_notation # определение части CYPHER-запроса с информацией о свойствах нового концепта properties = [] if real_name != '': properties.append("name: '{}'".format(real_name)) if real_codename != '': properties.append("codename: '{}'".format(real_codename)) if real_notation != '': properties.append("notation : '{}'".format(real_notation)) properties_str = '' for p in properties: properties_str += (p + ', ') properties_str = properties_str[:-2] # определение части CYPHER-запроса с информацией об отношении между исходным и новым концептами if rel_type == 'realization': rel_str = "{name: 'быть реализацией'}" elif rel_type == 'parameter': rel_str = "{name: 'быть параметром'}" elif rel_type == 'call': rel_str = "{name: 'вызывать'}" else: rel_str = "" # определение части CYPHER-запроса с информацией о лейблах нового концепта labels_str = '' # если тип отношения - быть реализацией, то лейблы наследуется от исходного концепта if rel_type == 'realization': get_query = "MATCH (a {name: '%s'}) RETURN distinct labels(a)" % concept print(concept) res = conn.query(get_query, db=db_name) labels = dict(res[0])['labels(a)'] print(labels) for label in labels: if label not in ['Requirements', 'Solutions', 'Development']: labels_str += ":{}".format(label) if len(concept_labels) != 0: for label in concept_labels: labels_str += ":{}".format(label) if not node_exists(real_name): if outcoming: query = '''MATCH (a {name: '%s'}) CREATE (:Development%s {%s})-[:Development %s]->(a)''' % ( concept, labels_str, properties_str, rel_str) if not outcoming: query = '''MATCH (a {name: '%s'}) CREATE (a)-[:Development %s]->(:Development%s {%s})''' % ( concept, rel_str, labels_str, properties_str) if node_exists(real_name): if outcoming: query = '''MATCH (a {name: '%s'}), (b:Development%s {%s}) CREATE (b)-[:Development %s]->(a)''' % (concept, labels_str, properties_str, rel_str) if not outcoming: query = '''MATCH (a {name: '%s'}), (b:Development%s {%s}) CREATE (a)-[:Development %s]->(b)''' % (concept, labels_str, properties_str, rel_str) conn.query(query, db=db_name)
CREATE (a)-[:Development %s]->(b)''' % (concept, labels_str, properties_str, rel_str) conn.query(query, db=db_name) def get_processes(process_str): res = process_str.split(',') if len(res) == 1 and res[0] == '': return [] else: return [i.strip() for i in res] # создаем базу онтологии conn.query("CREATE OR REPLACE DATABASE %s" % db_name) # добавляем сущности, относящиеся к требованиям fill_requirements('tiler_recs_concepts.csv', 'tiler_recs_relations.csv') # добавляем сущности, относящиеся к проектным решениям (для примера представлен один переход) # create_transition('Движение вперёд', 'Движение вправо', # 'Справа от плиткоукладчика нет уложенных плиток', # processes_before_t=['Укладывание плитки'], # processes_after_t=['Перемещение к следующему плиткоместу']) solutions = pd.read_csv('tiler_solutions.csv') solutions = solutions.fillna('') for _, row in solutions.iterrows(): processes_before_t = get_processes(row['processes_before_t']) processes_after_t = get_processes(row['processes_after_t']) create_transition(row['state_1'],