Commit e388a4c6 authored by Michele's avatar Michele
Browse files

fixed some perfomance issues, some debug code is still there

parent ceb6037d
......@@ -45,7 +45,7 @@ import helpers.bisimulation as bi
import csv
logging.basicConfig(level=logging.DEBUG)
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
HOST = 'localhost'
......
......@@ -54,7 +54,7 @@ class TicTacToeTeacher(AbstractTeacher):
sys.exit()
#self._socket.setblocking(0)
self._socket.settimeout(0.5) # second timeout, for quiescence
self._socket.settimeout(0.1) # timeout, for quiescence
#logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
......@@ -82,7 +82,7 @@ class TicTacToeTeacher(AbstractTeacher):
# Provide output from current state
def output(self):
ready = select.select([self._socket], [], [], 0.3) # second timeout, for quiescence
ready = select.select([self._socket], [], [], 0.1) # second timeout, for quiescence
output = 'delta'
if ready[0]:
output = self._socket.recv(1024).decode("utf-8")
......
......@@ -81,17 +81,19 @@ 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 *
......@@ -250,42 +252,6 @@ class LearningAlgorithm:
if observation:
self._table.updateEntry(trace, observation=observation)
# # this update function uses teacher.process(trace)
# # in case a InputOutputTeacher is used, outputs in trace are forced to happen
# # this is not realistic, but still useful at the moment.
# def oldUpdateTable(self):
# temp = 0
# tot = 0
# for c in range(200):
# for trace in self._table.getObservableTraces():
# observedOutputs = self._table.getOutputs(trace)
# output = self._teacher.process(trace)
# for i in range(10):
# # try again if retrieving output is unsuccesful
# if output != None:
# break
# output = self._teacher.process(trace)
# tot += 1
# if output != None:
# # Only if trace is a prefix in S, then
# # add trace + output to row (S cdot L_delta)
# if self._table.isInS(trace):
# self._table.addOneLetterExtension(trace, output)
#
# # Update set of outputs for traces where deltas are removed
# for deltaTrace in self._table.getDeltaTraces(trace):
# self._table.updateEntry(deltaTrace, output)
#
# # Add this output to the set of outputs observed after trace
# observedOutputs.add(output)
# else:
# temp += 1
#
# observation = self._oracle.observation(trace, observedOutputs)
# self._table.updateEntry(trace, output, observation)
def _processInputs(self, consecutiveInputs):
if consecutiveInputs != ():
output = self._teacher.oneOutput(consecutiveInputs)
......@@ -299,41 +265,70 @@ class LearningAlgorithm:
def stabilizeTable(self):
# While nothing changes, keep closing and consistent the table
print("Searching closing")
closingRows = self._table.isNotGloballyClosed()
consistentCheck = self._table.isNotGloballyConsistent()
while closingRows or consistentCheck:
while closingRows:
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:
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()
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()
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_")
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 getHypothesis(self, chaos=False):
# If table is not closed, ERROR
if self._table.isNotGloballyClosed():
self._logger.error("Tried to get hypotheses with table not \
closed or not consistent")
self._logger.error("Tried to get hypotheses with table not closed")
return None, None
# Get equivalence classes
rows = self._table.getEquivalenceClasses(chaos)
......@@ -406,7 +401,6 @@ class LearningAlgorithm:
return hyp
# Get all labels enabled after row
# check input enabledness
def _getAllLabels(self, row, outputs):
enabledInputs = self._teacher.getInputAlphabet()
enabledOutputs = self._teacher.getOutputAlphabet()
......@@ -414,8 +408,7 @@ class LearningAlgorithm:
enabledInputs = self._inputPurpose.getEnabled(row, outputs)
if self._outputPurpose != None:
enabledOutputs = self._outputPurpose.getEnabled(row, outputs)
allLabels = enabledInputs.union(enabledOutputs,
set((self._teacher.getQuiescence(),)))
allLabels = enabledInputs.union(enabledOutputs)
return allLabels
# Generate DOT files for hypotheses. hyp = hMinus|hPlus|both
......@@ -446,24 +439,37 @@ 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.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()
self._hPlus = self.getHypothesis(chaos=True)
# 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)
......
......@@ -145,6 +145,8 @@ class Table:
def _isNotClosed(self, chaos=False):
rows = set()
# search in Eq. classes
eqClasses = self.getEquivalenceClasses(chaos)
# TODO: Is there a faster way to check for global closedness
if self._closeStrategy == "First":
for row in self._rows.difference(self._rowsInS):
......@@ -155,8 +157,6 @@ class Table:
continue
found = False
# search in Eq. classes
eqClasses = self.getEquivalenceClasses(chaos)
for rowInS in eqClasses:
if self._moreSpecificRow(rowInS, row, chaos):
# Found a match, exit
......@@ -297,6 +297,8 @@ class Table:
# I do not need to check it again for other loops. Thus past is outside
# the for loop.
past = set()
# get representative of each equivalence class
eqClasses = self.getEquivalenceClasses(chaos)
# filter rows
for row1 in filter(rowsWithQuiescence, self._rowsInS):
row1Extended = th.flatten(row1 + (self._quiescence,), self._quiescence)
......@@ -306,8 +308,6 @@ class Table:
listOfRows = list(filter(moreSpecific(row1Extended), self._rowsInS))
rowsToCheck = set()
# get representative of each equivalence class
eqClasses = self.getEquivalenceClasses(chaos)
for row in eqClasses:
if row in listOfRows:
rowsToCheck.add(row)
......@@ -534,7 +534,7 @@ class Table:
break
# if newColumns:
# # Only one suffix per round, ok?
# # TODO Only one suffix per round, ok?
# break
# if newColumns:
# break
......
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