Commit f4871af1 authored by Romain Reuillon's avatar Romain Reuillon

[Plugin + Doc] enh: singularize objectives -> objective

parent 1355e796
......@@ -79,7 +79,7 @@ $model
// Construction of the workflow orchestrating the genetic algorithm
// genome is the inputs prototype and their variation ranges
// objectives are the objectives to minimize
// objective sets the objectives to minimize
// termination is the termination criterion, here it runs for 100 generations. A time limit could be set as an
// alternative by replacing 100 by 1 hour (hour is a duration type understood by OpenMOLE).
// the parallelism specifies how many evaluation are concurrently submitted to the execution environment
......@@ -89,7 +89,7 @@ val evolution =
x in (0.0, 1.0),
y in (0.0, 1.0),
s in List("apple", "banana", "strawberry")),
objectives = Seq(o1, o2),
objective = Seq(o1, o2),
evaluation = model,
parallelism = 10,
termination = 100
......@@ -115,7 +115,7 @@ NSGA2Evolution(
x in (0.0, 1.0),
y in (0.0, 1.0),
s in List("apple", "banana", "strawberry")),
objectives = Seq(o1, o2),
objective = Seq(o1, o2),
evaluation = model -- DeltaTask(o1 -> math.Pi, o2 -> 42),
parallelism = 10,
termination = 100
......@@ -143,7 +143,7 @@ NSGA2Evolution(
x in (0.0, 1.0),
y in (0.0, 1.0),
s in List("apple", "banana", "strawberry")),
objectives = Seq(o1, o2),
objective = Seq(o1, o2),
evaluation = model -- maximize,
parallelism = 10,
termination = 100) hook (workDirectory / "evolution")""", name = "nsga2 maximize example")
......
......@@ -48,7 +48,7 @@ This task takes three parameters:
val evolution =
NSGA2Evolution(
genome = Seq(x in (0.0, 1.0), y in (0.0, 1.0)),
objectives = Seq(o1, o2),
objective = Seq(o1, o2),
evaluation = model,
termination = 10000,
parallelism = 100,
......
......@@ -36,7 +36,7 @@ In case you want to explore a stochastic model with a GA you can do:
NSGA2Evolution(
mu = 100, // mu is the size of the population
genome = Seq(x in (0.0, 1.0), y in (0.0, 1.0)), // genome (of individuals) is the inputs prototype and their variation ranges
objectives = Seq(o1, o2), // objectives are the objectives to minimise
objective = Seq(o1, o2), // objective sets the objectives to minimise
// OpenMOLE provide a seed for your stochastic model to use (it is optional)
// 20% of the evaluations are used for replicating existing solutions
// 100 replication are stored at max for each individual
......
......@@ -99,7 +99,7 @@ It takes the following parameters:
@ul
@li{@code{evaluation}: the OpenMOLE task that runs the simulation (@i{i.e.} the model),}
@li{@code{objectives}: a list of the distance measures (which in the single criterion case will contain only one measure),}
@li{@code{objective}: a list of the distance measures (which in the single criterion case will contain only one measure),}
@li{@code{mu}: the population size,}
@li{@code{genome}: a list of the model parameters and their respective variation intervals,}
@li{@code{termination}: the total number of evaluations (execution of the task passed to the parameter "evaluation") to be executed,}
......@@ -148,7 +148,7 @@ val distance2 = Val[Double]
NSGA2Evolution(
evaluation = modelTask,
objectives = Seq(distance1, distance2),
objective = Seq(distance1, distance2),
mu = 200,
genome = Seq(
param1 in (0.0, 99.0),
......@@ -175,7 +175,7 @@ val model = ScalaTask("val distance = param1.sum * param2") set (inputs += (para
NSGA2Evolution(
evaluation = model ,
objectives = Seq(distance),
objective = Seq(distance),
mu = 200,
genome = Seq(
param1 in Array.fill(100)(0.0, 99.0),
......
......@@ -31,7 +31,7 @@ OSEEvolution(
origin = Seq(
param1 in (0.0 to 1.0 by 0.1),
param2 in (-10.0 to 10.0 by 1.0)),
objectives = Seq(
objective = Seq(
output1 under 5.0,
output2 under 50.0),
stochastic = Stochastic(seed = myseed)
......@@ -39,4 +39,4 @@ OSEEvolution(
""", name = "OSE", header = "val modelTask = EmptyTask()")
@i{origin} describes the discrete space of possible origins. Each cell is considered a potential origin. @i{objectives} describe the pattern to reach with inequalities. The sought patten is considered as reached when all the objective are under their threshold value. In this example OSE computes a maximal diversity of inputs for which all the outputs are under their respective threshold values.
\ No newline at end of file
@i{origin} describes the discrete space of possible origins. Each cell is considered a potential origin. @i{objective} describe the pattern to reach with inequalities. The sought patten is considered as reached when all the objective are under their threshold value. In this example OSE computes a maximal diversity of inputs for which all the outputs are under their respective threshold values.
\ No newline at end of file
......@@ -55,7 +55,7 @@ It takes the following parameters:
@li{@code{parallelism} the number of simulations that will be run in parallel,}
@li{@code{termination} the total number of evaluations to be executed,}
@li{@code{genome} a list of the model parameters and their respective variation intervals,}
@li{@code{objectives} a list of indicators measured for each evaluation of the model within which we search for diversity, with a discretization step,}
@li{@code{objective} a list of indicators measured for each evaluation of the model within which we search for diversity, with a discretization step,}
@li{@code{stochastic} the seed generator, which generates suitable seeds for the method. Mandatory if your model contains randomness. The generated seed for the model task is transmitted through the variable given as an argument of @code{Stochastic} (here myseed).}
@li{@code{reject}: (optional) a predicate which is true for genomes that must be rejected by the genome sampler (for instance "i1 > 50").}
......@@ -99,7 +99,7 @@ PSEEvolution(
genome = Seq(
param1 in (0.0, 1.0),
param2 in (-10.0, 10.0)),
objectives = Seq(
objective = Seq(
output1 in (0.0 to 40.0 by 5.0),
output2 in (0.0 to 4000.0 by 50.0)),
stochastic = Stochastic(seed = myseed)
......
......@@ -34,11 +34,11 @@ val o = Val[Int]
val d = Val[Double]
// Define the sampling by mapping the columns of the CSV file to OpenMOLE variables
val mySampling = CSVSampling(workDirectory / "file.csv") set (
// comma ',' is the default separator, but you can specify a different one using
val mySampling = CSVSampling(workDirectory / "file.csv", separator = ',') set (
outputs += i.mapped,
outputs += d mapped "colD",
// comma ',' is the default separator, but you can specify a different one using
separator := ','
)
// Define the model, here it just takes i as input
......
......@@ -114,7 +114,7 @@ val exploration =
) hook(
output = display,
values = Seq(i),
arrayOnRow = true)
format = CSVOutputFormat(arrayOnRow = true))
""", header = "val myModel = EmptyTask()", name = "hook direct sampling")
@br
......
......@@ -15,16 +15,16 @@
val food3 = Val[Double]
// Define the NetlogoTask
val cmds = Seq("run-to-grid")
val ants =
NetLogo5Task(workDirectory / "Ants.nlogo", cmds, seed = seed) set (
NetLogo5Task(workDirectory / "Ants.nlogo", go = Seq("run-to-grid"), seed = seed) set (
// Map the OpenMOLE variables to NetLogo variables
netLogoInputs += (gPopulation, "gpopulation"),
netLogoInputs += (gDiffusionRate, "gdiffusion-rate"),
netLogoInputs += (gEvaporationRate, "gevaporation-rate"),
netLogoOutputs += ("final-ticks-food1", food1),
netLogoOutputs += ("final-ticks-food2", food2),
netLogoOutputs += ("final-ticks-food3", food3),
inputs += gPopulation mapped "gpopulation",
inputs += gDiffusionRate mapped "gdiffusion-rate",
inputs += gEvaporationRate mapped "gevaporation-rate",
outputs += food1 mapped "final-ticks-food1",
outputs += food2 mapped "final-ticks-food2",
outputs += food3 mapped "final-ticks-food3",
// Define default values for inputs of the model
seed := 42,
gPopulation := 125.0,
......@@ -32,7 +32,6 @@
gEvaporationRate := 50
)"""
@p
This example presents how to explore a NetLogo model step by step with an Evolutionary/Genetic Algorithm (EA/GA) in
OpenMOLE.
......@@ -129,38 +128,28 @@ This script describes how to use the NSGA2 multi-objective optimisation algorith
The result files are written to @hl.highlight("/tmp/ants", "plain").
Notice how the @hl.highlight("evaluation", "plain") parameter of the @hl.highlight("SteadyStateEvolution", "plain")
method, is the netlogo task i.e. running the model, which indeed provides an @b{evaluation} of the genome
(parameter settings) efficiency regarding the @hl.highlight("objectives","plain").
(parameter settings) efficiency regarding the @hl.highlight("objective","plain").
@br @hl.openmole("""
// Define the population size: 100.
// Define the inputs and their respective variation bounds.
// Define the objectives to minimize.
// Tell OpenMOLE that this model is stochastic and that it should generate a seed for each execution
// Define the fitness evaluation
// Define the parallelism level
// Terminate after 10000 evaluations
val evolution =
SteadyStateEvolution(
// Define the population (10) and the number of generations (100).
// Define the inputs and their respective variation bounds.
// Define the objectives to minimize.
algorithm =
NSGA2(
mu = 100,
genome = Seq(gDiffusionRate in (0.0, 99.0), gEvaporationRate in (0.0, 99.0)),
objectives = Seq(food1, food2, food3),
stochastic = Stochastic(seed = seed)
),
evaluation = ants,
parallelism = 10,
termination = 1000
)
// Define a hook to save the Pareto frontier
evolution hook (workDirectory / "results")
NSGA2Evolution(
// Define the inputs and their respective variation bounds.
// Define the objectives to minimize.
genome = Seq(gDiffusionRate in (0.0, 99.0), gEvaporationRate in (0.0, 99.0)),
objective = Seq(food1, food2, food3),
stochastic = Stochastic(seed = seed),
evaluation = ants,
parallelism = 10,
termination = 1000
) hook (workDirectory / "results")
""", header = model, name = "ga netlogo evolution")
@h2{Scale up}
If you use distributed computing, it might be a good idea to opt for an Island model. Islands are better suited to
......@@ -169,30 +158,17 @@ script changes to implement islands in the workflow. Here we compute 2,000 islan
1 hour on the European grid:
@br @hl.openmole("""
val evolution =
SteadyStateEvolution(
algorithm =
NSGA2(
mu = 100,
genome = Seq(gDiffusionRate in (0.0, 99.0), gEvaporationRate in (0.0, 99.0)),
objectives = Seq(food1, food2, food3),
stochastic = Stochastic(seed = seed)
),
evaluation = ants,
termination = 1 hour
)
// Define the execution environment
val env = EGIEnvironment("vo.complex-systems.eu")
// Define the island model with 1,000 concurrent islands. Each island gets 50 individuals sampled from the global
// population. The algorithm stops after 100,000 islands evaluations.
val island =
IslandEvolution(
evolution,
parallelism = 1000,
termination = 100000
)
// Define the execution environment
val env = EGIEnvironment("biomed", openMOLEMemory = 1200 megabytes, cpuTime = 4 hours)
// Define the workflow
island on env hook (workDirectory / "results")""", header = model, name = "ga netlogo islands")
NSGA2Evolution(
genome = Seq(gDiffusionRate in (0.0, 99.0), gEvaporationRate in (0.0, 99.0)),
objective = Seq(food1, food2, food3),
stochastic = Stochastic(seed = seed),
evaluation = ants,
termination = 100000,
parallelism = 1000,
distribution = Island(1 hour)
) on env hook (workDirectory / "results")""", header = model, name = "ga netlogo islands")
......@@ -21,9 +21,10 @@ object CSVHook {
exclude: Seq[Val[_]] = Vector.empty,
header: OptionalArgument[FromContext[String]] = None,
unrollArray: Boolean = false,
arrayOnRow: Boolean = false,
overwrite: Boolean = false)(implicit name: sourcecode.Name, definitionScope: DefinitionScope): FromContextHook =
FormattedFileHook(
format = CSVOutputFormat(header = header, unrollArray = unrollArray, append = !overwrite),
format = CSVOutputFormat(header = header, unrollArray = unrollArray, append = !overwrite, arrayOnRow = arrayOnRow),
output = output,
values = values,
exclude = exclude,
......
......@@ -54,8 +54,8 @@ object Metadata {
}
case class NoisyObjectiveData(
name: String,
delta: Option[Double],
name: String,
delta: Option[Double],
negative: Boolean)
def fromString(s: String): Metadata =
......
......@@ -232,14 +232,14 @@ object NSGA2 {
def apply[P](
genome: Genome,
objectives: Objectives,
objective: Objectives,
mu: Int = 200,
stochastic: OptionalArgument[Stochastic] = None,
reject: OptionalArgument[Condition] = None
): EvolutionWorkflow =
WorkflowIntegration.stochasticity(objectives, stochastic.option) match {
WorkflowIntegration.stochasticity(objective, stochastic.option) match {
case None
val exactObjectives = objectives.map(o Objective.toExact(o))
val exactObjectives = objective.map(o Objective.toExact(o))
val integration: WorkflowIntegration.DeterministicGA[_] = WorkflowIntegration.DeterministicGA(
DeterministicParams(mu, genome, exactObjectives, operatorExploration, reject),
genome,
......@@ -248,7 +248,7 @@ object NSGA2 {
WorkflowIntegration.DeterministicGA.toEvolutionWorkflow(integration)
case Some(stochasticValue)
val noisyObjectives = objectives.map(o Objective.toNoisy(o))
val noisyObjectives = objective.map(o Objective.toNoisy(o))
val integration: WorkflowIntegration.StochasticGA[_] = WorkflowIntegration.StochasticGA(
StochasticParams(mu, operatorExploration, genome, noisyObjectives, stochasticValue.replications, stochasticValue.reevaluate, reject.option),
......@@ -268,7 +268,7 @@ object NSGA2Evolution {
def apply(
genome: Genome,
objectives: Objectives,
objective: Objectives,
evaluation: DSL,
termination: OMTermination,
mu: Int = 200,
......@@ -283,7 +283,7 @@ object NSGA2Evolution {
NSGA2(
mu = mu,
genome = genome,
objectives = objectives,
objective = objective,
stochastic = stochastic,
reject = reject
),
......
......@@ -411,14 +411,14 @@ object NichedNSGA2 {
def apply[P](
niche: Seq[NichedElement],
genome: Genome,
objectives: Objectives,
objective: Objectives,
nicheSize: Int,
stochastic: OptionalArgument[Stochastic] = None,
reject: OptionalArgument[Condition] = None
): EvolutionWorkflow =
WorkflowIntegration.stochasticity(objectives, stochastic.option) match {
WorkflowIntegration.stochasticity(objective, stochastic.option) match {
case None
val exactObjectives = objectives.map(o Objective.toExact(o))
val exactObjectives = objective.map(o Objective.toExact(o))
val integration: WorkflowIntegration.DeterministicGA[_] = new WorkflowIntegration.DeterministicGA(
DeterministicParams(
genome = genome,
......@@ -434,7 +434,7 @@ object NichedNSGA2 {
WorkflowIntegration.DeterministicGA.toEvolutionWorkflow(integration)
case Some(stochasticValue)
val noisyObjectives = objectives.map(o Objective.toNoisy(o))
val noisyObjectives = objective.map(o Objective.toNoisy(o))
val integration: WorkflowIntegration.StochasticGA[_] = WorkflowIntegration.StochasticGA(
StochasticParams(
......@@ -465,7 +465,7 @@ object NichedNSGA2Evolution {
termination: OMTermination,
niche: Seq[NichedElement],
genome: Genome,
objectives: Objectives,
objective: Objectives,
nicheSize: Int,
stochastic: OptionalArgument[Stochastic] = None,
parallelism: Int = 1,
......@@ -479,7 +479,7 @@ object NichedNSGA2Evolution {
niche = niche,
genome = genome,
nicheSize = nicheSize,
objectives = objectives,
objective = objective,
stochastic = stochastic,
reject = reject
),
......
......@@ -277,14 +277,14 @@ object OSE {
def apply(
origin: Seq[OriginAxe],
objectives: Seq[FitnessPattern],
objective: Seq[FitnessPattern],
genome: Genome = Seq(),
mu: Int = 200,
stochastic: OptionalArgument[Stochastic] = None,
reject: OptionalArgument[Condition] = None): EvolutionWorkflow =
WorkflowIntegration.stochasticity(objectives.map(_.objective), stochastic.option) match {
WorkflowIntegration.stochasticity(objective.map(_.objective), stochastic.option) match {
case None
val exactObjectives = FitnessPattern.toObjectives(objectives).map(o Objective.toExact(o))
val exactObjectives = FitnessPattern.toObjectives(objective).map(o Objective.toExact(o))
val fg = OriginAxe.fullGenome(origin, genome)
val integration: WorkflowIntegration.DeterministicGA[_] =
......@@ -294,7 +294,7 @@ object OSE {
origin = OriginAxe.toOrigin(origin, genome),
genome = fg,
objectives = exactObjectives,
limit = FitnessPattern.toLimit(objectives),
limit = FitnessPattern.toLimit(objective),
operatorExploration = operatorExploration,
reject = reject.option),
fg,
......@@ -304,7 +304,7 @@ object OSE {
WorkflowIntegration.DeterministicGA.toEvolutionWorkflow(integration)
case Some(stochasticValue)
val fg = OriginAxe.fullGenome(origin, genome)
val noisyObjectives = FitnessPattern.toObjectives(objectives).map(o Objective.toNoisy(o))
val noisyObjectives = FitnessPattern.toObjectives(objective).map(o Objective.toNoisy(o))
val integration: WorkflowIntegration.StochasticGA[_] =
WorkflowIntegration.StochasticGA(
......@@ -313,7 +313,7 @@ object OSE {
origin = OriginAxe.toOrigin(origin, genome),
genome = fg,
objectives = noisyObjectives,
limit = FitnessPattern.toLimit(objectives),
limit = FitnessPattern.toLimit(objective),
operatorExploration = operatorExploration,
historySize = stochasticValue.replications,
cloneProbability = stochasticValue.reevaluate,
......@@ -334,7 +334,7 @@ object OSEEvolution {
def apply(
origin: Seq[OSE.OriginAxe],
objectives: Seq[OSE.FitnessPattern],
objective: Seq[OSE.FitnessPattern],
evaluation: DSL,
termination: OMTermination,
mu: Int = 200,
......@@ -350,7 +350,7 @@ object OSEEvolution {
OSE(
origin = origin,
genome = genome,
objectives = objectives,
objective = objective,
stochastic = stochastic,
mu = mu,
reject = reject
......
......@@ -418,17 +418,17 @@ object PSE {
def apply(
genome: Genome,
objectives: Seq[PatternAxe],
objective: Seq[PatternAxe],
stochastic: OptionalArgument[Stochastic] = None,
reject: OptionalArgument[Condition] = None
) =
WorkflowIntegration.stochasticity(objectives.map(_.p), stochastic.option) match {
WorkflowIntegration.stochasticity(objective.map(_.p), stochastic.option) match {
case None
val exactObjectives = objectives.map(o Objective.toExact(o.p))
val exactObjectives = objective.map(o Objective.toExact(o.p))
val integration: WorkflowIntegration.DeterministicGA[_] = WorkflowIntegration.DeterministicGA(
DeterministicParams(
mgo.evolution.niche.irregularGrid(objectives.map(_.scale).toVector),
mgo.evolution.niche.irregularGrid(objective.map(_.scale).toVector),
genome,
exactObjectives,
operatorExploration,
......@@ -438,11 +438,11 @@ object PSE {
WorkflowIntegration.DeterministicGA.toEvolutionWorkflow(integration)
case Some(stochasticValue)
val noisyObjectives = objectives.map(o Objective.toNoisy(o.p))
val noisyObjectives = objective.map(o Objective.toNoisy(o.p))
val integration: WorkflowIntegration.StochasticGA[_] = WorkflowIntegration.StochasticGA(
StochasticParams(
pattern = mgo.evolution.niche.irregularGrid(objectives.map(_.scale).toVector),
pattern = mgo.evolution.niche.irregularGrid(objective.map(_.scale).toVector),
genome = genome,
objectives = noisyObjectives,
historySize = stochasticValue.replications,
......@@ -464,7 +464,7 @@ object PSEEvolution {
def apply(
genome: Genome,
objectives: Seq[PSE.PatternAxe],
objective: Seq[PSE.PatternAxe],
evaluation: DSL,
termination: OMTermination,
stochastic: OptionalArgument[Stochastic] = None,
......@@ -477,7 +477,7 @@ object PSEEvolution {
algorithm =
PSE(
genome = genome,
objectives = objectives,
objective = objective,
stochastic = stochastic,
reject = reject
),
......
......@@ -40,7 +40,7 @@ object Profile {
NichedNSGA2(
Vector(NichedNSGA2.NichedElement.Continuous(x, nX)),
genome,
objectives = Seq(objective),
objective = Seq(objective),
nicheSize = nicheSize.option.getOrElse(1),
reject = reject
)
......
......@@ -46,7 +46,7 @@ class WorkflowSpec extends FlatSpec with Matchers {
algorithm =
NSGA2(
genome = Seq(x in (0.0, 1.0), y in ("0.0", "1.0")),
objectives = Seq(x, y),
objective = Seq(x, y),
stochastic = Stochastic()
),
evaluation = puzzle,
......@@ -71,7 +71,7 @@ class WorkflowSpec extends FlatSpec with Matchers {
algorithm =
PSE(
genome = Seq(population in (0.0, 1.0), state in ("0.0", "1.0")),
objectives =
objective =
Seq(
population in (0.0 to 1.0 by 0.1),
state in (0.0 to 1.0 by 0.1)
......@@ -91,7 +91,7 @@ class WorkflowSpec extends FlatSpec with Matchers {
NSGA2(
mu = 200,
genome = Seq(xArray in Vector.fill(5)((0.0, 1.0)), yArray in Vector.fill(5)(("0", "1"))),
objectives = Seq()
objective = Seq()
)
}
......@@ -130,7 +130,7 @@ class WorkflowSpec extends FlatSpec with Matchers {
val nsga = NSGA2Evolution(
evaluation = testTask,
objectives = Seq(a),
objective = Seq(a),
genome = Seq(a in (0.0, 1.0)),
termination = 100,
parallelism = 10
......@@ -155,7 +155,7 @@ class WorkflowSpec extends FlatSpec with Matchers {
val nsga = NSGA2Evolution(
evaluation = testTask,
objectives = Seq(a),
objective = Seq(a),
genome = Seq(a in (0.0, 1.0)),
termination = 100,
distribution = Island(5)
......@@ -213,7 +213,7 @@ class WorkflowSpec extends FlatSpec with Matchers {
val nsga = NSGA2Evolution(
evaluation = EmptyTask() set (inputs += a, outputs += b),
objectives = Seq(b),
objective = Seq(b),
genome = Seq(a in (0.0, 1.0)),
termination = 100
)
......@@ -228,7 +228,7 @@ class WorkflowSpec extends FlatSpec with Matchers {
def nsga(i: Int) =
NSGA2Evolution(
evaluation = EmptyTask() set (inputs += a, outputs += b),
objectives = Seq(b),
objective = Seq(b),
genome = Seq(a in (0.0, 1.0)),
termination = 100
)
......@@ -243,7 +243,7 @@ class WorkflowSpec extends FlatSpec with Matchers {
val nsga = NSGA2Evolution(
evaluation = EmptyTask() set (inputs += a, outputs += b),
objectives = Seq(b),
objective = Seq(b),
genome = Seq(a in (0.0, 1.0)),
termination = 100,
distribution = Island(1)
......@@ -258,7 +258,7 @@ class WorkflowSpec extends FlatSpec with Matchers {
val wf = NSGA2Evolution(
evaluation = EmptyTask() set (inputs += a, outputs += b),
objectives = Seq(b delta 1.0),
objective = Seq(b delta 1.0),
genome = Seq(a in (0.0, 1.0)),
termination = 100
)
......@@ -272,7 +272,7 @@ class WorkflowSpec extends FlatSpec with Matchers {