-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMoteur.py
154 lines (121 loc) · 5.84 KB
/
Moteur.py
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
from Datatypes import Element, Rule, ConcreteRule, Hypothesis, VariableTypes, Constraint, EnumElem, Boolean, OperatorTypes
from Context import Context
import logging
import copy
from typing import Optional
# TODO : résoudre le cassage du chainage avant
class Moteur(object):
def __init__(self, context: Context):
self.context = context
def inputFact(self, fact: Element):
self.context.addFact(fact)
# self.saturateBase()
def inputRule(self, rule: Rule):
self.context.addRule(rule)
# try:
# self.context.checkRulesCoherence()
# self.saturateBase()
# except RuleCoherenceException as r:
# logging.error(r)
# self.rules.pop()
def inputHypothesis(self, hypothese: Hypothesis):
self.context.addHypothesis(hypothese)
#crée une metaregle à partir de son nom et du nom de ses rêgles
def createMetarule(self, rule_name : str, rule_list : list[str], ordered : bool = False, order_type : str = ""):
self.context.addMetarule(rule_name, rule_list, ordered, order_type)
# sature les rêgles afin de déduire la plus grande base de faits possible
def chainageAvant(self, objectives: Hypothesis) -> Context:
if objectives is None:
logging.warning("Aucun objectif donné, saturation de la base de faits")
objectives = Hypothesis("default",
[ConcreteRule([Constraint(Boolean("unsatisfiable_default_constraint", True), OperatorTypes.EQUALS)], [], "unsatisfiable")])
return_context: Context = Context()
simulation_context: Context = copy.deepcopy(self.context)
# print("simulation context :")
# print(simulation_context)
# print("return_context :")
# print(return_context)
res = True
while simulation_context.rule_list != [] and res and not objectives.satisfy(simulation_context.facts):
ajout = Moteur.trouverCorrespondanceRegle(simulation_context.facts ,simulation_context.rule_list)
if ajout is None:
res = False
else:
[(simulation_context.addFact(copy.copy(fact)), return_context.addFact(copy.copy(fact))) for fact in
ajout[0].consequence]
return_context.addRule(ajout[0])
simulation_context.removeRule(ajout[1])
# print("simulation context :")
# print(simulation_context)
# print("return_context :")
# print(return_context)
if not objectives.satisfy(simulation_context.facts):
print("------ OBJECTIF NON ATTEINT -----")
else :
print("--- OBJECTIF ATTEINT ---")
return return_context
# cherche une rêgle afin d'étendre la base de faits
# renvoie un tuple (index_regle, [faits_deduits]) ou None
def trouverCorrespondanceRegle(base_de_faits : list[Element], base_de_regles : list[Rule]) -> Optional[tuple[ConcreteRule, str]]:
"""Match rule"""
for regle in base_de_regles:
ret = regle.satisfy(base_de_faits)
if ret:
return ret
return None
def satisfaction_regle(base_de_faits: list, regle: Rule):
for element in regle.premisse:
if element in base_de_faits:
continue
else:
return False
return True
def chainageArriere(self, hypotheses_: Hypothesis) -> list[tuple[Constraint, Context, bool]]:
hypotheses: list[Constraint] = []
return_context: list[tuple[Constraint, Context, bool]] = []
for rule in hypotheses_.rules:
hypotheses.append(rule.premisse[0])
# liste les hypothèses
for hypothesis in hypotheses:
context = self.recChainageArriere(hypothesis, (Context(), True))
return_context.append((hypothesis, context[0], context[1]))
return return_context
def recChainageArriere(self, hypothesis: Constraint, return_context: tuple[Context, bool]) -> tuple[Context, bool]:
found_rule = self.trouverRegleConcluante(
hypothesis, list(self.context.facts.values()), list(self.context.rules.values()))
if found_rule:
true_hypothesis = True
for premisse in found_rule[0].premisse:
# if list(self.context.facts.values()).count(premisse.elem) == 0:
if not self.faitConnu(premisse.elem, list(self.context.facts.values())):
return_context = self.recChainageArriere(premisse, return_context)
if not return_context[1]:
true_hypothesis = False
break
if true_hypothesis:
for premisse in found_rule[0].premisse:
return_context[0].addFact(premisse.elem)
return_context[0].addRule(found_rule[0])
return return_context[0], True
return return_context[0], False
def faitConnu(self, researched_fact: Element, facts: [Element]):
for fact in facts:
if fact.equal(researched_fact):
return True
return False
def trouverRegleConcluante(self, hypothesis: Constraint, facts: list[Element], rules: list[Rule]):
"""Match rule"""
for rule in rules:
found_rule = rule.concludes(hypothesis.elem)
if found_rule:
conflict = False
for fact in facts:
if fact.conflicts(found_rule[0].consequence):
conflict = True
if not conflict:
for premisse in found_rule[0].premisse:
if premisse.elem.conflicts(list(self.context.facts.values())):
conflict = True
if not conflict:
return found_rule
return None