Adding self determination of generation length
This commit is contained in:
parent
98803b3700
commit
822df77f62
7 changed files with 1089 additions and 180 deletions
163
analyze_data.py
Normal file
163
analyze_data.py
Normal file
|
@ -0,0 +1,163 @@
|
|||
# Re-importing necessary libraries
|
||||
import json
|
||||
import matplotlib.pyplot as plt
|
||||
from collections import defaultdict
|
||||
import numpy as np
|
||||
|
||||
# Simplified JSON data for demonstration
|
||||
with open('gemla/round2.json', 'r') as file:
|
||||
simplified_json_data = json.load(file)
|
||||
|
||||
target_node_id = '0c1e64dc-6ddf-4dbb-bf6e-e8218b925194'
|
||||
|
||||
# Function to traverse the tree to find a node id
|
||||
def traverse_left_nodes(node):
|
||||
if node is None:
|
||||
return []
|
||||
|
||||
left_node = node.get("left")
|
||||
if left_node is None:
|
||||
return [node]
|
||||
|
||||
return [node] + traverse_left_nodes(left_node)
|
||||
|
||||
# Function to traverse the tree to find a node id
|
||||
def traverse_right_nodes(node):
|
||||
if node is None:
|
||||
return []
|
||||
|
||||
right_node = node.get("right")
|
||||
left_node = node.get("left")
|
||||
|
||||
if right_node is None and left_node is None:
|
||||
return []
|
||||
elif right_node and left_node:
|
||||
return [right_node] + traverse_right_nodes(left_node)
|
||||
|
||||
return []
|
||||
|
||||
|
||||
# Getting the left graph
|
||||
left_nodes = traverse_left_nodes(simplified_json_data[0])
|
||||
left_nodes.reverse()
|
||||
# print(node)
|
||||
# Print properties available on the first node
|
||||
node = left_nodes[0]
|
||||
# print(node["val"].keys())
|
||||
|
||||
scores = []
|
||||
for node in left_nodes:
|
||||
# print(node)
|
||||
# print(f'Node ID: {node["val"]["id"]}')
|
||||
# print(f'Node scores length: {len(node["val"]["node"]["scores"])}')
|
||||
if node["val"]["node"]:
|
||||
node_scores = node["val"]["node"]["scores"]
|
||||
if node_scores:
|
||||
for score in node_scores:
|
||||
scores.append(score)
|
||||
|
||||
# print(scores)
|
||||
|
||||
scores_values = [list(score_set.values()) for score_set in scores]
|
||||
|
||||
# Set up the figure for plotting on the same graph
|
||||
fig, ax = plt.subplots(figsize=(10, 6))
|
||||
|
||||
# Generate a boxplot for each set of scores on the same graph
|
||||
boxplots = ax.boxplot(scores_values, vert=False, patch_artist=True, labels=[f'Set {i+1}' for i in range(len(scores_values))])
|
||||
|
||||
# Set figure name to node id
|
||||
# fig.canvas.set_window_title('Main node line')
|
||||
|
||||
# Labeling
|
||||
ax.set_xlabel(f'Scores - Main Line')
|
||||
ax.set_ylabel('Score Sets')
|
||||
ax.yaxis.grid(True) # Add horizontal grid lines for clarity
|
||||
|
||||
# Set y-axis labels to be visible
|
||||
ax.set_yticklabels([f'Set {i+1}' for i in range(len(scores_values))])
|
||||
|
||||
# Getting most recent right graph
|
||||
right_nodes = traverse_right_nodes(simplified_json_data[0])
|
||||
target_node_id = None
|
||||
target_node = None
|
||||
if target_node_id:
|
||||
for node in right_nodes:
|
||||
if node["val"]["id"] == target_node_id:
|
||||
target_node = node
|
||||
break
|
||||
else:
|
||||
target_node = right_nodes[1]
|
||||
scores = target_node["val"]["node"]["scores"]
|
||||
|
||||
scores_values = [list(score_set.values()) for score_set in scores]
|
||||
|
||||
# Set up the figure for plotting on the same graph
|
||||
fig, ax = plt.subplots(figsize=(10, 6))
|
||||
|
||||
# Generate a boxplot for each set of scores on the same graph
|
||||
boxplots = ax.boxplot(scores_values, vert=False, patch_artist=True, labels=[f'Set {i+1}' for i in range(len(scores_values))])
|
||||
|
||||
|
||||
# Labeling
|
||||
ax.set_xlabel(f'Scores: {target_node['val']['id']}')
|
||||
ax.set_ylabel('Score Sets')
|
||||
ax.yaxis.grid(True) # Add horizontal grid lines for clarity
|
||||
|
||||
# Set y-axis labels to be visible
|
||||
ax.set_yticklabels([f'Set {i+1}' for i in range(len(scores_values))])
|
||||
|
||||
# Find the highest scoring sets combining all scores and generations
|
||||
scores = []
|
||||
for node in left_nodes:
|
||||
if node["val"]["node"]:
|
||||
node_scores = node["val"]["node"]["scores"]
|
||||
translated_node_scores = []
|
||||
if node_scores:
|
||||
for i in range(len(node_scores)):
|
||||
for (individual, score) in node_scores[i].items():
|
||||
translated_node_scores.append((node["val"]["id"], i, score))
|
||||
|
||||
scores.append(translated_node_scores)
|
||||
|
||||
# Add scores from the right nodes
|
||||
for node in right_nodes:
|
||||
if node["val"]["node"]:
|
||||
node_scores = node["val"]["node"]["scores"]
|
||||
translated_node_scores = []
|
||||
if node_scores:
|
||||
for i in range(len(node_scores)):
|
||||
for (individual, score) in node_scores[i].items():
|
||||
translated_node_scores.append((node["val"]["id"], i, score))
|
||||
|
||||
# Organize scores by individual and then by generation
|
||||
individual_generation_scores = defaultdict(lambda: defaultdict(list))
|
||||
for sublist in scores:
|
||||
for id, generation, score in sublist:
|
||||
individual_generation_scores[id][generation].append(score)
|
||||
|
||||
# Calculate Q3 for each individual's generation
|
||||
individual_generation_q3 = {}
|
||||
for id, generations in individual_generation_scores.items():
|
||||
for gen, scores in generations.items():
|
||||
individual_generation_q3[(id, gen)] = np.percentile(scores, 75)
|
||||
|
||||
# Sort by Q3 value, highest first, and select the top 20
|
||||
top_20_individual_generations = sorted(individual_generation_q3, key=individual_generation_q3.get, reverse=True)[:40]
|
||||
|
||||
# Prepare scores for the top 20 for plotting
|
||||
top_20_scores = [individual_generation_scores[id][gen] for id, gen in top_20_individual_generations]
|
||||
|
||||
# Adjust labels for clarity, indicating both the individual ID and generation
|
||||
labels = [f'{id[:8]}... Gen {gen}' for id, gen in top_20_individual_generations]
|
||||
|
||||
# Generate box and whisker plots for the top 20 individual generations
|
||||
fig, ax = plt.subplots(figsize=(12, 10))
|
||||
ax.boxplot(top_20_scores, vert=False, patch_artist=True, labels=labels)
|
||||
ax.set_xlabel('Scores')
|
||||
ax.set_ylabel('Individual Generation')
|
||||
ax.set_title('Top 20 Individual Generations by Q3 Value')
|
||||
|
||||
# Display the plot
|
||||
plt.show()
|
||||
|
|
@ -47,10 +47,7 @@ fn main() -> Result<()> {
|
|||
let mut gemla = log_error(
|
||||
Gemla::<FighterNN>::new(
|
||||
&PathBuf::from(args.file),
|
||||
GemlaConfig {
|
||||
generations_per_height: 5,
|
||||
overwrite: false,
|
||||
},
|
||||
GemlaConfig { overwrite: false },
|
||||
DataFormat::Json,
|
||||
)
|
||||
.await,
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -13,6 +13,7 @@ const POPULATION_REDUCTION_SIZE: u64 = 3;
|
|||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct TestState {
|
||||
pub population: Vec<i64>,
|
||||
pub max_generations: u64,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
@ -26,10 +27,16 @@ impl GeneticNode for TestState {
|
|||
population.push(thread_rng().gen_range(0..100))
|
||||
}
|
||||
|
||||
Ok(Box::new(TestState { population }))
|
||||
Ok(Box::new(TestState {
|
||||
population,
|
||||
max_generations: 10,
|
||||
}))
|
||||
}
|
||||
|
||||
async fn simulate(&mut self, _context: GeneticNodeContext<Self::Context>) -> Result<(), Error> {
|
||||
async fn simulate(
|
||||
&mut self,
|
||||
context: GeneticNodeContext<Self::Context>,
|
||||
) -> Result<bool, Error> {
|
||||
let mut rng = thread_rng();
|
||||
|
||||
self.population = self
|
||||
|
@ -38,7 +45,11 @@ impl GeneticNode for TestState {
|
|||
.map(|p| p.saturating_add(rng.gen_range(-1..2)))
|
||||
.collect();
|
||||
|
||||
Ok(())
|
||||
if context.generation >= self.max_generations {
|
||||
Ok(false)
|
||||
} else {
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
async fn mutate(&mut self, _context: GeneticNodeContext<Self::Context>) -> Result<(), Error> {
|
||||
|
@ -93,13 +104,15 @@ impl GeneticNode for TestState {
|
|||
|
||||
v = v[..(POPULATION_REDUCTION_SIZE as usize)].to_vec();
|
||||
|
||||
let mut result = TestState { population: v };
|
||||
let mut result = TestState {
|
||||
population: v,
|
||||
max_generations: 10,
|
||||
};
|
||||
|
||||
result
|
||||
.mutate(GeneticNodeContext {
|
||||
id: *id,
|
||||
generation: 0,
|
||||
max_generations: 0,
|
||||
gemla_context,
|
||||
})
|
||||
.await?;
|
||||
|
@ -118,7 +131,6 @@ mod tests {
|
|||
let state = TestState::initialize(GeneticNodeContext {
|
||||
id: Uuid::new_v4(),
|
||||
generation: 0,
|
||||
max_generations: 0,
|
||||
gemla_context: (),
|
||||
})
|
||||
.await
|
||||
|
@ -131,6 +143,7 @@ mod tests {
|
|||
async fn test_simulate() {
|
||||
let mut state = TestState {
|
||||
population: vec![1, 1, 2, 3],
|
||||
max_generations: 1,
|
||||
};
|
||||
|
||||
let original_population = state.population.clone();
|
||||
|
@ -139,7 +152,6 @@ mod tests {
|
|||
.simulate(GeneticNodeContext {
|
||||
id: Uuid::new_v4(),
|
||||
generation: 0,
|
||||
max_generations: 0,
|
||||
gemla_context: (),
|
||||
})
|
||||
.await
|
||||
|
@ -153,7 +165,6 @@ mod tests {
|
|||
.simulate(GeneticNodeContext {
|
||||
id: Uuid::new_v4(),
|
||||
generation: 0,
|
||||
max_generations: 0,
|
||||
gemla_context: (),
|
||||
})
|
||||
.await
|
||||
|
@ -162,7 +173,6 @@ mod tests {
|
|||
.simulate(GeneticNodeContext {
|
||||
id: Uuid::new_v4(),
|
||||
generation: 0,
|
||||
max_generations: 0,
|
||||
gemla_context: (),
|
||||
})
|
||||
.await
|
||||
|
@ -177,13 +187,13 @@ mod tests {
|
|||
async fn test_mutate() {
|
||||
let mut state = TestState {
|
||||
population: vec![4, 3, 3],
|
||||
max_generations: 1,
|
||||
};
|
||||
|
||||
state
|
||||
.mutate(GeneticNodeContext {
|
||||
id: Uuid::new_v4(),
|
||||
generation: 0,
|
||||
max_generations: 0,
|
||||
gemla_context: (),
|
||||
})
|
||||
.await
|
||||
|
@ -196,10 +206,12 @@ mod tests {
|
|||
async fn test_merge() {
|
||||
let state1 = TestState {
|
||||
population: vec![1, 2, 4, 5],
|
||||
max_generations: 1,
|
||||
};
|
||||
|
||||
let state2 = TestState {
|
||||
population: vec![0, 1, 3, 7],
|
||||
max_generations: 1,
|
||||
};
|
||||
|
||||
let merged_state = TestState::merge(&state1, &state2, &Uuid::new_v4(), ())
|
||||
|
|
|
@ -28,7 +28,6 @@ pub enum GeneticState {
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct GeneticNodeContext<S> {
|
||||
pub generation: u64,
|
||||
pub max_generations: u64,
|
||||
pub id: Uuid,
|
||||
pub gemla_context: S,
|
||||
}
|
||||
|
@ -46,7 +45,8 @@ pub trait GeneticNode: Send {
|
|||
/// TODO
|
||||
async fn initialize(context: GeneticNodeContext<Self::Context>) -> Result<Box<Self>, Error>;
|
||||
|
||||
async fn simulate(&mut self, context: GeneticNodeContext<Self::Context>) -> Result<(), Error>;
|
||||
async fn simulate(&mut self, context: GeneticNodeContext<Self::Context>)
|
||||
-> Result<bool, Error>;
|
||||
|
||||
/// Mutates members in a population and/or crossbreeds them to produce new offspring.
|
||||
///
|
||||
|
@ -72,7 +72,6 @@ where
|
|||
node: Option<T>,
|
||||
state: GeneticState,
|
||||
generation: u64,
|
||||
max_generations: u64,
|
||||
id: Uuid,
|
||||
}
|
||||
|
||||
|
@ -85,7 +84,6 @@ where
|
|||
node: None,
|
||||
state: GeneticState::Initialize,
|
||||
generation: 1,
|
||||
max_generations: 1,
|
||||
id: Uuid::new_v4(),
|
||||
}
|
||||
}
|
||||
|
@ -96,19 +94,17 @@ where
|
|||
T: GeneticNode + Debug + Send + Clone,
|
||||
T::Context: Send + Sync + Clone + Debug + Serialize + DeserializeOwned + 'static + Default,
|
||||
{
|
||||
pub fn new(max_generations: u64) -> Self {
|
||||
pub fn new() -> Self {
|
||||
GeneticNodeWrapper::<T> {
|
||||
max_generations,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from(data: T, max_generations: u64, id: Uuid) -> Self {
|
||||
pub fn from(data: T, id: Uuid) -> Self {
|
||||
GeneticNodeWrapper {
|
||||
node: Some(data),
|
||||
state: GeneticState::Simulate,
|
||||
generation: 1,
|
||||
max_generations,
|
||||
id,
|
||||
}
|
||||
}
|
||||
|
@ -125,10 +121,6 @@ where
|
|||
self.id
|
||||
}
|
||||
|
||||
pub fn max_generations(&self) -> u64 {
|
||||
self.max_generations
|
||||
}
|
||||
|
||||
pub fn generation(&self) -> u64 {
|
||||
self.generation
|
||||
}
|
||||
|
@ -140,7 +132,6 @@ where
|
|||
pub async fn process_node(&mut self, gemla_context: T::Context) -> Result<GeneticState, Error> {
|
||||
let context = GeneticNodeContext {
|
||||
generation: self.generation,
|
||||
max_generations: self.max_generations,
|
||||
id: self.id,
|
||||
gemla_context,
|
||||
};
|
||||
|
@ -151,14 +142,15 @@ where
|
|||
self.state = GeneticState::Simulate;
|
||||
}
|
||||
(GeneticState::Simulate, Some(n)) => {
|
||||
n.simulate(context.clone())
|
||||
let next_generation = n
|
||||
.simulate(context.clone())
|
||||
.await
|
||||
.with_context(|| format!("Error simulating node: {:?}", self))?;
|
||||
|
||||
self.state = if self.generation >= self.max_generations {
|
||||
GeneticState::Finish
|
||||
} else {
|
||||
self.state = if next_generation {
|
||||
GeneticState::Mutate
|
||||
} else {
|
||||
GeneticState::Finish
|
||||
};
|
||||
}
|
||||
(GeneticState::Mutate, Some(n)) => {
|
||||
|
@ -187,6 +179,7 @@ mod tests {
|
|||
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
|
||||
struct TestState {
|
||||
pub score: f64,
|
||||
pub max_generations: u64,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
@ -195,10 +188,14 @@ mod tests {
|
|||
|
||||
async fn simulate(
|
||||
&mut self,
|
||||
_context: GeneticNodeContext<Self::Context>,
|
||||
) -> Result<(), Error> {
|
||||
context: GeneticNodeContext<Self::Context>,
|
||||
) -> Result<bool, Error> {
|
||||
self.score += 1.0;
|
||||
Ok(())
|
||||
if context.generation >= self.max_generations {
|
||||
Ok(false)
|
||||
} else {
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
async fn mutate(
|
||||
|
@ -211,7 +208,10 @@ mod tests {
|
|||
async fn initialize(
|
||||
_context: GeneticNodeContext<Self::Context>,
|
||||
) -> Result<Box<TestState>, Error> {
|
||||
Ok(Box::new(TestState { score: 0.0 }))
|
||||
Ok(Box::new(TestState {
|
||||
score: 0.0,
|
||||
max_generations: 2,
|
||||
}))
|
||||
}
|
||||
|
||||
async fn merge(
|
||||
|
@ -226,13 +226,12 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_new() -> Result<(), Error> {
|
||||
let genetic_node = GeneticNodeWrapper::<TestState>::new(10);
|
||||
let genetic_node = GeneticNodeWrapper::<TestState>::new();
|
||||
|
||||
let other_genetic_node = GeneticNodeWrapper::<TestState> {
|
||||
node: None,
|
||||
state: GeneticState::Initialize,
|
||||
generation: 1,
|
||||
max_generations: 10,
|
||||
id: genetic_node.id(),
|
||||
};
|
||||
|
||||
|
@ -243,15 +242,17 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_from() -> Result<(), Error> {
|
||||
let val = TestState { score: 0.0 };
|
||||
let val = TestState {
|
||||
score: 0.0,
|
||||
max_generations: 10,
|
||||
};
|
||||
let uuid = Uuid::new_v4();
|
||||
let genetic_node = GeneticNodeWrapper::from(val.clone(), 10, uuid);
|
||||
let genetic_node = GeneticNodeWrapper::from(val.clone(), uuid);
|
||||
|
||||
let other_genetic_node = GeneticNodeWrapper::<TestState> {
|
||||
node: Some(val),
|
||||
state: GeneticState::Simulate,
|
||||
generation: 1,
|
||||
max_generations: 10,
|
||||
id: genetic_node.id(),
|
||||
};
|
||||
|
||||
|
@ -262,9 +263,12 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_as_ref() -> Result<(), Error> {
|
||||
let val = TestState { score: 3.0 };
|
||||
let val = TestState {
|
||||
score: 3.0,
|
||||
max_generations: 10,
|
||||
};
|
||||
let uuid = Uuid::new_v4();
|
||||
let genetic_node = GeneticNodeWrapper::from(val.clone(), 10, uuid);
|
||||
let genetic_node = GeneticNodeWrapper::from(val.clone(), uuid);
|
||||
|
||||
let ref_value = genetic_node.as_ref().unwrap();
|
||||
|
||||
|
@ -275,9 +279,12 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_id() -> Result<(), Error> {
|
||||
let val = TestState { score: 3.0 };
|
||||
let val = TestState {
|
||||
score: 3.0,
|
||||
max_generations: 10,
|
||||
};
|
||||
let uuid = Uuid::new_v4();
|
||||
let genetic_node = GeneticNodeWrapper::from(val.clone(), 10, uuid);
|
||||
let genetic_node = GeneticNodeWrapper::from(val.clone(), uuid);
|
||||
|
||||
let id_value = genetic_node.id();
|
||||
|
||||
|
@ -286,24 +293,14 @@ mod tests {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_max_generations() -> Result<(), Error> {
|
||||
let val = TestState { score: 3.0 };
|
||||
let uuid = Uuid::new_v4();
|
||||
let genetic_node = GeneticNodeWrapper::from(val.clone(), 10, uuid);
|
||||
|
||||
let max_generations = genetic_node.max_generations();
|
||||
|
||||
assert_eq!(max_generations, 10);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_state() -> Result<(), Error> {
|
||||
let val = TestState { score: 3.0 };
|
||||
let val = TestState {
|
||||
score: 3.0,
|
||||
max_generations: 10,
|
||||
};
|
||||
let uuid = Uuid::new_v4();
|
||||
let genetic_node = GeneticNodeWrapper::from(val.clone(), 10, uuid);
|
||||
let genetic_node = GeneticNodeWrapper::from(val.clone(), uuid);
|
||||
|
||||
let state = genetic_node.state();
|
||||
|
||||
|
@ -314,7 +311,7 @@ mod tests {
|
|||
|
||||
#[tokio::test]
|
||||
async fn test_process_node() -> Result<(), Error> {
|
||||
let mut genetic_node = GeneticNodeWrapper::<TestState>::new(2);
|
||||
let mut genetic_node = GeneticNodeWrapper::<TestState>::new();
|
||||
|
||||
assert_eq!(genetic_node.state(), GeneticState::Initialize);
|
||||
assert_eq!(genetic_node.process_node(()).await?, GeneticState::Simulate);
|
||||
|
|
|
@ -57,7 +57,6 @@ type SimulationTree<T> = Box<Tree<GeneticNodeWrapper<T>>>;
|
|||
/// ```
|
||||
#[derive(Serialize, Deserialize, Copy, Clone)]
|
||||
pub struct GemlaConfig {
|
||||
pub generations_per_height: u64,
|
||||
pub overwrite: bool,
|
||||
}
|
||||
|
||||
|
@ -126,9 +125,9 @@ where
|
|||
// Before we can process nodes we must create blank nodes in their place to keep track of which nodes have been processed
|
||||
// in the tree and which nodes have not.
|
||||
self.data
|
||||
.mutate(|(d, c, _)| {
|
||||
.mutate(|(d, _, _)| {
|
||||
let mut tree: Option<SimulationTree<T>> =
|
||||
Gemla::increase_height(d.take(), c, steps);
|
||||
Gemla::increase_height(d.take(), steps);
|
||||
mem::swap(d, &mut tree);
|
||||
})
|
||||
.await?;
|
||||
|
@ -268,11 +267,7 @@ where
|
|||
gemla_context.clone(),
|
||||
)
|
||||
.await?;
|
||||
tree.val = GeneticNodeWrapper::from(
|
||||
*merged_node,
|
||||
tree.val.max_generations(),
|
||||
tree.val.id(),
|
||||
);
|
||||
tree.val = GeneticNodeWrapper::from(*merged_node, tree.val.id());
|
||||
}
|
||||
}
|
||||
(Some(l), Some(r)) => {
|
||||
|
@ -284,11 +279,7 @@ where
|
|||
trace!("Copying node {}", l.val.id());
|
||||
|
||||
if let Some(left_node) = l.val.as_ref() {
|
||||
GeneticNodeWrapper::from(
|
||||
left_node.clone(),
|
||||
tree.val.max_generations(),
|
||||
tree.val.id(),
|
||||
);
|
||||
GeneticNodeWrapper::from(left_node.clone(), tree.val.id());
|
||||
}
|
||||
}
|
||||
(Some(l), None) => Gemla::merge_completed_nodes(l, gemla_context.clone()).await?,
|
||||
|
@ -296,11 +287,7 @@ where
|
|||
trace!("Copying node {}", r.val.id());
|
||||
|
||||
if let Some(right_node) = r.val.as_ref() {
|
||||
tree.val = GeneticNodeWrapper::from(
|
||||
right_node.clone(),
|
||||
tree.val.max_generations(),
|
||||
tree.val.id(),
|
||||
);
|
||||
tree.val = GeneticNodeWrapper::from(right_node.clone(), tree.val.id());
|
||||
}
|
||||
}
|
||||
(None, Some(r)) => Gemla::merge_completed_nodes(r, gemla_context.clone()).await?,
|
||||
|
@ -353,11 +340,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn increase_height(
|
||||
tree: Option<SimulationTree<T>>,
|
||||
config: &GemlaConfig,
|
||||
amount: u64,
|
||||
) -> Option<SimulationTree<T>> {
|
||||
fn increase_height(tree: Option<SimulationTree<T>>, amount: u64) -> Option<SimulationTree<T>> {
|
||||
if amount == 0 {
|
||||
tree
|
||||
} else {
|
||||
|
@ -365,13 +348,11 @@ where
|
|||
tree.as_ref().map(|t| t.height() as u64).unwrap_or(0) + amount - 1;
|
||||
|
||||
Some(Box::new(Tree::new(
|
||||
GeneticNodeWrapper::new(config.generations_per_height),
|
||||
Gemla::increase_height(tree, config, amount - 1),
|
||||
GeneticNodeWrapper::new(),
|
||||
Gemla::increase_height(tree, amount - 1),
|
||||
// The right branch height has to equal the left branches total height
|
||||
if left_branch_height > 0 {
|
||||
Some(Box::new(btree!(GeneticNodeWrapper::new(
|
||||
left_branch_height * config.generations_per_height
|
||||
))))
|
||||
Some(Box::new(btree!(GeneticNodeWrapper::new())))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
|
@ -446,6 +427,7 @@ mod tests {
|
|||
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
|
||||
struct TestState {
|
||||
pub score: f64,
|
||||
pub max_generations: u64,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
@ -454,10 +436,10 @@ mod tests {
|
|||
|
||||
async fn simulate(
|
||||
&mut self,
|
||||
_context: GeneticNodeContext<Self::Context>,
|
||||
) -> Result<(), Error> {
|
||||
context: GeneticNodeContext<Self::Context>,
|
||||
) -> Result<bool, Error> {
|
||||
self.score += 1.0;
|
||||
Ok(())
|
||||
Ok(context.generation < self.max_generations)
|
||||
}
|
||||
|
||||
async fn mutate(
|
||||
|
@ -470,7 +452,10 @@ mod tests {
|
|||
async fn initialize(
|
||||
_context: GeneticNodeContext<Self::Context>,
|
||||
) -> Result<Box<TestState>, Error> {
|
||||
Ok(Box::new(TestState { score: 0.0 }))
|
||||
Ok(Box::new(TestState {
|
||||
score: 0.0,
|
||||
max_generations: 10,
|
||||
}))
|
||||
}
|
||||
|
||||
async fn merge(
|
||||
|
@ -498,10 +483,7 @@ mod tests {
|
|||
assert!(!path.exists());
|
||||
|
||||
// Testing initial creation
|
||||
let mut config = GemlaConfig {
|
||||
generations_per_height: 1,
|
||||
overwrite: true,
|
||||
};
|
||||
let mut config = GemlaConfig { overwrite: true };
|
||||
let mut gemla = Gemla::<TestState>::new(&p, config, DataFormat::Json).await?;
|
||||
|
||||
// Now we can use `.await` within the spawned blocking task.
|
||||
|
@ -559,10 +541,7 @@ mod tests {
|
|||
CleanUp::new(&path).run(move |p| {
|
||||
rt.block_on(async {
|
||||
// Testing initial creation
|
||||
let config = GemlaConfig {
|
||||
generations_per_height: 10,
|
||||
overwrite: true,
|
||||
};
|
||||
let config = GemlaConfig { overwrite: true };
|
||||
let mut gemla = Gemla::<TestState>::new(&p, config, DataFormat::Json).await?;
|
||||
|
||||
// Now we can use `.await` within the spawned blocking task.
|
||||
|
|
Loading…
Add table
Reference in a new issue