Commit 076601f8 authored by Michele Volpato's avatar Michele Volpato

fixed error in issue 3, using tuple(label) instead of (label,)

parent 1b76707a
......@@ -42,33 +42,33 @@ from systems.iopurpose import InputPurpose, OutputPurpose
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
inputs = set(['a','b'])
inputs = set(['a','be'])
outputs = set(['x','y'])
quiescence = 'delta'
I1=InputOutputLTS(5, inputs, outputs, quiescence)
I1.addTransition(0,'a',1)
I1.addTransition(0,'a',2)
I1.addTransition(0,'b',0)
I1.addTransition(0,'be',0)
I1.addTransition(1,'a',0)
I1.addTransition(1,'b',3)
I1.addTransition(1,'be',3)
I1.addTransition(2,'a',0)
I1.addTransition(2,'b',3)
I1.addTransition(2,'be',3)
I1.addTransition(2,'x',4)
I1.addTransition(3,'a',0)
I1.addTransition(3,'x',4)
I1.addTransition(3,'b',3)
I1.addTransition(3,'be',3)
I1.addTransition(4,'y',2)
I1.addTransition(4,'b',4)
I1.addTransition(4,'be',4)
I1.addTransition(4,'a',0)
I1.addTransition(4,'x',0)
I1.addTransition(1,'a',0)
I1.addTransition(3,'b',1)
I1.addTransition(3,'a',0)
I1.addTransition(4,'b',2)
I1.addTransition(2,'a',3)
I1.addTransition(4,'y',0)
#I1.addTransition(4,'x',0)
#I1.addTransition(1,'a',0)
#I1.addTransition(3,'b',1)
#I1.addTransition(3,'a',0)
#I1.addTransition(4,'b',2)
#I1.addTransition(2,'a',3)
#I1.addTransition(4,'y',0)
I1.makeInputEnabled()
......@@ -77,7 +77,7 @@ T1 = InputOutputTeacher(I1)
O1 = InputOutputPowerOracle(I1)
outputExpert = OutputPurpose(set(['x','y', quiescence]))
inputExpert = InputPurpose(set(['a','b']))
inputExpert = InputPurpose(set(['a','be']))
tester = RandomTester(T1, 10000, 50)
......
......@@ -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'
......@@ -76,7 +76,7 @@ print("Starting learning...")
#print(T1.oneOutput(('1')))
L = LearningAlgorithm(T1, O1, printPath=path, maxLoops=4,
L = LearningAlgorithm(T1, O1, printPath=path, maxLoops=3,
tablePreciseness=100000, logger=logger, tester=tester, outputPurpose=outputExpert,
inputPurpose=inputExpert)
minus, plus = L.run()
......
......@@ -51,21 +51,21 @@ class TicTacToeOutputPurpose(Purpose):
pass
# Given a trace returns the set of outputs enabled after it.
def getEnabled(self, trace):
def getEnabled(self, trace, outputs):
# If the trace ends with an output, only quiescence is enabled
# TODO improve here
inputs = set(['0','1','2','3','4','5','6','7','8'])
if (trace != None and len(trace) > 0 and trace[-1] not in inputs):
return set(['delta'])
else:
#if (outputs != None and len(outputs) > 0):
# return outputs
#else:
if (outputs != None and len(outputs) > 0):
return outputs
else:
# In this SUL we have many outputs (>4000)
# for this reason we use a placeholder
# We also need a way to compare a set of outputs with the
# placeholder
return set(['PLACEHOLDER'])
return set(['PLACEHOLDER'])
def isIncluded(self, set1, set2):
if 'PLACEHOLDER' in set2:
......
......@@ -46,6 +46,9 @@ class TicTacToeTeacher(AbstractTeacher):
# counter for inputs:
self._count = 0
#logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
#Receiving confirmation from game
data = self._socket.recv(1024)
......@@ -56,10 +59,6 @@ class TicTacToeTeacher(AbstractTeacher):
#self._socket.setblocking(0)
self._socket.settimeout(0.1) # timeout, for quiescence
#logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
# Provide a sequence of inputs (possibly one or even zero) end get an output
# Tic Tac Toe is a mealy machine like game, there is alternation of input and
# output. This must be defined in inputExpert
......
......@@ -408,7 +408,7 @@ class LearningAlgorithm:
if self._inputPurpose != None:
enabledInputs = self._inputPurpose.getEnabled(row)
if self._outputPurpose != None:
enabledOutputs = self._outputPurpose.getEnabled(row)
enabledOutputs = self._outputPurpose.getEnabled(row, outputs)
allLabels = enabledInputs.union(enabledOutputs)
self._logger.debug("enabledInputs: "+ str(enabledInputs))
self._logger.debug("enabledOutputs: "+ str(enabledOutputs))
......
......@@ -53,7 +53,7 @@ class Table:
self._rows = set()
self._rows.add(())
for label in self._possibleInputs(()):
self._rows.add(tuple(label))
self._rows.add((label,))
# Define the top part of the table (for closedness)
self._rowsInS = set()
# Empty trace is always in S
......@@ -64,9 +64,9 @@ class Table:
# _entries is a dictionary (tuple of actions) -> (set(outputs), set(outputs))
# start with the empty sequence of actions and one letter extensions
self._entries = {():(set(),self._possibleOutputs(()))}
self._entries = {():(set(),self._possibleOutputs((), None))}
for label in self._possibleInputs(()):
self._entries[tuple(label)] = (set(),self._possibleOutputs(tuple(label)))
self._entries[tuple(label)] = (set(),self._possibleOutputs(tuple(label), None))
# Calculate the preciseness of the table
def preciseness(self):
......@@ -120,7 +120,6 @@ class Table:
# class belongs to the newly defined equivalence class. If so
# remove it.
# moreSpecific defines a PO set.
# TODO: check this method
rows = set()
for row in self._rowsInS:
found = False
......@@ -165,7 +164,7 @@ class Table:
if self._moreSpecificRow(rowInS, row, chaos):
# Found a match, exit
found = True
break
break #If plus, then we know there is AT LEAST a row in S to go to
# if not found, search in those we are adding now
# Here is the FIRST closing strategy
if not found:
......@@ -258,7 +257,7 @@ class Table:
# add new columns
# and add outputs to the new entry!
self.updateEntry(ce, output)
self._logger.warning("Handling a counterexample: adding column ")#+str(newSuffixes))
self._logger.info("Handling a counterexample: adding column ")#+str(newSuffixes))
return self.addColumn(newSuffixes, force=True)
def addColumn(self, columns, force=False):
......@@ -296,6 +295,7 @@ class Table:
return set()
# TODO: check this method with new algorithm added to thesis
# TODO: chaos_quiescence should not exist anymore
def _isNotReducible(self, chaos=False):
# function used for filtering rows, we want only those which
# have quiescence in their first column
......@@ -315,6 +315,8 @@ class Table:
# moreSpecific than row1Extended,
moreSpecific = lambda x: lambda y: self._moreSpecificRow(y, x, chaos)
listOfRows = list(filter(moreSpecific(row1Extended), self._rowsInS))
# if not chaos, then any of the row in listOfRows is enough,
# if chaos, then I might need to check more
rowsToCheck = set()
for row in eqClasses:
......@@ -328,7 +330,7 @@ class Table:
continue
if (row1, row) in past:
# I already visited this pair. Go to next state enabling quiescence
# I already visited this pair
continue
wait.add((row1, row, ()))
......@@ -339,15 +341,18 @@ class Table:
enabledRow2 = set()
if current[1] == "chaos_quiescence":
self._logger.info("chaos_quiescence 1")
# If we are in chaos_quiescence only quiescence is enabled
enabledRow2.add(self._quiescence)
else:
outputs = self.getOutputs(current[1])
enabledInputs = self._possibleInputs(current[1])
enabledRow2 = outputs.union(enabledInputs)
self._logger.debug("Checking reducibility, enabledRow2: " + str(enabledRow2))
for label in enabledRow2:
enabledRow1 = set()
if current[0] == "chaos_quiescence":
self._logger.info("chaos_quiescence 2")
# If we are in chaos_quiescence only quiescence is
# enabled
enabledRow1.add(self._quiescence)
......@@ -355,6 +360,7 @@ class Table:
outputs = self.getOutputs(current[0])
enabledInputs = self._possibleInputs(current[0])
enabledRow1 = outputs.union(enabledInputs)
self._logger.debug("Checking reducibility, enabledRow1: " + str(enabledRow1))
if label not in enabledRow1:
suffixes = set()
suffixes.add(current[2])
......@@ -366,6 +372,7 @@ class Table:
else:
newRow1 = ""
if current[0] == "chaos_quiescence":
self._logger.info("chaos_quiescence 3")
newRow1 = "chaos_quiescence"
else:
try:
......@@ -386,6 +393,7 @@ class Table:
# send the input to chaotic_delta
if self._entries[current[0] + (label,)] == self._emptyEntry(current[0] + (label,)):
newRow1 = "chaos_quiescence"
self._logger.info("chaos_quiescence 4")
else:
self._logger.error("Quiescence reducibility check: cannot obtain new pair of states. Row1: "
+ str(current[0]) + " label: " + str(label))
......@@ -395,6 +403,7 @@ class Table:
raise
newRow2 = ""
if current[1] == "chaos_quiescence":
self._logger.info("chaos_quiescence 5")
newRow2 = "chaos_quiescence"
else:
try:
......@@ -413,6 +422,7 @@ class Table:
# send the input to chaotic_delta
if self._entries[current[1] + (label,)] == self._emptyEntry(current[1] + (label,)):
newRow2 = "chaos_quiescence"
self._logger.info("chaos_quiescence 16")
else:
self._logger.error("Quiescence reducibility check: cannot obtain new pair of states."
+ " Row2: " + str(current[1]) + " label: " + str(label))
......@@ -582,7 +592,7 @@ class Table:
# get an empty nonfinal entry
def _emptyEntry(self, trace):
return (set(), self._possibleOutputs(trace))
return (set(), self._possibleOutputs(trace, None))
# get an empty final entry
def _emptyFinalEntry(self, trace):
......@@ -690,7 +700,7 @@ class Table:
if trace in self._entries:
return self._entries[trace][1]
else:
return self._possibleOutputs(trace)
return self._possibleOutputs(trace, None)
# Update an entry in the table. If it does not exist, create it
# observation is the answer of the observation oracle
......@@ -718,11 +728,11 @@ class Table:
# given a trace, query outputPurpose for the outputs that are possibly
# enabled after it
def _possibleOutputs(self, trace):
def _possibleOutputs(self, trace, outputs):
if self._outputPurpose == None:
return self._outputs.union(set((self._quiescence,)))
else:
return self._outputPurpose.getEnabled(trace)
return self._outputPurpose.getEnabled(trace, outputs)
# given a trace, query inputPurpose for the inputs that are
# enabled after it
......
......@@ -25,7 +25,7 @@ class Purpose(metaclass=ABCMeta):
# Given a trace, return the set of enabled actions after that trace
@abstractmethod
def getEnabled(self, trace):
def getEnabled(self, trace, outputs = None):
pass
# Given two sets of outputs return True if the first is included in the second.
......
......@@ -36,5 +36,6 @@ class OutputPurpose(Purpose):
self._outputs = outputs.copy()
# Given a trace returns the set of outputs enabled after it.
def getEnabled(self, trace):
# outputs is used when system is deterministic
def getEnabled(self, trace, outputs):
return self._outputs
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