Repository: AureumChaos/LEAP

Issue:
AttributesCSVProbe converts genome to a string
Trying to get individual genome data over a generational EA and the genomes are strings. They should be whatever object the genome is: `list`, `numpy.array`, etc. This is only an issue when using the `do_dataframe=True` option otherwise the data is written to a file stream.

Discussion:

Patch:
diff --git a/leap_ec/executable_rep/rules.py b/leap_ec/executable_rep/rules.py
index 1157078..87aa9da 100644
--- a/leap_ec/executable_rep/rules.py
+++ b/leap_ec/executable_rep/rules.py
@@ -244,7 +244,8 @@ class PittRulesDecoder(Decoder):
 
                 return segment
 
-            return create_segmented_sequence(num_rules, create_rule)
+            rule_set = create_segmented_sequence(num_rules, create_rule)
+            return rule_set()
 
         return create_rule_set
 
diff --git a/leap_ec/int_rep/ops.py b/leap_ec/int_rep/ops.py
index 59ec045..1967e22 100644
--- a/leap_ec/int_rep/ops.py
+++ b/leap_ec/int_rep/ops.py
@@ -231,6 +231,7 @@ def mutate_binomial(next_individual: Iterator, std: float, bounds: list,
 ##############################
 # Function genome_mutate_binomial
 ##############################
+@curry
 def genome_mutate_binomial(std,
                         bounds: list,
                         expected_num_mutations: float = None,
diff --git a/leap_ec/probe.py b/leap_ec/probe.py
index 5711ee8..169c422 100644
--- a/leap_ec/probe.py
+++ b/leap_ec/probe.py
@@ -315,8 +315,8 @@ class AttributesCSVProbe(op.Operator):
     You can retrieve the result programatically from the `dataframe` property:
 
     >>> probe.dataframe
-       step  fitness       genome
-    0   100        4  [0 1 1 1 1]
+       step  fitness           genome
+    0   100        4  [0, 1, 1, 1, 1]
 
     By default, the results are also written to `sys.stdout`.  You can pass
     any file object you like into the `stream` parameter.
@@ -440,7 +440,7 @@ class AttributesCSVProbe(op.Operator):
         if self.do_fitness:
             row['fitness'] = ind.fitness
         if self.do_genome:
-            row['genome'] = str(ind.genome)
+            row['genome'] = ind.genome
         for k, f in self.extra_metrics.items():
             row[k] = f(row)
 
diff --git a/leap_ec/segmented_rep/initializers.py b/leap_ec/segmented_rep/initializers.py
index 857a3bf..bb00d5f 100644
--- a/leap_ec/segmented_rep/initializers.py
+++ b/leap_ec/segmented_rep/initializers.py
@@ -19,7 +19,8 @@ def create_segmented_sequence(length, seq_initializer):
     to calculate the number of segments to generate.
 
     >>> from leap_ec.binary_rep.initializers import create_binary_sequence
-    >>> segments = create_segmented_sequence(3, create_binary_sequence(3))
+    >>> segmented_initializer = create_segmented_sequence(3, create_binary_sequence(3))
+    >>> segments = segmented_initializer()
     >>> assert len(segments) == 3
 
 
@@ -27,20 +28,17 @@ def create_segmented_sequence(length, seq_initializer):
     :type length: int or Callable
     :param seq_initializer: initializer for creating individual sequences
     :type seq_initializer: Callable
-    :return: test_sequence of segments
-    :rtype: list
+    :return: function that returns a list of segmented
+    :rtype: Callable
     """
     if callable(length):
         num_segments = length()
     else:
         num_segments = length
 
-    if not hasattr(seq_initializer, '__len__'):
-        seq_initializer = [ seq_initializer for _ in range(num_segments) ]
+    def segmented():
+        segments = [seq_initializer() for _ in range(num_segments)]
+        return segments
 
-    assert(len(seq_initializer) == num_segments)
-
-    segments = [ init() for init in seq_initializer ]
-
-    return segments
+    return segmented
 


Test patch:
diff --git a/tests/segmented_rep/test_initializers.py b/tests/segmented_rep/test_initializers.py
index a90f749..5293570 100644
--- a/tests/segmented_rep/test_initializers.py
+++ b/tests/segmented_rep/test_initializers.py
@@ -19,13 +19,16 @@ def gen_sequence():
 def test_segmented_initializer_fixed_length():
     """ created fixed length segments """
 
-    segments = create_segmented_sequence(1, gen_sequence)
+    segments_init = create_segmented_sequence(1, gen_sequence)
+    segments = segments_init()
     assert segments == [test_sequence]
 
-    segments = create_segmented_sequence(2, gen_sequence)
+    segments_init = create_segmented_sequence(2, gen_sequence)
+    segments = segments_init()
     assert segments == [test_sequence, test_sequence]
 
-    segments = create_segmented_sequence(3, gen_sequence)
+    segments_init = create_segmented_sequence(3, gen_sequence)
+    segments = segments_init()
     assert segments == [test_sequence, test_sequence, test_sequence]
 
 
@@ -47,8 +50,9 @@ def test_segmented_initializer_variable_length():
     for i in range(N):
         # randomly generate a sequence of segments with the number of segments
         # drawn from a uniform distribution
-        segments.append(create_segmented_sequence(distribution_func,
-                                                  gen_sequence))
+        initializer = create_segmented_sequence(distribution_func,
+                                                gen_sequence)
+        segments.append(initializer())
 
         # track the lengths of those segments
         segment_lengths.append(len(segments[-1]))