Commit 73358705 authored by Michele's avatar Michele

added the possibility to provide the experts with the set of outputs after the trace

parent 6b968579
......@@ -34,7 +34,7 @@ class InputPurpose(Purpose):
pass
# Given a trace returns the set of inputs enabled after it.
def getEnabled(self, trace):
def getEnabled(self, trace, outputs):
# If the trace ends with an input, return empty set, Otherwise the
# entire set of inputs
#TODO: can be improved by removing from inputs those already in the trace
......@@ -51,11 +51,14 @@ class OutputPurpose(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:
return set(itertools.product('XO_', repeat=9))
if (outputs != None and len(outputs) > 0):
return outputs
else:
return set(itertools.product('XO_', repeat=9))
......@@ -32,6 +32,7 @@ import sys
import select
import itertools
from teachers.baseteacher import AbstractTeacher
import helpers.deprecator as d
# Teacher for Tic Tac Toe.
class TicTacToeTeacher(AbstractTeacher):
......@@ -58,8 +59,9 @@ class TicTacToeTeacher(AbstractTeacher):
# Reply to a membership/output query
# trace is a list of inputs and or outputs
@d.deprecated
def process(self, trace):
print(ddd)
pass
# reset SUL
# reset = self.reset()
# if not reset:
......
......@@ -342,8 +342,8 @@ class LearningAlgorithm:
self._teacher.getOutputAlphabet().copy(),
self._teacher.getQuiescence(),
chaos)
# if not chaos:
# print(rows)
#if not chaos:
# print(rows)
# assign to each equivalence class a state number
# start with equivalence class of empty trace to 0
assignments = {():0}
......@@ -355,13 +355,15 @@ class LearningAlgorithm:
# add transitions
for row in rows:
allLabels = self._getAllLabels(row)
# TODO reduce allLabels set, use outputExpert
enabledOuptuts = self._table.getOutputs(row)
allLabels = self._getAllLabels(row, enabledOuptuts)
for label in allLabels:
# create row and search it in the table
extension = row + (label,)
# if not chaos:
# print(extension)
#if not chaos:
# print(extension)
if self._table.isInRows(extension):
for target in rows:
found = False
......@@ -407,13 +409,13 @@ class LearningAlgorithm:
# Get all labels enabled after row
# check input enabledness
def _getAllLabels(self, row):
def _getAllLabels(self, row, outputs):
enabledInputs = self._teacher.getInputAlphabet()
enabledOutputs = self._teacher.getOutputAlphabet()
if self._inputPurpose != None:
enabledInputs = self._inputPurpose.getEnabled(row)
enabledInputs = self._inputPurpose.getEnabled(row, outputs)
if self._outputPurpose != None:
enabledOutputs = self._outputPurpose.getEnabled(row)
enabledOutputs = self._outputPurpose.getEnabled(row, outputs)
allLabels = enabledInputs.union(enabledOutputs,
set((self._teacher.getQuiescence(),)))
return allLabels
......
......@@ -52,7 +52,7 @@ class Table:
# _rows also contains empty trace
self._rows = set()
self._rows.add(())
for label in self._inputPurpose.getEnabled(()):
for label in self._inputPurpose.getEnabled((),None):
self._rows.add(tuple(label))
# Define the top part of the table (for closedness)
self._rowsInS = set()
......@@ -61,9 +61,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(()))}
for label in self._possibleInputs(()):
self._entries[tuple(label)] = (set(),self._possibleOutputs(tuple(label)))
self._entries = {():(set(),self._possibleOutputs((), None))}
for label in self._possibleInputs((), None):
self._entries[tuple(label)] = (set(),self._possibleOutputs(tuple(label), None))
# Calculate the preciseness of the table
def preciseness(self):
......@@ -203,10 +203,10 @@ class Table:
def addOneLetterExtensions(self, rows):
modified = False
for row in rows:
for input in self._possibleInputs(row):
if self.addOneLetterExtension(row, input):
modified = True
outputs, observation = self._entries[row]
for my_input in self._possibleInputs(row, outputs):
if self.addOneLetterExtension(row, my_input):
modified = True
for output in outputs:
if self.addOneLetterExtension(row, output):
modified = True
......@@ -334,7 +334,8 @@ class Table:
enabledRow2.add(self._quiescence)
else:
# input enabledness
enabledInputs = self._possibleInputs(current[1])
outputs = self._entries[current[1]][0]
enabledInputs = self._possibleInputs(current[1], outputs)
enabledRow2 = self._entries[current[1]][0].union(enabledInputs)
for label in enabledRow2:
enabledRow1 = set()
......@@ -343,7 +344,8 @@ class Table:
# enabled
enabledRow1.add(self._quiescence)
else:
enabledInputs = self._possibleInputs(current[0])
outputs = self._entries[current[0]][0]
enabledInputs = self._possibleInputs(current[0], outputs)
enabledRow1 = self._entries[current[0]][0].union(enabledInputs)
if label not in enabledRow1:
suffixes = set()
......@@ -551,7 +553,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):
......@@ -684,19 +686,19 @@ 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
def _possibleInputs(self, trace):
def _possibleInputs(self, trace, outputs):
if self._inputPurpose == None:
return self._inputs
else:
return self._inputPurpose.getEnabled(trace)
return self._inputPurpose.getEnabled(trace, outputs)
# Given two entries, check if the former is more specific than the latter
# entry1 ⊑ entry2 => entry2.first is subset of entry1.first and entry1.second is subset of entry2.second
......@@ -713,8 +715,10 @@ class Table:
def _moreSpecificRow(self, row1, row2, plus=False):
# First: if they do not enable the same inputs, they are not in such
# a relation
inputs1 = self._possibleInputs(row1)
inputs2 = self._possibleInputs(row2)
outputs1 = self._entries[th.flatten(row1,self._quiescence)][0]
outputs2 = self._entries[th.flatten(row2,self._quiescence)][0]
inputs1 = self._possibleInputs(row1, outputs1)
inputs2 = self._possibleInputs(row2, outputs2)
if inputs1 != inputs2:
return False
......
......@@ -25,5 +25,5 @@ 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):
pass
......@@ -27,7 +27,7 @@ class InputPurpose(Purpose):
self._inputs = inputs.copy()
# Given a trace returns the set of inputs enabled after it.
def getEnabled(self, trace):
def getEnabled(self, trace, outputs):
return self._inputs
class OutputPurpose(Purpose):
......@@ -36,5 +36,5 @@ class OutputPurpose(Purpose):
self._outputs = outputs.copy()
# Given a trace returns the set of outputs enabled after it.
def getEnabled(self, trace):
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