File size: 2,788 Bytes
5d05c8b
c6c39e9
 
 
 
 
 
 
 
 
 
 
5d05c8b
c6c39e9
 
5d05c8b
 
c6c39e9
 
 
 
 
 
 
 
 
 
5d05c8b
 
c6c39e9
5d05c8b
c6c39e9
 
5d05c8b
 
c6c39e9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5d05c8b
c6c39e9
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
"""
MODULE INFERENCE ENGINE
=======================
Deductions ajoutees au graphe RDF apres ingestion. Chaque regle est EXPLICITE :
elle s'appuie sur le predicat que la feuille Ontology associe a une colonne precise,
jamais sur une devinette par nom de predicat.

- montant_net   : montant total du du pret (colonne Montant_Total, version courante —
                  les versions Prets_Update sont deja fusionnees dans Prets_Master).
                  Repli sur Montant_Capital si la feuille ne mappe pas Montant_Total.
- statut_risque : "HighValue" quand montant_net depasse SEUIL_HIGH_VALUE.
- a_emprunteur  : relation inverse de possede_pret, si ce predicat existe.
"""
from rdflib import Literal, Namespace
from rdflib.namespace import RDF, XSD

VORTEX = Namespace("http://vortex.ai/ontology#")
SEUIL_HIGH_VALUE = 100000


def _predicat_pour_colonne(regles, colonne):
    """(classe, predicat) de la regle data_property qui lit `colonne`, sinon None."""
    for r in regles or []:
        if str(r.get("ObjectColOrConcept", "")).strip() == colonne and str(r.get("ObjectType", "")).strip().lower() == "data_property":
            return str(r.get("SubjectClass", "")).strip(), str(r.get("Predicate", "")).strip()
    return None


class InferenceEngine:
    def __init__(self, rdf_store, regles=None):
        self.rdf_store = rdf_store
        self.regles = regles or []
        self.journal = []   # [(regle, triplets ajoutes | message)]

    def run_inference(self):
        g = self.rdf_store.g
        source = _predicat_pour_colonne(self.regles, "Montant_Total") or _predicat_pour_colonne(self.regles, "Montant_Capital")
        if source:
            classe, predicat = source
            ajouts = 0
            for sujet in g.subjects(RDF.type, VORTEX[classe]):
                for valeur in g.objects(sujet, VORTEX[predicat]):
                    try:
                        montant = float(valeur)
                    except (TypeError, ValueError):
                        continue
                    g.set((sujet, VORTEX.montant_net, Literal(montant, datatype=XSD.decimal)))
                    ajouts += 1
                    if montant > SEUIL_HIGH_VALUE:
                        g.set((sujet, VORTEX.statut_risque, Literal("HighValue")))
                    break
            self.journal.append((f"montant_net = {classe}.{predicat}", ajouts))
        else:
            self.journal.append(("montant_net", "ignorée : aucune règle Ontology ne lit Montant_Total ni Montant_Capital"))

        ajouts = 0
        for client, pret in list(g.subject_objects(VORTEX.possede_pret)):
            g.add((pret, VORTEX.a_emprunteur, client))
            ajouts += 1
        self.journal.append(("a_emprunteur = inverse de possede_pret", ajouts))
        return self.journal