Commit 7c2e3881 authored by Michele's avatar Michele

removed debug code. Working on learning.py

parent e388a4c6
......@@ -81,19 +81,16 @@ class LearningAlgorithm:
# cannot force it to happen.
def updateTable(self):
# First, try to avoid impossible traces: ask observation query
print("update")
for trace in self._table.getObservableTraces():
observedOutputs = self._table.getOutputs(trace)
observation = self._oracle.observation(trace, observedOutputs)
if observation:
self._table.updateEntry(trace, observation=observation)
print("done observable")
# For all traces for which we did not observed all possible outputs
oTraces = self._table.getObservableTraces()
trie = th.make_trie(oTraces)
print("asking "+str(len(oTraces))+" membership queries")
# Until we tried K times with no results, where K is the number of
# observable traces times the number of outputs (including quiescence)
K = len(oTraces) * 35 # (len(self._teacher.getOutputAlphabet()) + 1) # TODO comment from *
......@@ -264,11 +261,15 @@ class LearningAlgorithm:
def stabilizeTable(self):
# While nothing changes, keep closing and consistent the table
print("Searching closing")
# While nothing changes, keep closing and making the table consistent
closingRows = self._table.isNotGloballyClosed()
if not closingRows:
if self._makeConsistent():
self.updateTable()
closingRows = self._table.isNotGloballyClosed()
while closingRows:
print("Not closed")
self._logger.debug("Table is not closed")
self._logger.debug(closingRows)
self._table.promote(closingRows)
......@@ -281,49 +282,23 @@ class LearningAlgorithm:
closingRows = self._table.isNotGloballyClosed()
if not closingRows:
print("Searching consistent")
consistentCheck = self._table.isNotGloballyConsistent()
# Table is closed, check for consistency
if consistentCheck:
print("Not consistent")
self._logger.debug("Table is not consistent")
self._logger.debug(consistentCheck)
self._table.addColumn(consistentCheck, force=True)
if self._logger.isEnabledFor(logging.DEBUG):
self._table.printTable(prefix="_i_")
if self._makeConsistent():
self.updateTable()
closingRows = self._table.isNotGloballyClosed()
#
# while closingRows or consistentCheck:
# while closingRows:
# print("Not closed")
# self._logger.debug("Table is not closed")
# self._logger.debug(closingRows)
# self._table.promote(closingRows)
# # After promoting one should check if some one letter
# # extensions should also be added
# self._table.addOneLetterExtensions(closingRows)
# if self._logger.isEnabledFor(logging.DEBUG):
# self._table.printTable(prefix="_c_")
# self.updateTable()
# closingRows = self._table.isNotGloballyClosed()
# consistentCheck = self._table.isNotGloballyConsistent()
# # Table is closed, check for consistency
# if consistentCheck:
# print("Not consistent")
# self._logger.debug("Table is not consistent")
# self._logger.debug(consistentCheck)
# self._table.addColumn(consistentCheck, force=True)
# if self._logger.isEnabledFor(logging.DEBUG):
# self._table.printTable(prefix="_i_")
# # TODO: is an update needed here? in theory, when I encounter
# # an inconsistency, by adding a column, the interesting row
# # will immediately make the table not closed, no need of
# # update, right?
# #self.updateTable()
# closingRows = self._table.isNotGloballyClosed()
# consistentCheck = self._table.isNotGloballyConsistent()
def _makeConsistent(self):
consistentCheck = self._table.isNotGloballyConsistent()
# Table is closed, check for consistency
if consistentCheck:
self._logger.debug("Table is not consistent")
self._logger.debug(consistentCheck)
self._table.addColumn(consistentCheck, force=True)
if self._logger.isEnabledFor(logging.DEBUG):
self._table.printTable(prefix="_i_")
return True
else:
return False
def getHypothesis(self, chaos=False):
# If table is not closed, ERROR
......@@ -339,16 +314,26 @@ class LearningAlgorithm:
chaos)
# assign to each equivalence class a state number
# start with equivalence class of empty trace to 0
assignments = {():0}
# TODO: is () always the representative of an equivalence class?
# NO
rowForEmpty = ()
# search for the representative for ()
for row in rows:
# TODO: the method of table called at next line is
# private. Change to public, or add a public version
if self._table._moreSpecificRow(row, rowForEmpty, chaos):
rowForEmpty = row
break
assignments = {rowForEmpty:0}
count = 1
for row in rows:
if row != ():
if row != rowForEmpty:
assignments[row] = count
count = count + 1
# add transitions
for row in rows:
# TODO reduce allLabels set, use outputExpert
enabledOuptuts = self._table.getOutputs(row)
allLabels = self._getAllLabels(row, enabledOuptuts)
......@@ -356,16 +341,15 @@ class LearningAlgorithm:
# create row and search it in the table
extension = row + (label,)
if self._table.isInRows(extension):
found = False
for target in rows:
found = False
# TODO: the method of table called at next line is
# private. Change to public, or add a public version
if self._table._moreSpecificRow(extension, target, chaos):
if self._table._moreSpecificRow(target, extension, chaos):
hyp.addTransition(assignments[row], label,
assignments[target])
found = True
break
# do not break here, for hPlus we add nondeterminism here
if not found:
self._logger.warning("Chaotic behaviour")
# Either the table is not closed, or
......@@ -377,7 +361,7 @@ class LearningAlgorithm:
if label in self._teacher.getInputAlphabet():
hyp.addTransition(assignments[row], label,
hyp.getChaosDelta())
# TODO: getPossibleOutputs is deprecated
elif label in self._table.getPossibleOutputs(row):
hyp.addTransition(assignments[row], label,
hyp.getChaos())
......@@ -439,37 +423,27 @@ class LearningAlgorithm:
self._currentLoop = self._currentLoop + 1
self._logger.info("Learning loop number " + str(self._currentLoop))
# Fill the table and make it closed and consistent
print("Updating")
self.updateTable() # TODO learning sometimes stops here!
print("Stabilizing")
self.updateTable()
self.stabilizeTable()
print("Stabilized")
# Is the table quiescence reducible? If not make it so and
# then fill it again, make it closed and consitent
print("Reducing")
newSuffixes = self._table.isNotQuiescenceReducible()
while (newSuffixes or not self._table.isStable()):
print("Something to reduce")
if newSuffixes:
self._logger.debug("Table is not quiescence reducible")
self._logger.debug(newSuffixes)
if self._table.addColumn(newSuffixes, force=True):
if self._logger.isEnabledFor(logging.DEBUG):
self._table.printTable(prefix="_Q_")
print("Update in reduce")
self.updateTable()
print("Stabilize after reducing")
self.stabilizeTable()
print("Reducing again")
newSuffixes = self._table.isNotQuiescenceReducible()
print("Done reducing")
self._hMinus = self.getHypothesis()
# If there are no observable traces, hMinus == hPlus
if self._table.getObservableTraces() != set():
self._hPlus = self.getHypothesis(chaos=True)
else:
self._hPlus = self._hMinus
print("Hyp created")
if self._printPath != None:
self.generateDOT(path=self._printPath)
......
......@@ -675,11 +675,10 @@ class Table:
return outputs
# Return the set of outputs that can be observed after trace
# TODO: not clear the purpose of this method. rename?
@d.deprecated
# Return the second set.
def getPossibleOutputs(self, trace):
if trace in self._entries and self._entries[trace][1]:
return self._entries[trace][0]
if trace in self._entries:
return self._entries[trace][1]
else:
return self._possibleOutputs(trace, None)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment