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 @@
# -*-coding:Utf-8 -*
#==============================================================================
# TENET: Transduction Rule
# TENET: Pattern
#------------------------------------------------------------------------------
# Class to define a Compositional Transduction Rule (CTR), namely a rule
# associating a semantic graph pattern and a semantic net constructor.
# Several methods are proposed to translate the rule into a sequence of SPARQL
# queries applicable to a semantic graph.
# Class to define a pattern to find in a semantic graph. The pattern is
# composed of a list of semantic nets to be extracted from the graph and
# associated with a set of clauses (identification or relational clauses).
#==============================================================================
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
from rdflib import Graph
from rdflib import Namespace
from rdflib.namespace import NamespaceManager
import febTransduction.query_builder as query_builder
import febTransduction.net as net
# -- Useful Constant(s)
DEFAULT_ATTRIBUTE_VALUE = f'\"NA\"'
INDENT_STR = ' '
SENTENCE_REF = '?sentenceRef'
from febTransduction.net.semantic_net_rdf_reference import SemanticNetReferenceHandle
#==============================================================================
# Net Class
# Class
#==============================================================================
class Rule:
""" Class to define a Compositional Transduction Rule (CTR), namely a rule
associating a semantic graph pattern and a semantic net constructor.
class Pattern:
""" Class to define a pattern to find in a semantic graph. The pattern is
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
#--------------------------------------------------------------------------
def __init__(self, label, net):
def __init__(self, *nets):
# -- Base
self.label = label
self.new_net = net
# -- Pattern
self._identification_pattern_dict = {}
self._composition_pattern_list = []
self._restriction_pattern_list = []
# -- SPARQL Query
self.query_list = []
self.label = f' ----- finding'
self.net_list = []
for net in nets:
self.label += f' {net}'
self.net_list.append(f'?{net}')
# -- Reference Handle
self.referenceHandle = SemanticNetReferenceHandle()
#--------------------------------------------------------------------------
# Accessor(s)
#--------------------------------------------------------------------------
# --
# -- Pattern
self._identification_pattern_list = []
self._relation_pattern_list = []
#--------------------------------------------------------------------------
......@@ -74,162 +57,35 @@ class Rule:
#--------------------------------------------------------------------------
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):
self._composition_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))
def add_relation_pattern(self, net_1, relation, net_2):
self._relation_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):
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 apply(self, graph):
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_part = f"\n{INDENT_STR}"
clause_part += f"""# *** Identify variable label of base leaf ***
{nets[0].select_data('base_node')}
{nets[0].base_node} a amr:AMR_Leaf ;
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)
# -- Clause List
clause_list = []
for (attr_predicate, attr_value) in relation_pattern_list:
clause_list.append(f'{self.id} {attr_predicate} {attr_value}.')
for (net_1, relation, net_2) in relation_pattern_list:
clause_list.append(f'{net_1.id} {relation} {net_2.id}.')
# -- Query Generation
compose_query = query_builder.generate_construct_query(construct_part, clause_part)
self.query_list.append((query_label, compose_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)
query_code = query_builder.generate_select_query(select_data_list, clause_list)
query_result = graph.query(test_query)
print('\n' + ' *** - ***')
\ No newline at end of file
return query_result
\ No newline at end of file
......@@ -2,97 +2,167 @@
# -*-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
# 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__':
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))
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):
# -- Rule Initialization
rule_label = '"or" phenomena analysis 1 (targetting class)'
print(f"--- *** February Transduction *** Sequence: {rule_label}")
#logger.info(f"--- *** February Transduction *** Sequence: {rule_label}")
# -- Net Instanciation
property_net = net.PropertyNet(graph)
class_net_0 = net.ClassNet(graph)
phenomena_net = net.PhenomenaNet(graph)
composite_class_net = net.CompositeClassNet(graph)
# -- Selection Pattern Application
query_code = __select_pattern_1()
pattern_set = graph.query(query_code)
# -- Rule Initialization
pattern = transduction.Pattern(class_net_0, 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.apply(graph) # ou class_net_0, property_net, phenomena_net = pattern.apply(graph)
# -- New Net Computing
new_triple_list = []
for selection in pattern_set:
# -- 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
composite_class_net.mother_class = class_net_0
composite_class_net.mother_class = class_net
# etc
# -- Restriction Computation
# TODO
composite_class_net.restriction = restriction
for num in range(1, 9+1):
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
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)
# TODO: à voir si on veut d'autres relations
# -- Finalization
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
def analyze_phenomena_or_2():
#==============================================================================
# Rule with pattern property(property, or_phenomena)
#==============================================================================
# -- Net Instanciation
property_net_0 = net.PropertyNet(0)
property_net_1 = net.PropertyNet(1)
phenomena_net = net.PhenomenaNet()
or_composite_class_net = net.OrCompositeClassNet()
def __select_pattern_2():
# -- Rule Initialization
rule = transduction.Rule('"or" phenomena analysis 2 (targetting property)',
or_composite_class_net)
# -- Select Data List
select_data_list = ['?property_net_0', '?property_net', '?phenomena_net']
# -- Net Composition
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)
# -- Clause List
clause_list = []
clause_list.append(f'?property_net a [rdfs:subClassOf* net:Property_Net].')
clause_list.append(f'?property_net_0 a [rdfs:subClassOf* net:Property_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
# rule.compute_data(mother_class_net=property_net_0.id)
# -- Query Generation
query_code = transduction.query_builder.generate_select_query(select_data_list, clause_list)
# -- Restriction Computation
# TODO
return query_code
# -- Relation Propagation
# TODO
# -- Finalization
# TODO
def analyze_phenomena_or_2():
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__':
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')
rule = analyze_phenomena_or_1()
# rule = analyze_phenomena_or_1()
num = 0
for query_label, query in rule.query_list:
num += 1
print(f'*** query {num} - {query_label} ***\n{query}\n')
# num = 0
# for query_label, query in rule.query_list:
# num += 1
# print(f'*** query {num} - {query_label} ***\n{query}\n')
\ No newline at end of file
This diff is collapsed.
......@@ -9,6 +9,8 @@
import subprocess, os
from rdflib import Graph
from rdflib import Namespace
from rdflib.namespace import NamespaceManager
FILE_PATH = f'{os.path.dirname(os.path.abspath(__file__))}'
INPUT_DIR_PATH = f'{FILE_PATH}/input/'
......@@ -16,7 +18,7 @@ OUTPUT_DIR_PATH = f'{FILE_PATH}/output/'
TEST_GRAPH = f'{INPUT_DIR_PATH}testGraph1.ttl'
from context import tenet
from tenet.febTransduction import query_builder
from tenet.febTransduction import phenomena_application_or
INDENT_STR = ' '
......@@ -41,27 +43,34 @@ print('\n *** Development Test ***')
print(f'\n -- Test Graph Loading')
work_graph = Graph()
work_graph.bind('net', Namespace('https://tenet.tetras-libre.fr/semantic-net#'))
work_graph.parse(TEST_GRAPH)
print(f"----- Graph Loaded ({len(work_graph)})")
print(f'\n -- Test Nets')
property_net = '?property_net'
class_net_0 = '?class_net_0'
phenomena_net = '?phenomena_net'
# print(f'\n -- Test Nets')
# property_net = '?property_net'
# class_net_0 = '?class_net_0'
# phenomena_net = '?phenomena_net'
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')
triple_list = ['net:net1 a net:ClassNet.',
......
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment