Commit d8e2286d authored by David A.. Werner's avatar David A.. Werner
Browse files

Manduca has random_individual. initial_position is 0 centered. optionally...

Manduca has random_individual. initial_position is 0 centered. optionally record legs/muscles. bugfix when loading time_step
parent df85a40f
......@@ -192,7 +192,7 @@ class Manduca(object):
@staticmethod
def distance_traveled(manduca):
"""This function gets the current time step for a specified Manduca.
:param manduca: The Manduca to evaluated.
:type manduca: Manduca.
:returns: float -- the distance the Manduca has traveled.
......@@ -226,7 +226,9 @@ class Manduca(object):
:returns: numpy array -- the initial position of the Manduca.
"""
return np.arange(self.num_legs)*self.body_properties.L0
pos = np.arange(self.num_legs)*self.body_properties.L0
pos = pos - np.mean(pos)
return pos
def check_consistancy(self):
"""This function checks to make sure the Manduca's body is consistent, i.e., same number of legs and muscles.
......@@ -241,7 +243,7 @@ class Manduca(object):
def change_muscle_value(self, current_value, rng=np.random):
"""This function changes a muscle value for a specified Manduca.
:param current_value: The current muscle value.
:type current_value: float.
:param rng=np.random: The random number generator.
......@@ -252,12 +254,12 @@ class Manduca(object):
return rng.rand()*self.body_properties.muscle_strength
# First randomly choose the number of mutations (1 up to MAX_MUTATIONS)
# - flip a random leg-locked
# - flip a random muscle-on
# - do the secret-sauce mutation if desired.
#- flip a random leg-locked
#- flip a random muscle-on
#- do the secret-sauce mutation if desired.
def mutate (self, rng=np.random, max_mutations = 20):
"""This function mutates a specified Manduca by either flipping a random leg locked or flipping a random muscle on.
:param rng=np.random: The random number generator.
:type rng=np.random: A random number generator.
:param max_mutations = 20: The maximum possible number of mutations that can happen.
......@@ -288,7 +290,7 @@ class Manduca(object):
# This is the final function that you write yourself.
def mate(self, parent2, rng=np.random):
"""This function mates two lucky Manducas. Picks entire rows from one parent or the other to form child.
:param parent2: The other parent involved in the mating.
:type parent2: Manduca.
:param rng=np.random: The random number generator.
......@@ -309,7 +311,7 @@ class Manduca(object):
def __repr__(self):
"""This function prints the Manduca object.
:returns: string -- containing information about the Manduca which includes legs, muscles, and body properties.
"""
......@@ -326,7 +328,7 @@ class Manduca(object):
def __eq__(self, other):
"""This function checks to see if two Manducas are equivalent.
:param other: The other Manduca involved in the comparison.
:type other: Manduca.
:returns: bool -- whether the two Manducas are equivalent.
......@@ -340,13 +342,13 @@ class Manduca(object):
def __ne__(self, other):
"""This function checks to see if two Manducas are different.
:param other: The other Manduca involved in the comparison.
:type other: Manduca.
:returns: bool -- whether the two Manducas are different.
"""
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) or
......@@ -354,7 +356,7 @@ class Manduca(object):
def __hash__(self):
"""This functions returns a hash of the summary of the Manduca's properties
:param parent2: The other parent involved in the mating.
:type parent2: Manduca.
:returns: Manduca -- the new child Manduca.
......@@ -365,7 +367,7 @@ class Manduca(object):
manduca_str = leg_str + m_str + t_str
return hash(manduca_str)
def simulate(self, record_level=0, sub_intervals = 10):
def simulate(self, record_level=0, sub_intervals = 10, record_legs_and_muscles=False):
"""This functions returns a hash of the summary of the Manduca's properties
:param record_level: Which intervals to record the position/velocity/time
......@@ -392,10 +394,10 @@ class Manduca(object):
Front Leg: fn' = -k(xn-x{n-1}-L0) + c(v{n-1}-vn) + M{n-1}n
:param x: position of legs and velocites of legs
in the form [x0, x1, ..., xn, v0, v1, ..., vn]
in the form [x0, x1, ..., xn, v0, v1, ..., vn]
:param t: is an array of time values over which to integrate
in the form [t0, t1, ..., tN]
in the form [t0, t1, ..., tN]
:return: numpy array -- the derivatives of x
......@@ -455,6 +457,7 @@ class Manduca(object):
# Record the initial position and velocities
recorded_positions, recorded_velocities = [position], [velocities]
recorded_times = [0.0]
recorded_legs, recorded_muscles = [self.legs[0]], [self.muscles[0]]
# For each time-step, advance the simulation
for time, current_legs, current_muscles in zip(times, self.legs, self.muscles):
......@@ -481,21 +484,31 @@ class Manduca(object):
recorded_positions.append(position)
recorded_velocities.append(velocities)
recorded_times.append(end_time)
recorded_legs.append(current_legs)
recorded_muscles.append(current_muscles)
elif record_level == 2:
recorded_positions.extend(new_positions)
recorded_velocities.extend(new_velocities)
recorded_times.extend(new_times)
for _ in range(sub_intervals):
recorded_legs.append(current_legs)
recorded_muscles.append(current_muscles)
# If the record_level is 0, save the final interval as wel
if record_level not in [1,2]:
recorded_positions.append(position)
recorded_velocities.append(velocities)
recorded_times.append(end_time)
recorded_legs.append(current_legs)
recorded_muscles.append(current_muscles)
if record_legs_and_muscles == True:
return recorded_positions, recorded_velocities, recorded_times, recorded_legs,\
recorded_muscles
return recorded_positions, recorded_velocities, recorded_times
def save(self, file_name, compressed=True):
"""This function saves information about a Manduca to a file
:param file_name: The name of the file to be written to.
:type file_name: string.
:param compressed: Whether or not the file should be compressed.
......@@ -513,7 +526,7 @@ class Manduca(object):
@classmethod
def load(cls, file_name, *other_params, **kwargs):
"""This functions loads information about a Manduca from a file
:param cls: The other parent
:type cls: Manduca.
:param file_name: The name of the file to be loaded from
......@@ -527,7 +540,7 @@ class Manduca(object):
results = np.load(file_name)
legs = results['legs']
muscles = results['muscles']
time_step = results['time_step']
time_step = np.asscalar(results['time_step'])
args = []
for param in other_params:
args.append(results[param])
......@@ -545,7 +558,7 @@ class Manduca(object):
def clone(self):
"""This functions clones a Manduca
:returns: Manduca -- the Manduca clone.
"""
......@@ -553,12 +566,37 @@ class Manduca(object):
time_step=self.time_step,
body_properties=self.body_properties)
@staticmethod
def random_individual(num_legs, time_segments, time_step, **kwargs):
"""This functions returns a hash of the summary of the Manduca's properties
:param num_legs: The number of the legs the Manduca has.
:type num_legs: int.
:param time_step: .
:type time_step: int.
:param time_step: the time of one interval.
:type time_step: int.
:param \**kwargs: keyword args passed to super.
:returns: Manduca -- the new random Manduca.
"""
body_properties = kwargs.pop('body_properties', None)
if body_properties == None:
body_properties = Manduca.default_body_properties
kwargs['body_properties'] = body_properties
muscle_strength = body_properties.muscle_strength
rng = kwargs.pop('rng', np.random)
legs = rng.choice([0, 1], size=(time_segments, num_legs))
muscles = rng.uniform(size=(time_segments, num_legs-1))*muscle_strength
return Manduca(legs, muscles, time_step, **kwargs)
class SimpleManduca(Manduca):
"""A Manduca that has legs and muscles that are either ON/OFF"""
def __init__(self, legs, muscles, time_step, **kwargs):
"""This function is the constructor for the Simple Manduca class
:param legs: 2D array representing Manduca's legs.
:type legs: int.
:param muscles: 2D array representing Manduca's muscles.
......@@ -578,7 +616,7 @@ class SimpleManduca(Manduca):
@staticmethod
def random_individual(num_legs, time_segments, time_step, **kwargs):
"""This functions returns a hash of the summary of the Manduca's properties
:param num_legs: The number of the legs the Manduca has.
:type num_legs: int.
:param time_step: .
......@@ -586,7 +624,7 @@ class SimpleManduca(Manduca):
:param time_step: the time of one interval.
:type time_step: int.
:param \**kwargs: keyword args passed to super.
:returns: Manduca -- the new random Manduca.
"""
......@@ -603,7 +641,7 @@ class SimpleManduca(Manduca):
def change_muscle_value(self, current_value, rng=np.random):
"""This functions determines a new muscle value based on the previous
:param current_value: the current muscle value.
:type current_value: float.
:param rng=np.random: A random number generator
......
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