Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Alexander R. Hankin
EE194_Manduca_Simulator
Commits
6840e09f
Commit
6840e09f
authored
Apr 30, 2018
by
David A.. Werner
Browse files
Manduca.py pep8
parent
a7a9ae8f
Changes
1
Hide whitespace changes
Inline
Side-by-side
manduca/Manducas.py
View file @
6840e09f
...
...
@@ -2,167 +2,180 @@ import numpy as np
import
StringIO
import
functools
class
ManducaDeformityError
(
Exception
):
def
__init__
(
self
,
message
):
self
.
message
=
message
def
__str__
(
self
):
return
repr
(
self
.
message
)
class
Manduca
(
object
):
def
__init__
(
self
,
legs
,
muscles
,
time_step
):
self
.
_legs
=
self
.
_muscles
=
None
self
.
legs
=
np
.
copy
(
legs
)
self
.
muscles
=
np
.
copy
(
muscles
)
self
.
_time_step
=
time_step
self
.
_fitness
=
None
self
.
check_consistancy
()
@
property
def
legs
(
self
):
return
self
.
_legs
@
legs
.
setter
def
legs
(
self
,
legs
):
new_legs
=
np
.
array
(
legs
)
if
self
.
_legs
:
if
new_legs
.
shape
!=
self
.
_legs
.
shape
:
msg
=
'Ill-defined leg shape. Expected {} but got {}'
e
=
msg
.
format
(
self
.
_legs
.
shape
,
new_legs
.
shape
)
def
__init__
(
self
,
legs
,
muscles
,
time_step
):
self
.
_legs
=
self
.
_muscles
=
None
self
.
legs
=
np
.
copy
(
legs
)
self
.
muscles
=
np
.
copy
(
muscles
)
self
.
_time_step
=
time_step
self
.
_fitness
=
None
self
.
check_consistancy
()
@
property
def
legs
(
self
):
return
self
.
_legs
@
legs
.
setter
def
legs
(
self
,
legs
):
new_legs
=
np
.
array
(
legs
)
if
self
.
_legs
:
if
new_legs
.
shape
!=
self
.
_legs
.
shape
:
msg
=
'Ill-defined leg shape. Expected {} but got {}'
e
=
msg
.
format
(
self
.
_legs
.
shape
,
new_legs
.
shape
)
raise
(
ManducaDeformityError
(
e
))
self
.
_legs
=
new_legs
self
.
_fitness
=
None
@
property
def
muscles
(
self
):
return
self
.
_muscles
@
muscles
.
setter
def
muscles
(
self
,
muscles
):
new_muscles
=
np
.
array
(
muscles
)
if
self
.
_muscles
:
if
new_muscles
.
shape
!=
self
.
_muscles
.
shape
:
msg
=
'Ill-defined muscles shape. Expected {} but got {}'
e
=
msg
.
format
(
self
.
_muscles
.
shape
,
new_muscles
.
shape
)
raise
(
ManducaDeformityError
(
e
))
self
.
_muscles
=
new_muscles
self
.
_fitness
=
None
@
property
def
time_step
(
self
):
return
self
.
_time_step
@
time_step
.
setter
def
time_step
(
self
,
time_step
):
self
.
_time_step
=
time_step
self
.
_fitness
=
None
@
property
def
num_legs
(
self
):
return
self
.
legs
.
shape
[
1
]
@
property
def
num_muscles
(
self
):
return
self
.
muscles
.
shape
[
1
]
@
property
def
num_time_steps
(
self
):
leg_ts
,
muscle_ts
=
self
.
legs
.
shape
[
0
],
self
.
muscles
.
shape
[
0
]
if
leg_ts
!=
muscle_ts
:
msg
=
'Arbitrary number of time-steps. {} in legs, {} in muscles'
e
=
msg
.
format
(
leg_ts
,
muscle_ts
)
raise
(
ManducaDeformityError
(
e
))
self
.
_legs
=
new_legs
self
.
_fitness
=
None
@
property
def
muscles
(
self
):
return
self
.
_muscles
@
muscles
.
setter
def
muscles
(
self
,
muscles
):
new_muscles
=
np
.
array
(
muscles
)
if
self
.
_muscles
:
if
new_muscles
.
shape
!=
self
.
_muscles
.
shape
:
msg
=
'Ill-defined muscles shape. Expected {} but got {}'
e
=
msg
.
format
(
self
.
_muscles
.
shape
,
new_muscles
.
shape
)
return
leg_ts
@
property
def
fitness
(
self
):
if
(
self
.
_fitness
is
None
):
results
=
self
.
simulate
()
self
.
_fitness
=
0
return
(
self
.
_fitness
)
@
property
def
initial_position
(
self
):
return
np
.
arange
(
self
.
num_legs
)
*
500
def
check_consistancy
(
self
):
if
self
.
num_muscles
!=
self
.
num_legs
-
1
:
msg
=
'Ill-defined manduca has {} legs and {} muscles'
e
=
msg
.
format
(
self
.
num_legs
,
self
.
num_muscles
)
raise
(
ManducaDeformityError
(
e
))
self
.
_muscles
=
new_muscles
self
.
_fitness
=
None
@
property
def
time_step
(
self
):
return
self
.
_time_step
@
time_step
.
setter
def
time_step
(
self
,
time_step
):
self
.
_time_step
=
time_step
self
.
_fitness
=
None
@
property
def
num_legs
(
self
):
return
self
.
legs
.
shape
[
1
]
@
property
def
num_muscles
(
self
):
return
self
.
muscles
.
shape
[
1
]
@
property
def
num_time_steps
(
self
):
leg_ts
,
muscle_ts
=
self
.
legs
.
shape
[
0
],
self
.
muscles
.
shape
[
0
]
if
leg_ts
!=
muscle_ts
:
msg
=
'Arbitrary number of time-steps. {} in legs, {} in muscles'
e
=
msg
.
format
(
leg_ts
,
muscle_ts
)
raise
(
ManducaDeformityError
(
e
))
return
leg_ts
@
property
def
fitness
(
self
):
if
(
self
.
_fitness
is
None
):
results
=
self
.
simulate
()
self
.
_fitness
=
0
return
(
self
.
_fitness
)
@
property
def
initial_position
(
self
):
return
np
.
arange
(
self
.
num_legs
)
*
500
def
check_consistancy
(
self
):
if
self
.
num_muscles
!=
self
.
num_legs
-
1
:
msg
=
'Ill-defined manduca has {} legs and {} muscles'
e
=
msg
.
format
(
self
.
num_legs
,
self
.
num_muscles
)
raise
(
ManducaDeformityError
(
e
))
# Make sure the number of time steps is consistant
self
.
num_time_steps
def
__repr__
(
self
):
output
=
StringIO
.
StringIO
()
output
.
write
(
"
\n
legs | muscles"
)
for
leg_t
,
musc_t
in
zip
(
self
.
legs
,
self
.
muscles
):
leg_str
=
" "
.
join
(
"{:>1}"
.
format
(
int
(
l
))
for
l
in
leg_t
)
musc_str
=
" "
.
join
(
"{:>3}"
.
format
(
int
(
m
))
for
m
in
musc_t
)
output
.
write
(
"
\n
{} | {}"
.
format
(
leg_str
,
musc_str
))
val
=
output
.
getvalue
()
output
.
close
()
return
val
def
__eq__
(
self
,
other
):
return
(
self
.
time_step
==
other
.
time_step
and
np
.
array_equal
(
self
.
legs
,
other
.
legs
)
and
np
.
array_equal
(
self
.
muscles
,
other
.
muscles
)
)
def
__ne__
(
self
,
other
):
return
(
self
.
time_step
!=
other
.
time_step
or
not
(
np
.
array_equal
(
self
.
legs
,
other
.
legs
))
or
not
(
np
.
array_equal
(
self
.
muscles
,
other
.
muscles
)))
def
__hash__
(
self
):
return
hash
(
self
.
legs
.
tostring
()
+
self
.
muscles
.
tostring
()
+
str
(
self
.
time_step
))
def
simulate
(
self
):
pass
def
save
(
self
,
file_name
,
compressed
=
True
):
if
compressed
:
save_fn
=
np
.
savez_compressed
else
:
save_fn
=
np
.
savez
save_fn
(
file_name
,
legs
=
self
.
legs
,
muscles
=
self
.
muscles
,
time_step
=
self
.
time_step
,
fitness
=
self
.
_fitness
)
@
classmethod
def
load
(
cls
,
file_name
,
*
other_params
,
**
kwargs
):
try
:
results
=
np
.
load
(
file_name
)
legs
=
results
[
'legs'
]
muscles
=
results
[
'muscles'
]
time_step
=
results
[
'time_step'
]
args
=
[]
for
param
in
other_params
:
args
.
append
(
results
[
param
])
new_manduca
=
cls
(
legs
,
muscles
,
time_step
,
*
args
,
**
kwargs
)
if
'fitness'
in
results
:
new_manduca
.
_fitness
=
np
.
asscalar
(
results
[
'fitness'
])
return
new_manduca
except
(
IOError
,
ValueError
)
as
e
:
print
(
'Error loading {} from file {}'
.
format
(
cls
.
__name__
,
file_name
))
raise
(
e
)
def
clone
(
self
):
return
(
self
.
__class__
(
np
.
copy
(
self
.
legs
),
np
.
copy
(
self
.
muscles
)))
# Make sure the number of time steps is consistant
self
.
num_time_steps
def
__repr__
(
self
):
output
=
StringIO
.
StringIO
()
output
.
write
(
"
\n
legs | muscles"
)
for
leg_t
,
musc_t
in
zip
(
self
.
legs
,
self
.
muscles
):
leg_str
=
" "
.
join
(
"{:>1}"
.
format
(
int
(
l
))
for
l
in
leg_t
)
musc_str
=
" "
.
join
(
"{:>3}"
.
format
(
int
(
m
))
for
m
in
musc_t
)
output
.
write
(
"
\n
{} | {}"
.
format
(
leg_str
,
musc_str
))
val
=
output
.
getvalue
()
output
.
close
()
return
val
def
__eq__
(
self
,
other
):
return
(
self
.
time_step
==
other
.
time_step
and
np
.
array_equal
(
self
.
legs
,
other
.
legs
)
and
np
.
array_equal
(
self
.
muscles
,
other
.
muscles
))
def
__ne__
(
self
,
other
):
return
(
self
.
time_step
!=
other
.
time_step
or
not
(
np
.
array_equal
(
self
.
legs
,
other
.
legs
))
or
not
(
np
.
array_equal
(
self
.
muscles
,
other
.
muscles
)))
def
__hash__
(
self
):
leg_str
,
m_str
=
self
.
legs
.
tostring
(),
self
.
muscles
.
tostring
()
t_str
=
str
(
self
.
time_step
)
manduca_str
=
leg_str
+
m_str
+
t_str
return
hash
(
manduca_str
)
def
simulate
(
self
):
pass
def
save
(
self
,
file_name
,
compressed
=
True
):
if
compressed
:
save_fn
=
np
.
savez_compressed
else
:
save_fn
=
np
.
savez
save_fn
(
file_name
,
legs
=
self
.
legs
,
muscles
=
self
.
muscles
,
time_step
=
self
.
time_step
,
fitness
=
self
.
_fitness
)
@
classmethod
def
load
(
cls
,
file_name
,
*
other_params
,
**
kwargs
):
try
:
results
=
np
.
load
(
file_name
)
legs
=
results
[
'legs'
]
muscles
=
results
[
'muscles'
]
time_step
=
results
[
'time_step'
]
args
=
[]
for
param
in
other_params
:
args
.
append
(
results
[
param
])
new_manduca
=
cls
(
legs
,
muscles
,
time_step
,
*
args
,
**
kwargs
)
if
'fitness'
in
results
:
new_manduca
.
_fitness
=
np
.
asscalar
(
results
[
'fitness'
])
return
new_manduca
except
(
IOError
,
ValueError
)
as
e
:
msg
=
'Error loading {} from file {}'
print
(
msg
.
format
(
cls
.
__name__
,
file_name
))
raise
(
e
)
def
clone
(
self
):
return
(
self
.
__class__
(
np
.
copy
(
self
.
legs
),
np
.
copy
(
self
.
muscles
)))
class
SimpleManduca
(
Manduca
):
"""A Manduca that has legs and muscles that are either ON/OFF"""
def
__init__
(
self
,
legs
,
muscles
,
time_step
,
muscle_strength
=
None
):
super
(
SimpleManduca
,
self
).
__init__
(
legs
,
muscles
,
time_step
)
assert
((
self
.
legs
==
1
)
|
(
self
.
legs
==
0
)).
all
(),
"Legs must be 0 or 1"
if
muscle_strength
is
None
:
assert
self
.
muscles
.
max
()
!=
0
,
"Cannot detemine muscle_strength when all values are 0"
muscle_strength
=
self
.
muscles
.
max
()
assert
((
self
.
muscles
==
0
)
|
(
self
.
muscles
==
muscle_strength
)).
all
(),
\
"Muscles must be 0 or {}"
.
format
(
muscle_strength
)
@
staticmethod
def
random_individual
(
num_legs
,
time_segments
,
time_step
,
muscle_strength
=
100
,
rng
=
np
.
random
):
legs
=
rng
.
choice
([
0
,
1
],
size
=
(
time_segments
,
num_legs
))
muscles
=
rng
.
choice
([
0
,
muscle_strength
],
size
=
(
time_segments
,
num_legs
-
1
))
return
SimpleManduca
(
legs
,
muscles
,
time_step
,
muscle_strength
=
muscle_strength
)
"""A Manduca that has legs and muscles that are either ON/OFF"""
def
__init__
(
self
,
legs
,
muscles
,
time_step
,
muscle_strength
=
None
):
super
(
SimpleManduca
,
self
).
__init__
(
legs
,
muscles
,
time_step
)
locked_legs
,
unlocked_legs
=
self
.
legs
==
1
,
self
.
legs
==
0
assert
(
locked_legs
|
unlocked_legs
).
all
(),
"Legs must be 0 or 1"
if
muscle_strength
is
None
:
msg
=
"Cannot detemine muscle_strength when all values are 0"
assert
self
.
muscles
.
max
()
!=
0
,
msg
muscle_strength
=
self
.
muscles
.
max
()
musc_on
,
musc_off
=
self
.
muscles
==
0
,
self
.
muscles
==
muscle_strength
msg
=
"Muscles must be 0 or {}"
.
format
(
muscle_strength
)
assert
(
musc_on
|
musc_off
).
all
(),
msg
@
staticmethod
def
random_individual
(
num_legs
,
time_segments
,
time_step
,
**
kwargs
):
musc_stren
=
kwargs
.
pop
(
muscle_strength
,
100
)
rng
=
kwargs
.
pop
(
'rng'
,
np
.
random
)
legs
=
rng
.
choice
([
0
,
1
],
size
=
(
time_segments
,
num_legs
))
muscles
=
rng
.
choice
([
0
,
muscle_strength
],
size
=
(
time_segments
,
num_legs
-
1
))
return
SimpleManduca
(
legs
,
muscles
,
time_step
,
muscle_strength
=
muscle_strength
)
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