Skip to content
Snippets Groups Projects
Commit 9431756b authored by Aurélien Lamercerie's avatar Aurélien Lamercerie
Browse files

Development of febTransduction (in progress)

parent 9570e61b
No related branches found
No related tags found
No related merge requests found
from .pattern import Pattern
\ No newline at end of file
...@@ -2,71 +2,54 @@ ...@@ -2,71 +2,54 @@
# -*-coding:Utf-8 -* # -*-coding:Utf-8 -*
#============================================================================== #==============================================================================
# TENET: Transduction Rule # TENET: Pattern
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# Class to define a Compositional Transduction Rule (CTR), namely a rule # Class to define a pattern to find in a semantic graph. The pattern is
# associating a semantic graph pattern and a semantic net constructor. # composed of a list of semantic nets to be extracted from the graph and
# Several methods are proposed to translate the rule into a sequence of SPARQL # associated with a set of clauses (identification or relational clauses).
# queries applicable to a semantic graph.
#============================================================================== #==============================================================================
if __name__ == '__main__':
import os, sys
LIB_PATH = f'{os.path.dirname(os.path.abspath(__file__))}/..'
sys.path.insert(0, os.path.abspath(LIB_PATH))
print(sys.path[0])
import logging import logging
from rdflib import Graph
from rdflib import Namespace
from rdflib.namespace import NamespaceManager
import febTransduction.query_builder as query_builder import febTransduction.query_builder as query_builder
import febTransduction.net as net import febTransduction.net as net
# -- Useful Constant(s) from febTransduction.net.semantic_net_rdf_reference import SemanticNetReferenceHandle
DEFAULT_ATTRIBUTE_VALUE = f'\"NA\"'
INDENT_STR = ' '
SENTENCE_REF = '?sentenceRef'
#============================================================================== #==============================================================================
# Net Class # Class
#============================================================================== #==============================================================================
class Rule: class Pattern:
""" Class to define a Compositional Transduction Rule (CTR), namely a rule """ Class to define a pattern to find in a semantic graph. The pattern is
associating a semantic graph pattern and a semantic net constructor. composed of a list of semantic nets to be extracted from the graph and
associated with a set of clauses (identification or relational clauses).
""" """
#--------------------------------------------------------------------------
# Class Attributes
#--------------------------------------------------------------------------
# None
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
# Constructor # Constructor
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
def __init__(self, label, net): def __init__(self, *nets):
# -- Base # -- Base
self.label = label self.label = f' ----- finding'
self.new_net = net self.net_list = []
for net in nets:
# -- Pattern self.label += f' {net}'
self._identification_pattern_dict = {} self.net_list.append(f'?{net}')
self._composition_pattern_list = []
self._restriction_pattern_list = []
# -- SPARQL Query
self.query_list = []
# -- Reference Handle
self.referenceHandle = SemanticNetReferenceHandle()
#-------------------------------------------------------------------------- # -- Pattern
# Accessor(s) self._identification_pattern_list = []
#-------------------------------------------------------------------------- self._relation_pattern_list = []
# --
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
...@@ -74,162 +57,35 @@ class Rule: ...@@ -74,162 +57,35 @@ class Rule:
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
def add_identification_pattern(self, net, **net_attribute): def add_identification_pattern(self, net, **net_attribute):
self._identification_pattern_dict[net] = net.identify_attribute(**net_attribute) for attr_ref in net_attribute.keys():
attr_predicate = self.referenceHandle.get_predicate(attr_ref)
attr_value = net_attribute.get(attr_ref)
self._identification_pattern_list.append(())
def add_composition_pattern(self, net_1, relation, net_2): def add_relation_pattern(self, net_1, relation, net_2):
self._composition_pattern_list.append((net_1, relation, net_2)) self._relation_pattern_list.append((net_1, relation, net_2))
def add_restriction_pattern(self, net_1, relation, net_2):
self._restriction_pattern_list.append((net_1, relation, net_2))
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
# Method(s) to construct a new semantic net by composition of net(s) # Pattern Application Method
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
def __define_identification_clause(self, *nets): def apply(self, graph):
clause_part = f"\n{INDENT_STR}"
clause_part += f"# -- Identify Net(s)"
for net in nets:
clause_part += f"\n{INDENT_STR}"
clause_part += net.identify()
if net in self._identification_pattern_dict:
clause_part += self._identification_pattern_dict[net]
return clause_part
def __define_pattern_clause(self):
clause_part = f"\n{INDENT_STR}"
clause_part += f"# -- Identify Pattern "
for (net_1, relation, net_2) in self._composition_pattern_list:
clause_part += f"\n{INDENT_STR}"
clause_part += f'{net_1.id} {relation} {net_2.id}.'
return clause_part
def __define_tracking_data_selection_clause(self, *nets):
clause_part = f"\n{INDENT_STR}"
clause_part += f"# -- Data Selection "
for net in nets:
clause_part += f"\n{INDENT_STR}"
clause_part += net.select_tracking_data()
return clause_part
def __define_new_net_binding_clause(self, *nets): # -- Select Data List
select_data_list = []
for net in net_list:
select_data_list.append(net.id)
assert len(nets) > 0, '__define_new_net_binding_clause impossible without net' # -- Clause List
clause_list = []
clause_part = f"\n{INDENT_STR}" for (attr_predicate, attr_value) in relation_pattern_list:
clause_part += f"""# *** Identify variable label of base leaf *** clause_list.append(f'{self.id} {attr_predicate} {attr_value}.')
{nets[0].select_data('base_node')} for (net_1, relation, net_2) in relation_pattern_list:
{nets[0].base_node} a amr:AMR_Leaf ; clause_list.append(f'{net_1.id} {relation} {net_2.id}.')
amr:hasVariable ?variable.
?variable amr:label ?varLabel."""
clause_part += f"\n\n{INDENT_STR}"
clause_part += f"# -- Naming Binding \n{INDENT_STR}"
clause_part += self.new_net.bind_naming(*nets)
clause_part += f"\n\n{INDENT_STR}"
clause_part += f"# -- URI Binding"
clause_part += self.new_net.bind_uri(self.new_net.naming, '?varLabel')
return clause_part
def __define_new_net(self):
construct_part = f"\n{INDENT_STR}"
construct_part += f'# -- New net \n'
construct_part += self.new_net.define()
return construct_part
def __define_composition(self, *nets):
construct_part = f"\n{INDENT_STR}"
construct_part += f'# -- Composition Tracking for {self.new_net.id}'
main = True
for net in nets:
construct_part += f"\n{INDENT_STR}"
construct_part += self.new_net.track_composante(net, main)
main = False
return construct_part
def __define_deprecate_net(self, *nets):
if (nets is not None) & (len(nets) != 0):
construct_part = f'\n{INDENT_STR}'
construct_part += f'# -- Deprecate net \n{INDENT_STR}'
construct_part += f'{nets[0].id} a net:Deprecated_Net.'
return construct_part
def compose(self, *nets):
query_label = 'new net construction'
# -- Clause Part
clause_part = ''
clause_part += self.__define_identification_clause(*nets)
clause_part += '\n'
clause_part += self.__define_pattern_clause()
clause_part += '\n'
clause_part += self.__define_tracking_data_selection_clause(*nets)
clause_part += '\n'
clause_part += self.__define_new_net_binding_clause(*nets)
# -- Construct Part
construct_part = ''
construct_part += self.__define_new_net()
construct_part += self.__define_composition(*nets)
construct_part += self.__define_deprecate_net(*nets)
# -- Query Generation # -- Query Generation
compose_query = query_builder.generate_construct_query(construct_part, clause_part) query_code = query_builder.generate_select_query(select_data_list, clause_list)
self.query_list.append((query_label, compose_query)) query_result = graph.query(test_query)
#==============================================================================
# Development Test
#==============================================================================
if __name__ == '__main__':
print('\n' + ' *** Development Test ***')
# print('\n' + ' -- Net Definition')
property_net_0 = net.PropertyNet(0)
property_net_1 = net.PropertyNet(1)
phenomena_net = net.PhenomenaNet()
or_composite_class_net = net.OrCompositeClassNet()
# print('\n' + ' -- Test Rule 1')
rule = Rule('Test Rule', or_composite_class_net)
rule.add_identification_pattern(phenomena_net, phenomena_type='amr:phenomena_conjunction_or')
rule.add_composition_pattern(property_net_1, 'amr:role_ARG0', property_net_0)
rule.add_composition_pattern(property_net_1, 'amr:role_ARG1', phenomena_net)
rule.compose(property_net_0, property_net_1, phenomena_net)
rule.compute_data()
num = 0
for query_label, query in rule.query_list:
num += 1
print(f'*** query {num} - {query_label} ***\n{query}\n')
# print('\n' + ' -- load a rule definition from a dictionary')
# rule.load_dict(rule_def_1)
# print(rule)
# print('\n' + ' -- load a prefix list')
# rule.load_prefix_list(prefix_list_1)
# print(rule)
# print('\n' + ' -- get the SPARQL query')
# query = rule.get_query()
# print(query)
print('\n' + ' *** - ***') return query_result
\ No newline at end of file \ No newline at end of file
...@@ -2,97 +2,167 @@ ...@@ -2,97 +2,167 @@
# -*-coding:Utf-8 -* # -*-coding:Utf-8 -*
#============================================================================== #==============================================================================
# TENET: AMR CTR at 'Net Expansion' level # TENET: AMR CTR at 'Net Expansion' level for phenomena application (or)
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# Module grouping compositional transduction rule_sets (CTR) for the analysis # Module grouping compositional transduction rule_sets (CTR) for the analysis
# of AMR structures, at 'Net Expansion' level # of AMR structures, at 'Net Expansion' level
#============================================================================== #==============================================================================
import subprocess, os
from rdflib import Graph
from rdflib import Namespace
from rdflib.namespace import NamespaceManager
if __name__ == '__main__': if __name__ == '__main__':
import os, sys import os, sys
LIB_PATH = f'{os.path.dirname(os.path.abspath(__file__))}/../../..' LIB_PATH = f'{os.path.dirname(os.path.abspath(__file__))}/..'
sys.path.insert(0, os.path.abspath(LIB_PATH)) sys.path.insert(0, os.path.abspath(LIB_PATH))
print(sys.path[0]) print(sys.path[0])
import febTransduction as transduction
from febTransduction.query_builder import generate_select_query
#============================================================================== #==============================================================================
# Rule to analyze conjunction phenomena # Rule with pattern property(class, or_phenomena)
#============================================================================== #==============================================================================
def __select_pattern_1():
# -- Select Data List
select_data_list = ['?property_net', '?class_net', '?phenomena_net']
# -- Clause List
clause_list = []
clause_list.append(f'?property_net a [rdfs:subClassOf* net:Property_Net].')
clause_list.append(f'?class_net a [rdfs:subClassOf* net:Class_Net].')
clause_list.append(f'?phenomena_net a [rdfs:subClassOf* net:Phenomena_Net].')
clause_list.append(f'?phenomena_net net:hasPhenomenaType amr:phenomena_conjunction_or.')
clause_list.append(f'?property_net amr:role_ARG0 ?class_net.')
clause_list.append(f'?property_net amr:role_ARG1 ?phenomena_net.')
# -- Query Generation
query_code = transduction.query_builder.generate_select_query(select_data_list, clause_list)
return query_code
# pattern = transduction.Pattern('class_net', 'property_net', 'phenomena_net')
# pattern.add_identification_pattern(phenomena_net, phenomena_type='amr:phenomena_conjunction_or')
# pattern.add_composition_pattern(property_net, 'amr:role_ARG0', class_net_0)
# pattern.add_composition_pattern(property_net, 'amr:role_ARG1', phenomena_net)
# pattern_query = pattern.get_select_query()
# return pattern_query
def __op_pattern_1(phenomena_net_uri, num):
assert 1 <= num <= 9
# -- Select Data List
select_data_list = ['?class_net']
# -- Clause List
clause_list = []
clause_list.append(f'?class_net a [rdfs:subClassOf* net:Class_Net].')
clause_list.append(f'{phenomena_net_uri} amr:role_op{num} ?class_net.')
# -- Query Generation
query_code = transduction.query_builder.generate_select_query(select_data_list, clause_list)
return query_code
def __define_restriction(net, op_set): # TODO
pass
return net
def analyze_phenomena_or_1(graph): def analyze_phenomena_or_1(graph):
# -- Rule Initialization
rule_label = '"or" phenomena analysis 1 (targetting class)' rule_label = '"or" phenomena analysis 1 (targetting class)'
print(f"--- *** February Transduction *** Sequence: {rule_label}") print(f"--- *** February Transduction *** Sequence: {rule_label}")
#logger.info(f"--- *** February Transduction *** Sequence: {rule_label}") #logger.info(f"--- *** February Transduction *** Sequence: {rule_label}")
# -- Net Instanciation # -- Selection Pattern Application
property_net = net.PropertyNet(graph) query_code = __select_pattern_1()
class_net_0 = net.ClassNet(graph) pattern_set = graph.query(query_code)
phenomena_net = net.PhenomenaNet(graph)
composite_class_net = net.CompositeClassNet(graph)
# -- Rule Initialization # -- New Net Computing
pattern = transduction.Pattern(class_net_0, property_net, phenomena_net) new_triple_list = []
pattern.add_identification_pattern(phenomena_net, phenomena_type='amr:phenomena_conjunction_or') for selection in pattern_set:
pattern.add_composition_pattern(property_net, 'amr:role_ARG0', class_net_0)
pattern.add_composition_pattern(property_net, 'amr:role_ARG1', phenomena_net)
pattern.apply(graph) # ou class_net_0, property_net, phenomena_net = pattern.apply(graph)
# -- Net Composition # -- Net Composition
composite_class_net.compose(class_net_0, property_net, phenomena_net) class_net = net.ClassNet(graph, selection.class_net)
property_net = net.PropertyNet(graph, selection.property_net)
phenomena_net = net.PhenomenaNet(graph, selection.phenomena_net)
composite_class_net = net.CompositeClassNet(graph)
composite_class_net.compose(class_net, property_net, phenomena_net)
# -- Data Computation # -- Data Computation
composite_class_net.mother_class = class_net_0 composite_class_net.mother_class = class_net
# etc # etc
# -- Restriction Computation # -- Restriction Computation
# TODO for num in range(1, 9+1):
composite_class_net.restriction = restriction query_code = __op_pattern_1(selection.phenomena_net, num)
op_set = graph.query(query_code)
composite_class_net = __define_restriction(composite_class_net, op_set)
# -- Relation Propagation # -- Relation Propagation
for (n1, rel, _) in class_net_0.input_relation_list: for (n1, rel, _) in class_net.input_relation_list:
composite_class_net.add_input_relation(n1, rel) composite_class_net.add_input_relation(n1, rel)
# TODO: à voir si on veut d'autres relations # TODO: à voir si on veut d'autres relations
# -- Finalization # -- Finalization
composite_class_net.finalize() composite_class_net.finalize()
new_triple_list = composite_class_net.generate_triple_definition() new_triples = composite_class_net.generate_triple_definition()
new_triple_list.append(new_triples)
return rule_label, new_triple_list return rule_label, new_triple_list
def analyze_phenomena_or_2(): #==============================================================================
# Rule with pattern property(property, or_phenomena)
#==============================================================================
# -- Net Instanciation def __select_pattern_2():
property_net_0 = net.PropertyNet(0)
property_net_1 = net.PropertyNet(1)
phenomena_net = net.PhenomenaNet()
or_composite_class_net = net.OrCompositeClassNet()
# -- Rule Initialization # -- Select Data List
rule = transduction.Rule('"or" phenomena analysis 2 (targetting property)', select_data_list = ['?property_net_0', '?property_net', '?phenomena_net']
or_composite_class_net)
# -- Net Composition # -- Clause List
rule.add_identification_pattern(phenomena_net, phenomena_type='amr:phenomena_conjunction_or') clause_list = []
rule.add_composition_pattern(property_net_1, 'amr:role_ARG0', property_net_0) clause_list.append(f'?property_net a [rdfs:subClassOf* net:Property_Net].')
rule.add_composition_pattern(property_net_1, 'amr:role_ARG1', phenomena_net) clause_list.append(f'?property_net_0 a [rdfs:subClassOf* net:Property_Net].')
rule.compose(property_net_0, property_net_1, phenomena_net) clause_list.append(f'?phenomena_net a [rdfs:subClassOf* net:Phenomena_Net].')
clause_list.append(f'?phenomena_net net:hasPhenomenaType amr:phenomena_conjunction_or.')
clause_list.append(f'?property_net amr:role_ARG0 ?property_net_0.')
clause_list.append(f'?property_net amr:role_ARG1 ?phenomena_net.')
# -- Data Computation # -- Query Generation
# rule.compute_data(mother_class_net=property_net_0.id) query_code = transduction.query_builder.generate_select_query(select_data_list, clause_list)
# -- Restriction Computation return query_code
# TODO
# -- Relation Propagation
# TODO
# -- Finalization def analyze_phenomena_or_2():
# TODO
return rule # -- Rule Initialization
rule_label = '"or" phenomena analysis 2 (targetting class)'
print(f"--- *** February Transduction *** Sequence: {rule_label}")
# -- Selection Pattern Application
query_code = __select_pattern_2()
pattern_set = graph.query(query_code)
# -- New Net Computing
new_triple_list = []
for selection in pattern_set:
pass
return rule_label, new_triple_list
...@@ -104,11 +174,43 @@ if __name__ == '__main__': ...@@ -104,11 +174,43 @@ if __name__ == '__main__':
print('\n' + ' *** Development Test ***') print('\n' + ' *** Development Test ***')
print(f'\n -- Test Graph Loading')
graph = Graph()
graph.bind('net', Namespace('https://tenet.tetras-libre.fr/semantic-net#'))
graph.parse('testGraph1.ttl')
print(f"----- Graph Loaded ({len(graph)})")
print('\n -- Select Pattern Application 1')
query_code = __select_pattern_1()
print(query_code)
pattern_result_set = graph.query(query_code)
print(f'\n ----- number of selection found: {len(pattern_result_set)}')
for selection in pattern_result_set:
result_str = f'>>> '
result_str += f'{selection.property_net.n3(graph.namespace_manager)}'
result_str += f' {selection.class_net.n3(graph.namespace_manager)}'
result_str += f' {selection.phenomena_net.n3(graph.namespace_manager)}'
print(result_str)
print('\n -- Select Pattern Application 2')
query_code = __select_pattern_2()
print(query_code)
pattern_result_set = graph.query(query_code)
print(f'\n ----- number of selection found: {len(pattern_result_set)}')
for selection in pattern_result_set:
result_str = f'>>> '
result_str += f'{selection.property_net.n3(graph.namespace_manager)}'
result_str += f' {selection.property_net_0.n3(graph.namespace_manager)}'
result_str += f' {selection.phenomena_net.n3(graph.namespace_manager)}'
print(result_str)
print('\n -- Rule') print('\n -- Rule')
rule = analyze_phenomena_or_1() # rule = analyze_phenomena_or_1()
num = 0 # num = 0
for query_label, query in rule.query_list: # for query_label, query in rule.query_list:
num += 1 # num += 1
print(f'*** query {num} - {query_label} ***\n{query}\n') # print(f'*** query {num} - {query_label} ***\n{query}\n')
\ No newline at end of file
This diff is collapsed.
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
import subprocess, os import subprocess, os
from rdflib import Graph from rdflib import Graph
from rdflib import Namespace
from rdflib.namespace import NamespaceManager
FILE_PATH = f'{os.path.dirname(os.path.abspath(__file__))}' FILE_PATH = f'{os.path.dirname(os.path.abspath(__file__))}'
INPUT_DIR_PATH = f'{FILE_PATH}/input/' INPUT_DIR_PATH = f'{FILE_PATH}/input/'
...@@ -16,7 +18,7 @@ OUTPUT_DIR_PATH = f'{FILE_PATH}/output/' ...@@ -16,7 +18,7 @@ OUTPUT_DIR_PATH = f'{FILE_PATH}/output/'
TEST_GRAPH = f'{INPUT_DIR_PATH}testGraph1.ttl' TEST_GRAPH = f'{INPUT_DIR_PATH}testGraph1.ttl'
from context import tenet from context import tenet
from tenet.febTransduction import query_builder from tenet.febTransduction import phenomena_application_or
INDENT_STR = ' ' INDENT_STR = ' '
...@@ -41,27 +43,34 @@ print('\n *** Development Test ***') ...@@ -41,27 +43,34 @@ print('\n *** Development Test ***')
print(f'\n -- Test Graph Loading') print(f'\n -- Test Graph Loading')
work_graph = Graph() work_graph = Graph()
work_graph.bind('net', Namespace('https://tenet.tetras-libre.fr/semantic-net#'))
work_graph.parse(TEST_GRAPH) work_graph.parse(TEST_GRAPH)
print(f"----- Graph Loaded ({len(work_graph)})") print(f"----- Graph Loaded ({len(work_graph)})")
print(f'\n -- Test Nets') # print(f'\n -- Test Nets')
property_net = '?property_net' # property_net = '?property_net'
class_net_0 = '?class_net_0' # class_net_0 = '?class_net_0'
phenomena_net = '?phenomena_net' # phenomena_net = '?phenomena_net'
print(f'\n -- Select Query Test') print(f'\n -- Select Query Test')
select_data_list = [class_net_0, property_net, phenomena_net]
composition_pattern_list = []
composition_pattern_list.append((property_net, 'amr:role_ARG0', class_net_0))
composition_pattern_list.append((property_net, 'amr:role_ARG1', phenomena_net))
clause_list = define_clause_list(composition_pattern_list)
test_query = query_builder.generate_select_query(select_data_list, clause_list)
print(test_query)
query_result = work_graph.query(test_query)
for row in query_result:
print(f"{row.class_net_0} - {row.property_net} - {row.phenomena_net} ")
# select_data_list = [class_net_0, property_net, phenomena_net]
# composition_pattern_list = []
# composition_pattern_list.append((property_net, 'amr:role_ARG0', class_net_0))
# composition_pattern_list.append((property_net, 'amr:role_ARG1', phenomena_net))
# clause_list = define_clause_list(composition_pattern_list)
# test_query = query_builder.generate_select_query(select_data_list, clause_list)
# print(test_query)
# query_result = work_graph.query(test_query)
pattern_result_set = phenomena_application_or.apply_or_phenomena_pattern_1(work_graph)
print(f'\n *** Select Result ***')
for selection in pattern_result_set:
result_str = f'>>> '
result_str += f'{selection.class_net_0.n3(work_graph.namespace_manager)}'
result_str += f' {selection.property_net.n3(work_graph.namespace_manager)}'
result_str += f' {selection.phenomena_net.n3(work_graph.namespace_manager)}'
print(result_str)
print(f'\n -- Insert Query Test') print(f'\n -- Insert Query Test')
triple_list = ['net:net1 a net:ClassNet.', triple_list = ['net:net1 a net:ClassNet.',
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment