Skip to content

Commit

Permalink
Merge branch 'main' into dup_sim
Browse files Browse the repository at this point in the history
  • Loading branch information
Leviathan321 authored Dec 11, 2024
2 parents 7f1c30c + bb8e619 commit 4781fb8
Show file tree
Hide file tree
Showing 12 changed files with 199 additions and 41 deletions.
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ jobs:
run: |
echo "Executing tests..."
pytest ./tests/test_experiments.py
pytest ./tests/test_default_experiments.py
deploy:
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ OpenSBTs Ecosystem
Releases
===============

- `0.1.7 <https://github.com/opensbt/opensbt-core/releases/tag/0.1.7>`_
- `0.1.6 <https://github.com/opensbt/opensbt-core/releases/tag/0.1.6>`_

Integrated Simulators
Expand Down
11 changes: 6 additions & 5 deletions opensbt/algorithm/nsga2_optimizer.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from opensbt.utils.operators import select_operator
from pymoo.core.problem import Problem
from pymoo.termination import get_termination
from pymoo.algorithms.moo.nsga2 import NSGA2
Expand All @@ -20,7 +21,6 @@ class NsgaIIOptimizer(Optimizer):

def __init__(self,
problem: Problem,

config: SearchConfiguration):
self.config = config
self.problem = problem
Expand All @@ -43,11 +43,12 @@ def __init__(self,
self.algorithm = NSGA2(
pop_size=config.population_size,
n_offsprings=config.num_offsprings,
sampling=FloatRandomSampling(),
crossover=SBX(prob=config.prob_crossover, eta=config.eta_crossover),
mutation=PM(prob=config.prob_mutation, eta=config.eta_mutation),
eliminate_duplicates=True,
sampling = select_operator("init", config),
crossover = select_operator("cx", config),
mutation = select_operator("mut", config),
eliminate_duplicates = select_operator("dup", config),
archive=MemoryArchive())
)

''' Prioritize max search time over set maximal number of generations'''
if config.maximal_execution_time is not None:
Expand Down
22 changes: 13 additions & 9 deletions opensbt/algorithm/nsga2dt_optimizer.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import random
from opensbt.model_ga.result import SimulationResult
from opensbt.evaluation.critical import Critical
from opensbt.utils.operators import select_operator
from pymoo.termination import get_termination
from pymoo.algorithms.moo.nsga2 import NSGA2
from pymoo.core.population import Population
Expand Down Expand Up @@ -126,11 +127,12 @@ def run(self) -> SimulationResult:
inner_algorithm = NSGA2(
pop_size=None,
n_offsprings=None,
sampling=None,
crossover=SBX(prob=prob_crossover, eta=eta_crossover),
mutation=PM(prob=prob_mutation, eta=eta_mutation),
eliminate_duplicates=True,
archive=MemoryArchive())
sampling = select_operator("init", config),
crossover = select_operator( "cx", config),
mutation = select_operator( "mut", config),
eliminate_duplicates = select_operator( "dup", config),
archive=MemoryArchive()
)

tree_iteration = 0
n_func_evals = 0
Expand All @@ -155,10 +157,12 @@ def run(self) -> SimulationResult:
pop_size=pop_size,
n_offsprings=num_offsprings,
sampling=initial_population,
crossover=SBX(prob=prob_crossover, eta=eta_crossover),
mutation=PM(prob=prob_mutation, eta=eta_mutation),
eliminate_duplicates=True,
archive=MemoryArchive())
crossover = select_operator("cx",config),
mutation = select_operator("mut", config),
eliminate_duplicates = select_operator( "dup", config),
archive=MemoryArchive()
)


termination = get_termination("n_gen", inner_num_gen)

Expand Down
4 changes: 4 additions & 0 deletions opensbt/algorithm/pso_optimizer.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from opensbt.utils.operators import select_operator
from pymoo.core.problem import Problem
from pymoo.termination import get_termination
from pymoo.algorithms.soo.nonconvex.pso import PSO
Expand Down Expand Up @@ -41,6 +42,9 @@ def __init__(self,
# initialize algorithm
self.algorithm = PSO(
pop_size=config.population_size,
archive = MemoryArchive(),
pop_size = config.population_size,
sampling = select_operator("init",config),
archive = MemoryArchive()
)

Expand Down
26 changes: 25 additions & 1 deletion opensbt/experiment/search_configuration.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from dataclasses import dataclass


@dataclass
class SearchConfiguration(object):
""" This class holds all configuration parameter related to opimization algorithms
"""
Expand All @@ -24,6 +27,16 @@ class SearchConfiguration(object):

seed = None

operators= {
"cx" : None,
"mut" : None,
"dup" : None,
"init" : None
}

custom_params = { # to be forwarded to operators

}

class DefaultSearchConfiguration(SearchConfiguration):
""" This class holds all configuration parameter initialized with default values
Expand All @@ -48,4 +61,15 @@ class DefaultSearchConfiguration(SearchConfiguration):
ref_point_hv = None
nadir = ref_point_hv

seed = None
seed = None

operators= {
"cx" : None,
"mut" : None,
"dup" : None,
"init" : None
}

custom_params = { # to be forwarded to operators

}
63 changes: 42 additions & 21 deletions opensbt/simulation/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,49 @@ class SimulationOutput(object):
"""
Class represents data output after execution of a simulation. An example JSON representation of a SimulationOutput instance is:
{
"simTime" : 3,
"times": [1.0,2.0,3.0],
"location": {
"ego" : [(1,1),(2,2),(3,3)],
"adversary" : [(4,1),(4,2),(4,3)
},
"velocity": {
"ego" : [0.5,0.5,0.5],
"adversary" : [0.9,0.9,0.9],
},
"collisions": [],
"actors" : {
1: "ego",
2: "adversary"
},
"otherParams" : {
"isCollision": False
},
...
{
"simTime": 10, // Simulation time
"times": [0.0, 0.1, 0.2, ... , 10.0 ], // Time steps; delta is not predefined
"location": {
"ego": [
[0.0, 0.0], [0.1, 0.1], ... // x,y positions for each time step
],
"adversary": [
[10.0, 0.0], [9.9, 0.1], ...
]
},
"velocity": {
"ego": [
[1,1,0], [1,1,0], ... // velocity vector for each time step
"adversary": [
[0,1,0], [0, 1, 1], ...
]
},
"speed": {
"ego": [1.4, 1.4, ... ], // magnitude of velocity vector (known as "speed") for each time step
"adversary": [1, 1, ... ]
},
"acceleration": {
"ego": [0.1, 0, ...],
"adversary": [0.05, 0, ...]
},
"yaw": { // heading in rad for each time step
"ego": [0.5, 0.5, ...],
"adversary": [0.2, 0.2, ...]
},
"collisions": [ // actor ids with timesteps if any collisions
],
"actors": { // type of actors mapped to ids; the actor types "ego" and "adversary" have to be assigned
"ego": "ego",
"adversary": "adversary",
"vehicles": [],
"pedestrians": []
},
"otherParams": { // store custom data
"car_width" : 3,
"car_length" : 5
}
}
"""
simTime: float
times: List
Expand Down
33 changes: 33 additions & 0 deletions opensbt/utils/operators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from pymoo.operators.crossover.sbx import SBX # type: ignore
from pymoo.operators.mutation.pm import PM # type: ignore
from pymoo.operators.sampling.lhs import LHS # type: ignore

def select_operator(operation,
config,
**kwargs):
"""
Selects either the default operator or a custom operator based on the condition.
"""
if kwargs is not None:
kwargs = {}

if config.operators[operation] is None:
if operation == "mut":
operator = PM
if "prob" not in kwargs:
kwargs["prob"] = config.prob_mutation
if "eta" not in kwargs:
kwargs["eta"] = config.eta_mutation
elif operation == "cx":
operator = SBX
if "prob" not in kwargs:
kwargs["prob"] = config.prob_crossover
if "eta" not in kwargs:
kwargs["eta"] = config.eta_crossover
elif operation == "init":
operator = LHS
elif operation == "dup":
return True
else:
operator = config.operators[operation]
return operator(**kwargs) # Passes the keyword arguments to the operator
2 changes: 1 addition & 1 deletion opensbt/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.1.6"
__version__ = "0.1.7"
2 changes: 1 addition & 1 deletion project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "OpenSBT"
version = "0.1.6"
version = "0.1.7"
authors = [
{name = "Lev Sorokin", email = "[email protected]"},
]
Expand Down
66 changes: 66 additions & 0 deletions tests/test_default_experiments.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import os
from pathlib import Path
import subprocess
from typing import Dict
import pymoo
import time

from examples.carla.carla_simulation import CarlaSimulator
from opensbt.experiment.experiment import Experiment
from opensbt.model_ga.individual import IndividualSimulated
from tests import test_base
pymoo.core.individual.Individual = IndividualSimulated

from opensbt.model_ga.population import PopulationExtended
pymoo.core.population.Population = PopulationExtended

from opensbt.model_ga.result import SimulationResult
pymoo.core.result.Result = SimulationResult

from opensbt.model_ga.problem import SimulationProblem
pymoo.core.problem.Problem = SimulationProblem

from opensbt.algorithm.nsga2_optimizer import NsgaIIOptimizer
from opensbt.evaluation.critical import CriticalAdasDistanceVelocity
from opensbt.experiment.search_configuration import DefaultSearchConfiguration
from opensbt.evaluation.fitness import FitnessMinDistanceVelocityFrontOnly
from opensbt.problem.adas_problem import ADASProblem

from opensbt.experiment.experiment_store import experiments_store
from default_experiments import *
import logging as log

class TestDefaultExperiments():

@staticmethod
def test_dummy_experiments_no_args():
""" Go over all predefined experiments and run them. Right now only experiments are tested that
do not require GPU access. I.e., CARLA based experiments are not tested. """

store : Dict[str, Experiment] = experiments_store.get_store()

assert len(store) > 0

for name, exp in store.items():
print(exp.problem)
if exp.problem.is_simulation() and exp.problem.simulate_function == CarlaSimulator.simulate:
continue
log.info("Starting experiment:", name)
if os.path.exists('.\\venv\\Scripts\\Activate'):
venv_path = '.\\venv\\Scripts\\Activate &&'
prefix = ['cmd', '/c']
elif os.path.exists('.\\venv\\bin\\activate'):
venv_path = '.\\venv\\bin\\activate &&'
prefix = ["source"]
else:
venv_path = ""
prefix = [""]

result = subprocess.run( prefix + [f'{venv_path} python',
'run.py', "-e", name],
shell=True,
capture_output=True,
text=True)
log.info("Finished experiment")

assert result.returncode == 0
9 changes: 6 additions & 3 deletions tests/test_experiments.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@ class TestExperiments():
WAIT_RESULTS_TIME = 10

@staticmethod
def results_correctly_written(result, results_path):
req_folders = ["simout", "gif", "trace_comparison", "design_space", "objective_space", "classification"]
def results_correctly_written(results_path):
req_folders = ["simout",
"gif",
"trace_comparison",
"design_space", "objective_space", "classification"]

for folder in req_folders:
if not os.path.isdir(results_path + folder):
Expand Down Expand Up @@ -83,5 +86,5 @@ def test_dummy_experiment():

time.sleep(TestExperiments.WAIT_RESULTS_TIME)

assert TestExperiments.results_correctly_written(result = res, results_path=results_path)
assert TestExperiments.results_correctly_written(results_path=results_path)

0 comments on commit 4781fb8

Please sign in to comment.