Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
Michele Volpato
Alnos
Commits
2573e7f7
Commit
2573e7f7
authored
Oct 28, 2015
by
Michele
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added deprecator, started working on more specific for closedness
parent
3612b6db
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
69 additions
and
18 deletions
+69
-18
examples/learn.py
examples/learn.py
+2
-2
helpers/deprecator.py
helpers/deprecator.py
+24
-0
learning/learning.py
learning/learning.py
+1
-1
learning/observationtable.py
learning/observationtable.py
+42
-15
No files found.
examples/learn.py
View file @
2573e7f7
...
...
@@ -12,7 +12,7 @@ import helpers.bisimulation as bi
from
testing.randomtesting
import
RandomTester
from
systems.iopurpose
import
InputPurpose
,
OutputPurpose
logging
.
basicConfig
(
level
=
logging
.
DEBUG
)
logging
.
basicConfig
(
level
=
logging
.
INFO
)
logger
=
logging
.
getLogger
(
__name__
)
inputs
=
set
([
'a'
,
'b'
])
...
...
@@ -52,7 +52,7 @@ O1 = InputOutputPowerOracle(I1)
outputExpert
=
OutputPurpose
(
set
([
'x'
,
'y'
,
quiescence
]))
inputExpert
=
InputPurpose
(
set
([
'a'
,
'b'
]))
tester
=
RandomTester
(
T1
,
10000
,
2
0
)
tester
=
RandomTester
(
T1
,
10000
,
5
0
)
currentdir
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
inspect
.
getfile
(
inspect
.
currentframe
())))
...
...
helpers/deprecator.py
0 → 100644
View file @
2573e7f7
import
logging
logged
=
False
def
deprecated
(
func
):
"""This is a decorator which can be used to mark functions
as deprecated. It will result in a warning being emmitted
when the function is used."""
def
new_func
(
*
args
,
**
kwargs
):
# Log only once for each run
global
logged
if
not
logged
:
#warnings.simplefilter('always', DeprecationWarning) #turn off filter
print
(
"Warning: Call to deprecated function {}."
.
format
(
func
.
__name__
))
#warnings.warn("Call to deprecated function {}.".format(func.__name__), category=DeprecationWarning, stacklevel=2)
#warnings.simplefilter('default', DeprecationWarning) #reset filter
logged
=
True
return
func
(
*
args
,
**
kwargs
)
new_func
.
__name__
=
func
.
__name__
new_func
.
__doc__
=
func
.
__doc__
new_func
.
__dict__
.
update
(
func
.
__dict__
)
return
new_func
learning/learning.py
View file @
2573e7f7
...
...
@@ -345,7 +345,7 @@ class LearningAlgorithm:
found
=
False
# TODO: the method of table called at next line is
# private. Change to public, or add a public version
if
self
.
_table
.
_
rowEquality
(
extension
,
target
,
chaos
):
if
self
.
_table
.
_
moreSpecificRow
(
extension
,
target
,
chaos
):
hyp
.
addTransition
(
assignments
[
row
],
label
,
assignments
[
target
])
found
=
True
...
...
learning/observationtable.py
View file @
2573e7f7
...
...
@@ -3,6 +3,7 @@ import os, inspect
from
itertools
import
combinations
,
product
import
logging
import
helpers.traces
as
th
import
helpers.deprecator
as
d
class
Table
:
...
...
@@ -69,6 +70,7 @@ class Table:
return
trace
in
self
.
_rows
# Given two rows, check if they belong to the same equivalence class
@
d
.
deprecated
def
_rowEquality
(
self
,
row1
,
row2
,
withObservation
=
False
):
for
column
in
self
.
_columns
:
entry1
=
th
.
flatten
(
row1
+
column
,
self
.
_quiescence
)
...
...
@@ -87,14 +89,14 @@ class Table:
return
False
return
True
def
getEquivalenceClasses
(
self
,
withObservation
=
False
):
def
getEquivalenceClasses
(
self
,
plus
=
False
):
# () is always in the equivalence classes
rows
=
set
()
rows
.
add
(())
for
row
in
self
.
_rowsInS
-
set
(()):
found
=
False
for
singleRow
in
rows
:
if
self
.
_
rowEquality
(
row
,
singleRow
,
withObservation
):
if
self
.
_
moreSpecificRow
(
row
,
singleRow
,
plus
):
found
=
True
break
if
not
found
:
...
...
@@ -116,7 +118,7 @@ class Table:
found
=
False
# search in S
for
rowInS
in
self
.
_rowsInS
:
if
self
.
_
rowEquality
(
row
,
row
InS
,
True
):
if
self
.
_
moreSpecificRow
(
row
InS
,
row
,
True
):
# Found a match, exit
found
=
True
break
...
...
@@ -124,7 +126,7 @@ class Table:
# Here is the FIRST closing strategy
if
not
found
:
for
newRow
in
rows
:
if
self
.
_
rowEquality
(
row
,
newR
ow
,
True
):
if
self
.
_
moreSpecificRow
(
newRow
,
r
ow
,
True
):
# already added this equivalence class
found
=
True
break
...
...
@@ -196,12 +198,12 @@ class Table:
return
self
.
addColumn
(
newSuffixes
,
force
=
True
)
# return the length of the longest suffix in columns
def
getLengthColumns
(
self
):
length
=
0
for
item
in
self
.
_columns
:
if
len
(
item
)
>
length
:
length
=
len
(
item
)
return
length
#
def getLengthColumns(self):
#
length = 0
#
for item in self._columns:
#
if len(item) > length:
#
length = len(item)
#
return length
def
addColumn
(
self
,
columns
,
force
=
False
):
if
force
:
...
...
@@ -252,8 +254,8 @@ class Table:
for
row1
in
filter
(
rowsWithQuiescence
,
self
.
_rowsInS
):
row1Extended
=
row1
+
(
self
.
_quiescence
,)
# filter for rows in top part of the table that are
#
equivalent to
row1Extended
equivalentRows
=
lambda
x
:
lambda
y
:
self
.
_
rowEquality
(
x
,
y
,
chaos
)
#
moreSpecific than
row1Extended
equivalentRows
=
lambda
x
:
lambda
y
:
self
.
_
moreSpecificRow
(
x
,
y
,
chaos
)
row2
=
next
(
filter
(
equivalentRows
(
row1Extended
),
self
.
_rowsInS
))
if
row1
==
row2
:
...
...
@@ -308,6 +310,8 @@ class Table:
# the first entry is emptyEntry.
# In this case (it can only be an input) we
# send the input to chaotic_delta
# Old code, prior to _moreSpecificRow
if
self
.
_entries
[
current
[
0
]
+
(
label
,)]
==
self
.
_emptyEntry
(
current
[
0
]
+
(
label
,)):
newRow1
=
"chaos_quiescence"
else
:
...
...
@@ -365,12 +369,12 @@ class Table:
newColumns
=
set
()
for
row1
,
row2
in
combi
:
# If the rows are in the same equivalence class
if
self
.
_
rowEquality
(
row1
,
row2
,
chaos
):
if
self
.
_
moreSpecificRow
(
row1
,
row2
,
chaos
):
for
label
in
labels
:
rowExt1
=
row1
+
(
label
,)
rowExt2
=
row2
+
(
label
,)
if
rowExt1
in
self
.
_rows
and
rowExt2
in
self
.
_rows
:
# I could call self._
rowEquality
() but then
# I could call self._
moreSpecificRow
() but then
# I need to iterate again to find the suffix.
# It is better to do it directly.
for
column
in
self
.
_columns
:
...
...
@@ -396,7 +400,7 @@ class Table:
break
if
newColumns
:
# TODO: only one suffix per round, ok?
break
break
if
newColumns
:
break
...
...
@@ -580,6 +584,29 @@ class Table:
else
:
return
self
.
_inputPurpose
.
getEnabled
(
trace
)
# Given two entries, check if the former is more specific than the latter
def
_moreSpecificEntry
(
self
,
entry1
,
entry2
,
plus
):
if
not
plus
:
#return entry1 == entry2
return
entry2
[
0
].
issubset
(
entry1
[
0
])
else
:
#return entry1[0] == entry2[0]
return
(
entry2
[
0
].
issubset
(
entry1
[
0
])
and
entry1
[
1
].
issubset
(
entry2
[
1
]))
# Given two rows, check if the former is more specific than the latter
def
_moreSpecificRow
(
self
,
row1
,
row2
,
plus
=
False
):
for
column
in
self
.
_columns
:
entry1
=
th
.
flatten
(
row1
+
column
,
self
.
_quiescence
)
entry2
=
th
.
flatten
(
row2
+
column
,
self
.
_quiescence
)
if
entry1
not
in
self
.
_entries
and
entry2
not
in
self
.
_entries
:
return
True
elif
entry1
not
in
self
.
_entries
or
entry2
not
in
self
.
_entries
:
return
False
if
not
self
.
_moreSpecificEntry
(
self
.
_entries
[
entry1
],
self
.
_entries
[
entry2
],
plus
):
return
False
return
True
# Print table, for test
def
printTable
(
self
,
path
=
None
,
prefix
=
""
):
if
path
==
None
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment