Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
SimRA
Manage
Activity
Members
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Model registry
Analyze
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Guilhem Gamard
SimRA
Commits
500c61ff
Commit
500c61ff
authored
5 years ago
by
Guilhem Gamard
Browse files
Options
Downloads
Patches
Plain Diff
First draft
parent
35425efa
No related branches found
No related tags found
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
simra.py
+35
-45
35 additions, 45 deletions
simra.py
with
35 additions
and
45 deletions
simra.py
+
35
−
45
View file @
500c61ff
#!/usr/bin/env python3
#!/usr/bin/env python3
import
collections
from
collections
import
deque
import
copy
from
copy
import
deep
copy
from
functools
import
reduce
from
functools
import
reduce
from
itertools
import
count
from
itertools
import
count
import
tkinter
as
TK
import
tkinter
as
TK
...
@@ -8,6 +8,19 @@ import tkinter as TK
...
@@ -8,6 +8,19 @@ import tkinter as TK
# ################################################################
# ################################################################
# General utilities
# General utilities
class
Gensym
:
"""
Poor man
'
s closure to generate unique names.
"""
def
__init__
(
self
,
prefix
=
"
g
"
,
seq
=
count
()):
self
.
prefix
=
prefix
self
.
seq
=
seq
def
__call__
(
self
):
return
"
{}{}
"
.
format
(
self
.
prefix
,
next
(
self
.
seq
))
gensym
=
Gensym
()
# gensym() returns successively "g0", "g1", "g2", etc.
def
dict_filter
(
dictionary
,
keys
):
def
dict_filter
(
dictionary
,
keys
):
"""
"""
Return a subdictionary of `dictionary` comprising only the given `keys`.
Return a subdictionary of `dictionary` comprising only the given `keys`.
...
@@ -21,6 +34,9 @@ def integers(n):
...
@@ -21,6 +34,9 @@ def integers(n):
return
list
(
range
(
n
))
return
list
(
range
(
n
))
def
flatten
(
l
):
def
flatten
(
l
):
"""
Given a list of list, return the list of elements of sublists.
"""
return
[
item
for
sublist
in
l
for
item
in
sublist
]
return
[
item
for
sublist
in
l
for
item
in
sublist
]
# ################################################################
# ################################################################
...
@@ -32,6 +48,7 @@ class Node:
...
@@ -32,6 +48,7 @@ class Node:
Constructor fields:
Constructor fields:
name -- Any hashable value, used for printing and identification
name -- Any hashable value, used for printing and identification
(must be unique inside an AN or all hell breaks loose)
update_func -- Update Function; it must take one parameter: a dictionary
update_func -- Update Function; it must take one parameter: a dictionary
mapping name of neighbours to their values
mapping name of neighbours to their values
dependencies -- List of dependency names (other nodes
'
names)
dependencies -- List of dependency names (other nodes
'
names)
...
@@ -40,7 +57,6 @@ class Node:
...
@@ -40,7 +57,6 @@ class Node:
Other fields:
Other fields:
state -- Curent value of the node
state -- Curent value of the node
"""
"""
def
__init__
(
self
,
name
,
update_func
=
None
,
dependencies
=
[],
init_state
=
0
):
def
__init__
(
self
,
name
,
update_func
=
None
,
dependencies
=
[],
init_state
=
0
):
self
.
name
=
name
self
.
name
=
name
self
.
update_func
=
update_func
self
.
update_func
=
update_func
...
@@ -55,8 +71,7 @@ class Node:
...
@@ -55,8 +71,7 @@ class Node:
self
.
dependencies
.
append
(
new_dependency
)
self
.
dependencies
.
append
(
new_dependency
)
def
update
(
self
,
neigh_vals
):
def
update
(
self
,
neigh_vals
):
f
=
self
.
update_func
self
.
state
=
self
.
update_func
(
neigh_vals
)
self
.
state
=
f
(
neigh_vals
)
def
__repr__
(
self
):
def
__repr__
(
self
):
return
"
{{node {}: {}}}
"
.
format
(
self
.
name
,
self
.
state
)
return
"
{{node {}: {}}}
"
.
format
(
self
.
name
,
self
.
state
)
...
@@ -90,11 +105,11 @@ class AN:
...
@@ -90,11 +105,11 @@ class AN:
written to `_nodes`.
written to `_nodes`.
"""
"""
def
__init__
(
self
,
nodes
=
{},
update_mode
=
[],
history_len
=
10
):
def
__init__
(
self
,
nodes
=
{},
update_mode
=
[],
history_len
=
10
0
):
self
.
nodes
=
nodes
self
.
nodes
=
nodes
self
.
update_mode
=
update_mode
self
.
update_mode
=
update_mode
self
.
up
=
0
self
.
up
=
0
self
.
history
=
collections
.
deque
(
maxlen
=
history_len
)
self
.
history
=
deque
(
maxlen
=
history_len
)
# ################################################################
# ################################################################
...
@@ -138,7 +153,7 @@ class AN:
...
@@ -138,7 +153,7 @@ class AN:
@history_len.setter
@history_len.setter
def
history_len
(
self
,
new_history_len
):
def
history_len
(
self
,
new_history_len
):
new_history
=
collections
.
deque
(
new_history_len
)
new_history
=
deque
(
maxlen
=
new_history_len
)
for
i
in
range
(
min
(
new_history_len
,
self
.
history_len
)):
for
i
in
range
(
min
(
new_history_len
,
self
.
history_len
)):
new_history
.
append
(
self
.
history
[
-
(
i
+
1
)])
new_history
.
append
(
self
.
history
[
-
(
i
+
1
)])
self
.
history
=
new_history
self
.
history
=
new_history
...
@@ -154,28 +169,26 @@ class AN:
...
@@ -154,28 +169,26 @@ class AN:
def
reset_state
(
self
):
def
reset_state
(
self
):
"""
Set each node to its initial value, and the up to 0.
"""
"""
Set each node to its initial value, and the up to 0.
"""
new_nodes
=
self
.
_nodes
.
copy
(
)
new_nodes
=
deepcopy
(
self
.
_nodes
)
for
node
in
new_nodes
:
for
node
in
new_nodes
:
node
.
reset_state
()
node
.
reset_state
()
self
.
history
.
append
(
self
.
_nodes
)
self
.
history
.
append
(
self
.
_nodes
)
self
.
_nodes
=
new_nodes
self
.
_nodes
=
new_nodes
self
.
up
=
0
self
.
up
=
0
def
update
(
self
):
def
update
(
self
):
"""
Update the AN once.
"""
"""
Update the AN once.
"""
new_nodes
=
copy
.
deepcopy
(
self
.
_nodes
)
new_nodes
=
deepcopy
(
self
.
_nodes
)
for
n
in
self
.
update_mode
[
self
.
up
]:
for
n
in
self
.
update_mode
[
self
.
up
]:
local_view
=
dict_filter
(
self
.
state
,
self
.
_nodes
[
n
].
dependencies
)
local_view
=
dict_filter
(
self
.
state
,
self
.
_nodes
[
n
].
dependencies
)
new_nodes
[
n
].
update
(
local_view
)
new_nodes
[
n
].
update
(
local_view
)
self
.
history
.
append
(
self
.
_nodes
)
self
.
history
.
append
(
self
.
nodes
)
self
.
_nodes
=
new_nodes
self
.
_nodes
=
new_nodes
self
.
up
+=
1
self
.
up
+=
1
def
unupdate
(
self
):
def
unupdate
(
self
):
"""
Roll back one step of the AN, within limits of history_len.
"""
"""
Roll back one step of the AN, within limits of history_len.
"""
self
.
_nodes
=
copy
.
deepcopy
(
self
.
history
.
pop
()
)
self
.
_nodes
=
self
.
history
.
pop
()
self
.
up
-=
1
self
.
up
-=
1
def
run
(
self
,
steps
):
def
run
(
self
,
steps
):
...
@@ -220,7 +233,7 @@ def is_block_seq(mode):
...
@@ -220,7 +233,7 @@ def is_block_seq(mode):
def
block_seq
(
mode
):
def
block_seq
(
mode
):
"""
"""
Checks that `mode` is block-sequential. If so, return it.
Checks that `mode` is block-sequential. If so, return it.
If not, raise a ValueError exception. Useful for funct
o
inal programming.
If not, raise a ValueError exception. Useful for functi
o
nal programming.
"""
"""
if
not
is_block_seq
(
mode
):
raise
ValueError
()
if
not
is_block_seq
(
mode
):
raise
ValueError
()
return
mode
return
mode
...
@@ -228,12 +241,12 @@ def block_seq(mode):
...
@@ -228,12 +241,12 @@ def block_seq(mode):
def
periodic_mode
(
mode
):
def
periodic_mode
(
mode
):
"""
"""
The identity function, with another name.
The identity function, with another name.
Useful for function
n
al programming.
Useful for functional programming.
"""
"""
return
mode
return
mode
# ################################################################
# ################################################################
#
Trivial nodes
#
Node construction
def
node_fixpoint
(
name
,
init_val
=
0
):
def
node_fixpoint
(
name
,
init_val
=
0
):
"""
"""
...
@@ -302,7 +315,7 @@ def cycle(signs, init_vals=None, update_mode=None):
...
@@ -302,7 +315,7 @@ def cycle(signs, init_vals=None, update_mode=None):
return
AN
(
nodes
,
update_mode
)
return
AN
(
nodes
,
update_mode
)
# ################################################################
# ################################################################
# And-not
symmetric
networks
# And-not networks
def
land
(
b1
,
b2
):
def
land
(
b1
,
b2
):
"""
Like `and`, but a function (usable with `reduce`)
"""
"""
Like `and`, but a function (usable with `reduce`)
"""
...
@@ -311,7 +324,7 @@ def land(b1, b2):
...
@@ -311,7 +324,7 @@ def land(b1, b2):
def
and_not_update_func
(
dep_list
):
def
and_not_update_func
(
dep_list
):
"""
"""
Return an update function for a node in an and_not network.
Return an update function for a node in an and_not network.
If dep_list is [1, -2, 3, -4], the node has positive neighbours 1, 3
If dep_list is [1, -2, 3, -4],
then
the node has positive neighbours 1, 3
and negative neighbours 2, 4.
and negative neighbours 2, 4.
"""
"""
def
node_update_func
(
args
):
def
node_update_func
(
args
):
...
@@ -341,11 +354,12 @@ def and_not(dep_lists, init_vals, update_mode):
...
@@ -341,11 +354,12 @@ def and_not(dep_lists, init_vals, update_mode):
"""
"""
nodes
=
[]
nodes
=
[]
for
(
dep_list
,
init_val
,
i
)
in
zip
(
dep_lists
[
1
:],
init_vals
[
1
:],
count
(
1
)):
for
(
dep_list
,
init_val
,
i
)
in
zip
(
dep_lists
[
1
:],
init_vals
[
1
:],
count
(
1
)):
update_func
=
ant_not_update_func
(
dep_list
)
print
(
"
{} {} {}
"
.
format
(
dep_list
,
init_val
,
i
))
update_func
=
and_not_update_func
(
dep_list
)
deps
=
[
abs
(
d
)
for
d
in
dep_list
]
deps
=
[
abs
(
d
)
for
d
in
dep_list
]
node
=
Node
(
i
,
update_func
,
deps
,
init_val
)
node
=
Node
(
i
,
update_func
,
deps
,
init_val
)
nodes
.
append
(
node
)
nodes
.
append
(
node
)
return
AN
(
nodes
[
1
:]
,
update_mode
)
return
AN
(
nodes
,
update_mode
)
# ################################################################
# ################################################################
...
@@ -375,27 +389,3 @@ example_update = [
...
@@ -375,27 +389,3 @@ example_update = [
[],
[],
]
]
# ################################################################
def
button_press
(
event
):
print
(
"
clicked at ({},{})
"
.
format
(
event
.
x
,
event
.
y
))
def
button_release
(
event
):
print
(
"
Released at ({},{})
"
.
format
(
event
.
x
,
event
.
y
))
def
main
():
window
=
Tk
()
window
.
title
(
"
SIMulateur de Réseau d
'
Automates
"
)
canvas
=
Canvas
(
window
)
canvas
.
create_rectangle
(
128
,
64
,
32
,
32
,
outline
=
"
#ff0000
"
,
fill
=
"
#aaaaaa
"
)
canvas
.
bind
(
"
<Button-1>
"
,
button_press
)
canvas
.
bind
(
"
<ButtonRelease-1>
"
,
button_release
)
canvas
.
pack
(
fill
=
BOTH
,
expand
=
1
)
window
.
mainloop
()
if
__name__
==
'
__main__
'
:
main
()
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment