Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 2 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ itertools = "0.10"
tracing = { version = "0.1", default-features = false }
tracing-appender = "0.2"
tracing-subscriber = { version = "0.3", default-features = false, features = ["env-filter", "fmt", "json", "std"] }
gymnasia = { version = "1.0", default-features = false }
gymnasia = { version = "3.0", default-features = false }
uuid = { version = "1.2.2", features = ["v4", "serde"] }
clap = { version = "4.1.8", features = ["derive"] }
config = "0.13"
Expand Down
2 changes: 1 addition & 1 deletion crates/lgp-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
csv = "1.1"
itertools = "0.10"
gymnasia = { version = "1.0", default-features = false }
gymnasia = { version = "3.0", default-features = false }
rayon = "1.7"
tracing = { version = "0.1", features = ["attributes"] }
tracing-subscriber = { version = "0.3", default-features = false, features = ["env-filter", "fmt", "json", "std", "ansi"] }
Expand Down
2 changes: 1 addition & 1 deletion crates/lgp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ itertools = "0.10"
tracing = { version = "0.1", features = ["attributes"] }
tracing-appender = "0.2"
tracing-subscriber = { version = "0.3", default-features = false, features = ["env-filter", "fmt", "json", "std", "ansi"] }
gymnasia = { version = "1.0", default-features = false, optional = true }
gymnasia = { version = "3.0", default-features = false, optional = true }
uuid = { version = "1.2.2", features = ["v4", "serde"] }
clap = { version = "4.1.8", features = ["derive"] }
config = "0.13"
Expand Down
56 changes: 29 additions & 27 deletions crates/lgp/benches/performance_after_training.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,33 @@ use lgp::{
utils::benchmark_tools::load_and_run_program,
};

const TYPES: &[&str] = &[
"mountain_car_q",
"mountain_car_lgp",
"cart_pole_q",
"cart_pole_lgp",
/// Maps benchmark type to the config directory name used by the experiment runner.
const TYPES: &[(&str, &str)] = &[
("mountain_car_q", "mountain_car_with_q"),
("mountain_car_lgp", "mountain_car_lgp"),
("cart_pole_q", "cart_pole_with_q"),
("cart_pole_lgp", "cart_pole_lgp"),
];

fn performance_benchmark(c: &mut Criterion) {
let n_trials = 5;
let n_iterations = 100;

for program_type in TYPES {
for (program_type, config_dir) in TYPES {
let mut better_count = 0;
let mut improvement_values = Vec::with_capacity(n_iterations);

for path in glob(&format!(
"assets/experiments/**/benchmarks/{}/best.json",
program_type
))
.unwrap()
.flatten()
{
let parent = path.parent().unwrap().parent().unwrap().parent().unwrap();
let iteration_count = parent
.file_name()
.unwrap()
.to_str()
.unwrap()
.replace("iteration_", "")
.parse::<u32>()
.unwrap();

let bench_id = format!("perf_{}_iteration_{}", program_type, iteration_count);
let mut improvement_values = Vec::new();

let pattern = format!("outputs/{}/**/outputs/best.json", config_dir);

for path in glob(&pattern).unwrap().flatten() {
// Layout: outputs/<name>/<run_id>/outputs/best.json
let run_id = path
.parent()
.and_then(|p| p.parent())
.and_then(|p| p.file_name())
.and_then(|n| n.to_str())
.unwrap_or("unknown");

let bench_id = format!("perf_{}_{}", program_type, run_id);

c.bench_function(&bench_id, |b| {
b.iter(|| {
Expand Down Expand Up @@ -75,6 +69,14 @@ fn performance_benchmark(c: &mut Criterion) {
});
}

if improvement_values.is_empty() {
eprintln!(
"No benchmark data found for '{}' (glob: {}). Skipping.",
program_type, pattern
);
continue;
}

let mean =
improvement_values.iter().cloned().sum::<f64>() / improvement_values.len() as f64;
let median = {
Expand Down
3 changes: 1 addition & 2 deletions crates/lgp/examples/cart_pole.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
//!
//! Run with: `cargo run -p lgp-core --example cart_pole --features gym`

use itertools::Itertools;

use gymnasia::envs::classical_control::cartpole::CartPoleEnv;
use itertools::Itertools;

use lgp::core::engines::core_engine::HyperParametersBuilder;
use lgp::core::engines::status_engine::{Status, StatusEngine};
Expand Down
43 changes: 22 additions & 21 deletions crates/lgp/src/problems/gym.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use std::marker::PhantomData;

use gymnasia::core::Env;
use gymnasia::core::Flatten;
use gymnasia::core::StepResult;
use gymnasia::envs::classical_control::cartpole::CartPoleEnv;
use gymnasia::envs::classical_control::mountain_car::MountainCarEnv;
use gymnasia::utils::renderer::RenderMode;

use crate::core::engines::breed_engine::BreedEngine;
use crate::core::engines::core_engine::Core;
Expand All @@ -23,9 +24,9 @@ use crate::extensions::interactive::UseRlFitness;
use crate::extensions::q_learning::QProgram;
use crate::extensions::q_learning::QProgramGeneratorParameters;

pub trait GymRsEnvExt: Env<Action = usize> + Send + Sync
pub trait GymRsEnvExt: Env<Action = i64> + Clone + Send + Sync
where
Self::Observation: Copy + Into<Vec<f64>> + Send + Sync,
Self::Observation: Copy + Flatten + Send + Sync,
{
fn create() -> Self;
fn max_steps() -> usize;
Expand All @@ -34,7 +35,7 @@ where

impl GymRsEnvExt for CartPoleEnv {
fn create() -> Self {
CartPoleEnv::new(RenderMode::None)
CartPoleEnv::new()
}
fn max_steps() -> usize {
500
Expand All @@ -46,7 +47,7 @@ impl GymRsEnvExt for CartPoleEnv {

impl GymRsEnvExt for MountainCarEnv {
fn create() -> Self {
MountainCarEnv::new(RenderMode::None)
MountainCarEnv::new()
}
fn max_steps() -> usize {
200
Expand All @@ -59,7 +60,7 @@ impl GymRsEnvExt for MountainCarEnv {
#[derive(Clone, Debug)]
pub struct GymRsInput<E: GymRsEnvExt>
where
E::Observation: Copy + Into<Vec<f64>> + Send + Sync,
E::Observation: Copy + Flatten + Send + Sync,
{
environment: E,
terminated: bool,
Expand All @@ -71,19 +72,19 @@ where
impl<E> State for GymRsInput<E>
where
E: GymRsEnvExt,
E::Observation: Copy + Into<Vec<f64>> + Send + Sync,
E::Observation: Copy + Flatten + Send + Sync,
{
fn get_value(&self, idx: usize) -> f64 {
self.observation[idx]
}

fn execute_action(&mut self, action: usize) -> f64 {
let action_reward = self.environment.step(action);
let step_result: StepResult<E::Observation> = self.environment.step(action as i64);
self.episode_idx += 1;
self.observation = action_reward.observation.into();
self.observation = step_result.observation.flatten();
self.terminated =
self.episode_idx >= E::max_steps() || action_reward.done || action_reward.truncated;
action_reward.reward.into_inner()
self.episode_idx >= E::max_steps() || step_result.terminated || step_result.truncated;
step_result.reward
}

fn get(&mut self) -> Option<&mut Self> {
Expand All @@ -98,26 +99,26 @@ where
impl<T> RlState for GymRsInput<T>
where
T: GymRsEnvExt,
T::Observation: Copy + Into<Vec<f64>> + Send + Sync,
T::Observation: Copy + Flatten + Send + Sync,
{
fn is_terminal(&mut self) -> bool {
self.terminated
}

fn get_initial_state(&self) -> Vec<f64> {
self.initial_state.into()
self.initial_state.flatten()
}
}

impl<T> Reset<GymRsInput<T>> for ResetEngine
where
T: GymRsEnvExt,
T::Observation: Copy + Into<Vec<f64>> + Send + Sync,
T::Observation: Copy + Flatten + Send + Sync,
{
fn reset(item: &mut GymRsInput<T>) {
item.environment.reset(None, false, None);
item.environment.reset(None, Default::default());
item.environment.set_state(item.initial_state);
item.observation = item.initial_state.into();
item.observation = item.initial_state.flatten();
item.terminated = false;
item.episode_idx = 0;
}
Expand All @@ -126,12 +127,12 @@ where
impl<T> Generate<(), GymRsInput<T>> for GenerateEngine
where
T: GymRsEnvExt,
T::Observation: Copy + Into<Vec<f64>> + Send + Sync,
T::Observation: Copy + Flatten + Send + Sync,
{
fn generate(_from: ()) -> GymRsInput<T> {
let mut environment: T = T::create();
let (initial_state, _) = environment.reset(None, false, None);
let observation = initial_state.into();
let initial_state = environment.reset(None, Default::default());
let observation = initial_state.flatten();

GymRsInput {
environment,
Expand All @@ -151,7 +152,7 @@ pub struct GymRsEngine<T>(PhantomData<T>);
impl<T> Core for GymRsQEngine<T>
where
T: GymRsEnvExt,
T::Observation: Copy + Into<Vec<f64>> + Send + Sync,
T::Observation: Copy + Flatten + Send + Sync,
{
type Individual = QProgram;
type ProgramParameters = QProgramGeneratorParameters;
Expand All @@ -169,7 +170,7 @@ where
impl<T> Core for GymRsEngine<T>
where
T: GymRsEnvExt,
T::Observation: Copy + Into<Vec<f64>> + Send + Sync,
T::Observation: Copy + Flatten + Send + Sync,
{
type Individual = Program;
type ProgramParameters = ProgramGeneratorParameters;
Expand Down
Loading