diff --git a/.travis.yml b/.travis.yml index cfcf63d..1a8e414 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,14 @@ services: jobs: include: + - stage: Build Sources + if: branch = master + language: scala + scala: + - 2.12.5 + script: + - sbt ++$TRAVIS_SCALA_VERSION compile tut + - stage: GitHub Release if: tag IS present before_install: diff --git a/README.md b/README.md index cf04ed4..d839da9 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Community tutorial for CIlib +[![Build Status](https://travis-ci.org/cirg-up/cilib-tutorial.svg?branch=master)](https://travis-ci.org/cirg-up/cilib-tutorial) + Welcome to the community tutorial source repository! ## About the tutorial diff --git a/build.sbt b/build.sbt index a0d67cd..eff0f0d 100644 --- a/build.sbt +++ b/build.sbt @@ -11,18 +11,54 @@ git.useGitDescribe := true scalacOptions ++= Seq( "-deprecation", - "-encoding", "UTF-8", - "-unchecked", - "-feature", - "-Xlint", -// "-Xfatal-warnings", - "-Ywarn-dead-code", - "-Ypartial-unification" -// "-Ydelambdafy:inline" // workaround for future deadlock on the 2.12.1 REPL + "-encoding", "utf-8", // Specify character encoding used by source files. + "-explaintypes", // Explain type errors in more detail. + "-feature", // Emit warning and location for usages of features that should be imported explicitly. + "-language:existentials", // Existential types (besides wildcard types) can be written and inferred + "-language:experimental.macros", // Allow macro definition (besides implementation and application) + "-language:higherKinds", // Allow higher-kinded types + "-language:implicitConversions", // Allow definition of implicit functions called views + "-unchecked", // Enable additional warnings where generated code depends on assumptions. + "-Xcheckinit", // Wrap field accessors to throw an exception on uninitialized access. + "-Xfatal-warnings", // Fail the compilation if there are any warnings. + "-Xfuture", // Turn on future language features. + "-Xlint:adapted-args", // Warn if an argument list is modified to match the receiver. + "-Xlint:by-name-right-associative", // By-name parameter of right associative operator. + "-Xlint:constant", // Evaluation of a constant arithmetic expression results in an error. + "-Xlint:delayedinit-select", // Selecting member of DelayedInit. + "-Xlint:doc-detached", // A Scaladoc comment appears to be detached from its element. + "-Xlint:inaccessible", // Warn about inaccessible types in method signatures. + "-Xlint:infer-any", // Warn when a type argument is inferred to be `Any`. + "-Xlint:missing-interpolator", // A string literal appears to be missing an interpolator id. + "-Xlint:nullary-override", // Warn when non-nullary `def f()' overrides nullary `def f'. + "-Xlint:nullary-unit", // Warn when nullary methods return Unit. + "-Xlint:option-implicit", // Option.apply used implicit view. + "-Xlint:package-object-classes", // Class or object defined in package object. + "-Xlint:poly-implicit-overload", // Parameterized overloaded implicit methods are not visible as view bounds. + "-Xlint:private-shadow", // A private field (or class parameter) shadows a superclass field. + "-Xlint:stars-align", // Pattern sequence wildcard must align with sequence component. + "-Xlint:type-parameter-shadow", // A local type parameter shadows a type already in scope. + "-Xlint:unsound-match", // Pattern match may not be typesafe. + "-Yno-adapted-args", // Do not adapt an argument list (either by inserting () or creating a tuple) to match the receiver. + "-Ypartial-unification", // Enable partial unification in type constructor inference + "-Ywarn-dead-code", // Warn when dead code is identified. + "-Ywarn-extra-implicit", // Warn when more than one implicit parameter section is defined. + "-Ywarn-inaccessible", // Warn about inaccessible types in method signatures. + "-Ywarn-infer-any", // Warn when a type argument is inferred to be `Any`. + "-Ywarn-nullary-override", // Warn when non-nullary `def f()' overrides nullary `def f'. + "-Ywarn-nullary-unit", // Warn when nullary methods return Unit. + "-Ywarn-numeric-widen", // Warn when numerics are widened. + "-Ywarn-unused:implicits", // Warn if an implicit parameter is unused. + "-Ywarn-unused:imports", // Warn if an import selector is not referenced. + "-Ywarn-unused:locals", // Warn if a local definition is unused. + "-Ywarn-unused:params", // Warn if a value parameter is unused. + "-Ywarn-unused:patvars", // Warn if a variable bound in a pattern is unused. + "-Ywarn-unused:privates", // Warn if a private member is unused. + "-Ywarn-value-discard" // Warn when non-Unit expression results are unused. ) -scalacOptions in Tut := (scalacOptions in Tut).value.filterNot(Set("-Ywarn-unused-import")) +scalacOptions in Tut := (scalacOptions in Tut).value.filterNot(Set("-Ywarn-unused-import", "-Ywarn-unused:imports")) libraryDependencies ++= Seq( "net.cilib" %% "cilib-core" % cilibVersion, @@ -42,8 +78,10 @@ lazy val epub = taskKey[Unit]("Build the ePub version of the book") lazy val json = taskKey[Unit]("Build the Pandoc JSON AST of the book") lazy val all = taskKey[Unit]("Build all versions of the book") -pdf := { tutQuick.value ; "grunt pdf" ! } -html := { tutQuick.value ; "grunt html" ! } -epub := { tutQuick.value ; "grunt epub" ! } -json := { tutQuick.value ; "grunt json" ! } +import scala.sys.process._ + +pdf := { tutQuick.value ; Seq("grunt", "pdf").! } +html := { tutQuick.value ; Seq("grunt", "html").! } +epub := { tutQuick.value ; Seq("grunt", "epub").! } +json := { tutQuick.value ; Seq("grunt", "json").! } all := { pdf.value ; html.value ; epub.value ; json.value } diff --git a/project/build.properties b/project/build.properties index 64317fd..0531343 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.15 +sbt.version=1.1.2 diff --git a/project/plugins.sbt b/project/plugins.sbt index 90d4a2b..2ca4d70 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,3 +1,3 @@ addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "0.9.3") -addSbtPlugin("org.tpolecat" % "tut-plugin" % "0.5.2") -addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC8") +addSbtPlugin("org.tpolecat" % "tut-plugin" % "0.6.4") +addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.1") diff --git a/src/pages/benchmarks/index.md b/src/pages/benchmarks/index.md index 1d4aa28..bdd5953 100644 --- a/src/pages/benchmarks/index.md +++ b/src/pages/benchmarks/index.md @@ -1,13 +1,16 @@ # Benchmarks -Often in computational intelligence we will need to test algorithms on standard problems. -It should be noted that CIRG contains a library of benchmarks that we can use with CILib. -The benchmarks can be found [here][benchmarks] as well as a list of available benchmarks. -To import benchmarks into your build you need the following dependency added to your sbt.build. +Often in computational intelligence we will need to test algorithms on +standard problems. It should be noted that CIRG contains a library of +benchmarks that we can use with CILib. The benchmarks can be found +[here][benchmarks] as well as a list of available benchmarks. To +import benchmarks into your build you need the following dependency +added to your sbt.build. ` "net.cilib" %% "benchmarks" % "0.1.1"` -The following snippets of code will demonstrate how to include benchmarks in your program as an example use. +The following snippets of code will demonstrate how to include +benchmarks in your program as an example use. ```tut:book:silent import cilib._ @@ -17,12 +20,13 @@ import spire.implicits._ import spire.math.Interval // Example use +val bounds = Interval(-5.12,5.12)^30 val env = Environment( cmp = Comparison.dominance(Min), - eval = Eval.unconstrained(Benchmarks.spherical[NonEmptyList, Double]).eval, - bounds = Interval(-5.12,5.12)^30) + eval = Eval.unconstrained(Benchmarks.spherical[NonEmptyList, Double]).eval) ``` -That's all there is to it! -Be sure to check out the list of benchmarks that are included and can be accessed by the `Benchmark` object. +That's all there is to it! Be sure to check out the list of +benchmarks that are included and can be accessed by the `Benchmark` +object. diff --git a/src/pages/constraint/object.md b/src/pages/constraint/object.md index 4046160..e2235be 100644 --- a/src/pages/constraint/object.md +++ b/src/pages/constraint/object.md @@ -45,9 +45,10 @@ import spire.implicits._ import spire.algebra.Eq val sumLessThanCons = LessThan(sumCF, 12.0) -val firstNumberCons = cilib.Equal(ConstraintFunction((l: NonEmptyList[Double]) => l.head), 4.0) // A constraint that ensures the first element of a list is 4 +val firstNumberCons = cilib.Equal(ConstraintFunction((l: NonEmptyList[Double]) => l.head), 4.0) ``` + ```tut:book Constraint.violationCount(List(sumLessThanCons, firstNumberCons), NonEmptyList(19.0, 37.23, 12.0)) Constraint.violationCount(List(sumLessThanCons, firstNumberCons), NonEmptyList(4.0, 3.0, 2.0)) @@ -60,4 +61,4 @@ Determines the magnitude of the number of violated constraints. ```tut:book Constraint.violationMagnitude(0.1, 0.9, List(sumLessThanCons, firstNumberCons), NonEmptyList(19.0, 37.23, 12.0)) -``` \ No newline at end of file +``` diff --git a/src/pages/position/maths.md b/src/pages/position/maths.md index f189ce8..6243820 100644 --- a/src/pages/position/maths.md +++ b/src/pages/position/maths.md @@ -10,17 +10,17 @@ import spire.math._ import scalaz._ import Scalaz._ ``` + ```tut:book:silent val rng = RNG.init(1234L) val e = Eval.unconstrained[NonEmptyList,Double](_.map(x => x*x).suml).eval val a = Position.createPosition(Interval(-5.12,5.12)^3).eval(rng) val b = Position.createPosition(Interval(-5.12,5.12)^3).flatMap(p => Position.eval(e, p)).eval(rng) ``` + ```tut:book a + b // Add Point and Solution a + a // Add Point and Point b + b // Add Solution and Solution a - b // Subtract Solution from Point - -// And so forth -``` \ No newline at end of file +``` diff --git a/src/pages/runner/GAexample.md b/src/pages/runner/GAexample.md index 4ec95b1..5bbfc16 100644 --- a/src/pages/runner/GAexample.md +++ b/src/pages/runner/GAexample.md @@ -1,8 +1,12 @@ ## Creating a GA Isn't this exciting! + All our work over the past chapters is coming together! -It should be noted that the only thing we will be using from `cilib-ga` is the type `Individual`, which, as we discussed before, is an `Enity` with a state of type `Unit` since GA's do not need a state. + +It should be noted that the only thing we will be using from +`cilib-ga` is the type `Individual`, which, as we discussed before, is +an `Enity` with a state of type `Unit` since GA's do not need a state. ### Imports @@ -20,26 +24,30 @@ import spire.math.Interval ### The Problem Environment -For our problem we are going to attempt to find the greatest area produced by a 2 dimensional rectangle. -The sides can range from 0.1 to 12. +For our problem we are going to attempt to find the greatest area +produced by a 2 dimensional rectangle. The sides can range from 0.1 +to 12. ```tut:book +val bounds = Interval(0.1, 12.0)^2 + val env = Environment( cmp = Comparison.dominance(Max), - eval = Eval.unconstrained[NonEmptyList,Double](_.foldLeft1(_ * _)).eval, - bounds = Interval(0.1, 12.0)^2 + eval = Eval.unconstrained[NonEmptyList,Double](_.foldLeft1(_ * _)).eval ) ``` ### The GA Algorithm The GA algorithm is the exact same one used in `cilib-ga`. -The reason we are intentionally defining it as opposed to importing it is so that we can see the inner workings and learn from it. + +The reason we are intentionally defining it as opposed to importing it +is so that we can see the inner workings and learn from it. ```scala def ga[S]( p_c: Double, - parentSelection: NonEmptyList[Individual[S]] => RVar[List[Individual[S]]], + parentSelection: NonEmptyList[Individual[S]] => RVar[List[Individual[S]]], crossover: List[Individual[S]] => RVar[List[Individual[S]]], mutation: List[Individual[S]] => RVar[List[Individual[S]]] ): NonEmptyList[Individual[S]] => Individual[S] => Step[Double,List[Individual[S]]] = @@ -64,22 +72,27 @@ crossover //is the function that we will use to produce off spring mutation //is the function we will use to mutate the offspring ``` -All right. Not too bad. -By being able to pass functions to a generic GA method allows us to build a GA specific to our needs. -It should also be noted that all the passable functions yield the same data type. -Now before we move to the actual implementation of the `ga` method, I would like to remind you that for comprehensions are essentially chained `flatMaps`. -This allows us to chain steps together. -So we know that this method will return a function of type +All right. Not too bad. By being able to pass functions to a generic +GA method allows us to build a GA specific to our needs. It should +also be noted that all the passable functions yield the same data +type. Now before we move to the actual implementation of the `ga` +method, I would like to remind you that for comprehensions are +essentially chained `flatMaps`. This allows us to chain steps +together. So we know that this method will return a function of type `NonEmptyList[Individual[S]] => Individual[S] => Step[Double,List[Individual[S]]]` -Which in simply means, that we are going to get a function that return a `Step` representing a series of computations applied to every `Individual` with a collection of `Individuals`. -Okay, so now we know what we are returning but let's see how we get to that by looking at the "series of computations". +Which in simply means, that we are going to get a function that return +a `Step` representing a series of computations applied to every +`Individual` with a collection of `Individuals`. Okay, so now we know +what we are returning but let's see how we get to that by looking at +the "series of computations". `parents <- Step.pointR(parentSelection(collection))` -Here we are selecting our parents from the collection using the parentSelection function that was passed as a parameter. -Lastly, it will be wrapped in a `Step`. +Here we are selecting our parents from the collection using the +parentSelection function that was passed as a parameter. Lastly, it +will be wrapped in a `Step`. `r <- Step.pointR(Dist.stdUniform.map(_ < p_c))` @@ -91,27 +104,36 @@ crossed <- else Step.point[Double,List[Individual[S]]](parents) ``` -If r is `true` we will produce crossovers based on the `parents` using the crossover function parameter, else we are going to just leave the parents as is. -How frequently the crossover occurs depends on your `p_c`. +If r is `true` we will produce crossovers based on the `parents` using +the crossover function parameter, else we are going to just leave the +parents as is. How frequently the crossover occurs depends on your +`p_c`. `mutated <- Step.pointR[Double,List[Individual[S]]](mutation(crossed))` -Nothing too complex here. We are simply mutating our ``crossed`` individuals using the mutation function parameter. -Also note that ``mutated`` will have a data type very similar tto our return type. +Nothing too complex here. We are simply mutating our ``crossed`` +individuals using the mutation function parameter. Also note that +``mutated`` will have a data type very similar tto our return type. `evaluated <- mutated.traverseU(x => Step.eval((v: Position[Double]) => v)(x))` -Lastly, we are taking every `Individual` from `mutated` and wrapping each one in an evaluation `Step`. -Remember that this is just a step representing evaluation, not actually evaluating the `Individuals` right now. +Lastly, we are taking every `Individual` from `mutated` and wrapping +each one in an evaluation `Step`. Remember that this is just a step +representing evaluation, not actually evaluating the `Individuals` +right now. Let's get to creating the functions we will be passing to our ga method. ### Selection Method -For our selection method we will be creating a random selection method. -We know that it needs to have the type `NonEmptyList[Individual[S]] => RVar[List[Individual[S]]]`. -To make this even easier to read we can include a custom type, `type Ind = Individual[Unit]`, making it `NonEmptyList[Ind] => RVar[List[Individual[S]]]`. -Create a function with the name `randomSelection` that will randomly select two `Inds` from an non empty list. +For our selection method we will be creating a random selection +method. We know that it needs to have the type +`NonEmptyList[Individual[S]] => RVar[List[Individual[S]]]`. To make +this even easier to read we can include a custom type, `type Ind = +Individual[Unit]`, making it `NonEmptyList[Ind] => +RVar[List[Individual[S]]]`. Create a function with the name +`randomSelection` that will randomly select two `Inds` from an non +empty list.
@@ -126,10 +148,14 @@ val randomSelection: NonEmptyList[Ind] => RVar[List[Ind]] = ### Selection Method -For our selection method we will be creating a random selection method. -We know that it needs to have the type `NonEmptyList[Individual[S]] => RVar[List[Individual[S]]]`. -To make this even easier to read we can include a custom type, `type Ind = Individual[Unit]`, making it `NonEmptyList[Ind] => RVar[List[Individual[S]]]`. -Create a function with the name `randomSelection` that will randomly select two `Inds` from an non empty list. +For our selection method we will be creating a random selection +method. We know that it needs to have the type +`NonEmptyList[Individual[S]] => RVar[List[Individual[S]]]`. To make +this even easier to read we can include a custom type, `type Ind = +Individual[Unit]`, making it `NonEmptyList[Ind] => +RVar[List[Individual[S]]]`. Create a function with the name +`randomSelection` that will randomly select two `Inds` from an non +empty list.
@@ -145,9 +171,11 @@ val randomSelection: NonEmptyList[Ind] => RVar[List[Ind]] = ### Crossover Method We will be creating a one point crossover method to be used in our GA. -It will need to have the type `List[Individual[S]] => RVar[List[Individual[S]]]` and let's call it `onePoint`. -There should be two `Individuals`, parents, in the list that will be used to create two new `Individuals` from a one point cross over. -Else we should output an error. +It will need to have the type `List[Individual[S]] => +RVar[List[Individual[S]]]` and let's call it `onePoint`. There should +be two `Individuals`, parents, in the list that will be used to create +two new `Individuals` from a one point cross over. Else we should +output an error.
```tut:book @@ -166,15 +194,17 @@ def onePoint(xs: List[Ind]): RVar[List[Ind]] = ### Mutation Method -Our mutation method will be relatively simply. -For every `Individual` we want to mutate it's position where each point in the position is mutated based on a `Boolean`. -If It is true, mutate the point by multiplying by a random number from a gaussian distribution. -Else leave it as it is. -This deciding `Boolean` is determined the same way r is in our `ga` method. -Except, that is compared with a double parameter, `p_m`, representing the mutation rate. -So you might need groups of parameters. -Call this method `mutation` and be aware of it's return type. -Also some helpful hints are to think about using `Lenses` and the `ModifyF` function, as well as `traverse` for sequencing through points ot a list. +Our mutation method will be relatively simply. For every `Individual` +we want to mutate it's position where each point in the position is +mutated based on a `Boolean`. If It is true, mutate the point by +multiplying by a random number from a gaussian distribution. Else +leave it as it is. This deciding `Boolean` is determined the same way +r is in our `ga` method. Except, that is compared with a double +parameter, `p_m`, representing the mutation rate. So you might need +groups of parameters. Call this method `mutation` and be aware of +it's return type. Also some helpful hints are to think about using +`Lenses` and the `ModifyF` function, as well as `traverse` for +sequencing through points ot a list.
```tut:book @@ -191,29 +221,31 @@ def mutation(p_m: Double)(xs: List[Ind]): RVar[List[Ind]] = ### My GA -Now that we have defined all those methods we should be able to construct our GA with the following line of code: +Now that we have defined all those methods we should be able to +construct our GA with the following line of code: `val myGA = ga(0.7, randomSelection, onePoint, mutation(0.2))` -Great! Remember that what we have here is still just a function. One that takes a collection of `Individuals` and returns a `Step`. +Great! Remember that what we have here is still just a function. One +that takes a collection of `Individuals` and returns a `Step`. `NonEmptyList[Ind] => Ind => Step[Double,List[Ind]]` ### Creating a Collection -We have the ga function, but not the collection. So let's go ahead and create that. Keep in mind that we are dealing with `Individuals` +We have the `myGA` function, but not the collection. So let's go ahead and +create that. Keep in mind that we are dealing with `Individuals` ```tut:book:invisible ```tut:book -val swarm = Position.createCollection[Ind](x => Entity((), x))(env.bounds, 20) +val swarm = Position.createCollection[Ind](x => Entity((), x))(bounds, 20) ``` ### Creating an Iterator -Here is where things get a little more interesting. -Remember the `Iteration` section earlier in this chapter? -Here is where we dive into that. -I'll first present the code and then we can go over it. +Here is where things get a little more interesting. Remember the +`Iteration` section earlier in this chapter? Here is where we dive +into that. I'll first present the code and then we can go over it. ```scala val iterator = @@ -223,9 +255,11 @@ val iterator = .map(_.take(20).toNel.getOrElse(sys.error("error")))) ``` -This code creates a synchronous iterator based on our ga that at each generation select the best 20 based on our comparison dominance. -`Iteration.sync(myGA).map(_.suml)` allows us to work with a `List[Ind]`. -`r` is an `Ind` which becomes a `Step` with a comparison. +This code creates a synchronous iterator based on our ga that at each +generation select the best 20 based on our comparison dominance. +`Iteration.sync(myGA).map(_.suml)` allows us to work with a +`List[Ind]`. `r` is an `Ind` which becomes a `Step` with a +comparison. ### Running our GA @@ -233,4 +267,5 @@ Lastly, running our program requires a `Runner`. `println(Runner.repeat(1000, iterator, swarm).run(env).eval(RNG.init(12L)).toString)` -This line of code will produce the results of our ga after 1000 iterations as a string. \ No newline at end of file +This line of code will produce the results of our ga after 1000 +iterations as a string. diff --git a/src/pages/step/class.md b/src/pages/step/class.md index c837076..aa770a4 100644 --- a/src/pages/step/class.md +++ b/src/pages/step/class.md @@ -1,15 +1,15 @@ ## Step Class -`Step` is has a very simple class definition. -It takes a single parameter, that being a function of type `Environment[A] => RVar[B]`. +`Step` is has a very simple class definition. It takes a single +parameter, that being a function of type `Environment[A] => RVar[B]`. We see this member function used we we call `run` of a `Step`. -``` +``` final case class Step[A,B] private (run: Environment[A] => RVar[B]) ``` -Not complicated at all. -And because of it's monadic nature we have the following functions at our disposal. +Not complicated at all. And because of it's monadic nature we have +the following functions at our disposal. ```scala map[C](f: B => C): Step[A,C] @@ -17,7 +17,8 @@ map[C](f: B => C): Step[A,C] flatMap[C](f: B => Step[A,C]): Step[A,C] ``` -We will be using the `Step` we created at the beginning of this chapter, `myStep`. +We will be using the `Step` we created at the beginning of this +chapter, `myStep`. ### map @@ -30,14 +31,15 @@ import spire.math._ import scalaz._ import Scalaz._ +val bounds = Interval(-5.12,5.12)^2 + val env = Environment( cmp = Comparison.dominance(Min), - eval = Eval.unconstrained[NonEmptyList,Double](_.map(x => x * x).suml).eval, - bounds = Interval(-5.12,5.12)^2 + eval = Eval.unconstrained[NonEmptyList,Double](_.map(x => x * x).suml).eval ) val rng = RNG.init(12) -val particle = Position.createPosition(env.bounds).map(p => Entity(Mem(p, p.zeroed), p)).eval(rng) +val particle = Position.createPosition(bounds).map(p => Entity(Mem(p, p.zeroed), p)).eval(rng) def explore (position: Position[Double]): Position[Double] = position.map(x => x * 0.73) val myStep = Step.eval(explore)(particle) ``` @@ -47,20 +49,23 @@ myStep.map(entity => Lenses._position.get(entity)).run(env).eval(rng) In this example we changed it from -- a step in where the particle's position is updated and evaluated to return a new `Entity` -- to a step in where the particle's position is updated and evaluated to return the resulting `Position`. +- a step in where the particle's position is updated and evaluated to + return a new `Entity` +- to a step in where the particle's position is updated and evaluated + to return the resulting `Position`. ### flatMap -Here we changing the context. -In this example, We are passing an `Entity[A] => Step[A, C]`, thus producing a new `Step[A, C]` which will differ from our original `Step[A, B]`. -What will happen here is that we adding an extra *step*. +Here we changing the context. In this example, We are passing an +`Entity[A] => Step[A, C]`, thus producing a new `Step[A, C]` which +will differ from our original `Step[A, B]`. What will happen here is +that we adding an extra *step*. ```tut:book:silent val rng = RNG.init(12) def explore (position: Position[Double]): Position[Double] = position.map(x => x * 0.73) -val particle = Position.createPosition(env.bounds).map(p => Entity(Mem(p, p.zeroed), p)).eval(rng) +val particle = Position.createPosition(bounds).map(p => Entity(Mem(p, p.zeroed), p)).eval(rng) val myStep = Step.eval(explore)(particle) def negate (position: Position[Double]): Position[Double] = position.map(x => x * -1) @@ -69,10 +74,11 @@ def negate (position: Position[Double]): Position[Double] = position.map(x => x myStep.flatMap(entity => Step.eval(negate)(particle)).run(env).eval(rng) ``` -So now our `Step` represents a step in an algorithm where a position is multiplied by 0.73 and then negated. -This step might not serve any real world purpose but it demonstrates how we may chain `Steps` together to form an algorithm. -This is easily achieved by using for comprehensions. -For example, take a look at the following method. +So now our `Step` represents a step in an algorithm where a position +is multiplied by 0.73 and then negated. This step might not serve any +real world purpose but it demonstrates how we may chain `Steps` +together to form an algorithm. This is easily achieved by using for +comprehensions. For example, take a look at the following method. ```tut:book def algorithm(entity: Entity[Mem[Double], Double]) = (for { @@ -81,4 +87,4 @@ def algorithm(entity: Entity[Mem[Double], Double]) = (for { } yield step2).map(entity => Lenses._position.get(entity)) algorithm(particle).run(env).eval(rng) -``` \ No newline at end of file +``` diff --git a/src/pages/step/environment.md b/src/pages/step/environment.md index fadb08b..639505f 100644 --- a/src/pages/step/environment.md +++ b/src/pages/step/environment.md @@ -1,13 +1,13 @@ ## Environment -An environment is simply a *container* for the specifications of our problem. -And as we can see from the class definition, it uses types we are very familiar with. +An environment is simply a *container* for the specifications of our +problem. And as we can see from the class definition, it uses types +we are very familiar with. -``` +``` final case class Environment[A]( cmp: Comparison, - eval: RVar[NonEmptyList[A] => Objective[A]], - bounds: NonEmptyList[spire.math.Interval[Double]]) + eval: RVar[NonEmptyList[A] => Objective[A]]) ``` An example of creating an `Environment` would be the following... @@ -23,7 +23,6 @@ import spire.implicits.{eu => _, _} ```tut:book val env = Environment( cmp = Comparison.dominance(Min), - eval = Eval.unconstrained[NonEmptyList,Double](_.map(x => x * x).suml).eval, - bounds = Interval(-5.12,5.12)^2 + eval = Eval.unconstrained[NonEmptyList,Double](_.map(x => x * x).suml).eval ) -``` \ No newline at end of file +``` diff --git a/src/pages/step/index.md b/src/pages/step/index.md index 7f023bc..cc24ee2 100644 --- a/src/pages/step/index.md +++ b/src/pages/step/index.md @@ -1,12 +1,13 @@ # Step -What is this mysterious data type called `Step`? -Well, it actually represents a *step* in an algorithm. -Nothing mysterious at all. How does this happen? -`Step` is a monad transformer and because monad transformers are monads themselves, we can freely compose different Step instances to create a larger computation. +What is this mysterious data type called `Step`? Well, it actually +represents a *step* in an algorithm. Nothing mysterious at all. How +does this happen? `Step` is a monad transformer and because monad +transformers are monads themselves, we can freely compose different +Step instances to create a larger computation. -In the last chapter we learnt how to create `Entities`, but what about evaluating them? -This wil be our first introduction to `Step`. +In the last chapter we learnt how to create `Entities`, but what about +evaluating them? This wil be our first introduction to `Step`. ```tut:book:invisible import cilib._ @@ -17,20 +18,23 @@ import Scalaz._ ``` ```tut:book:silent val rng = RNG.init(12) +val bounds = Interval(-5.12,5.12)^2 val env = Environment( cmp = Comparison.dominance(Min), - eval = Eval.unconstrained[NonEmptyList,Double](_.map(x => x * x).suml).eval, - bounds = Interval(-5.12,5.12)^2 + eval = Eval.unconstrained[NonEmptyList,Double](_.map(x => x * x).suml).eval ) -val particle = Position.createPosition(env.bounds).map(p => Entity(Mem(p, p.zeroed), p)).eval(rng) +val particle = Position.createPosition(bounds).map(p => Entity(Mem(p, p.zeroed), p)).eval(rng) def explore (position: Position[Double]): Position[Double] = position.map(x => x * 0.73) ``` ```tut:book val myStep = Step.eval(explore)(particle) ``` -This `Step` represents a step in some algorithm where the particle's position is updated and evaluated to return a new `Entity`. +This `Step` represents a step in some algorithm where the particle's +position is updated and evaluated to return a new `Entity`. -Understanding the `Step` concept is important as we will begin to start making more complex *steps* that which may be used in an algorithm. \ No newline at end of file +Understanding the `Step` concept is important as we will begin to +start making more complex *steps* that which may be used in an +algorithm. diff --git a/src/pages/step/object.md b/src/pages/step/object.md index 1d9466b..a8e2cf1 100644 --- a/src/pages/step/object.md +++ b/src/pages/step/object.md @@ -1,6 +1,7 @@ ## Step Companion Object -The companion object offers several methods that we may use to create instances of `Steps`. +The companion object offers several methods that we may use to create +instances of `Steps`. ```scala point[A,B](b: B): Step[A,B] @@ -18,14 +19,15 @@ withCompareR[A,B](f: Comparison => RVar[B]): Step[A,B] evalF[A:Numeric](pos: Position[A]): Step[A,Position[A]] ``` -We will be using the `Environment` and `RNG` we created at the beginning of this chapter. +We will be using the `Environment` and `RNG` we created at the +beginning of this chapter. ``` val rng = RNG.init(12) +val bounds = Interval(-5.12,5.12)^2 val env = Environment( cmp = Comparison.dominance(Min), - eval = Eval.unconstrained[NonEmptyList,Double](_.map(x => x * x).suml).eval, - bounds = Interval(-5.12,5.12)^2 + eval = Eval.unconstrained[NonEmptyList,Double](_.map(x => x * x).suml).eval ) ``` @@ -40,14 +42,14 @@ import spire.math._ import scalaz._ import Scalaz._ val rng = RNG.init(12) +val bounds = Interval(-5.12,5.12)^2 val env = Environment( cmp = Comparison.dominance(Min), - eval = Eval.unconstrained[NonEmptyList,Double](_.map(x => x * x).suml).eval, - bounds = Interval(-5.12,5.12)^2 + eval = Eval.unconstrained[NonEmptyList,Double](_.map(x => x * x).suml).eval ) ``` ```tut:book:silent -val particle = Position.createPosition(env.bounds).map(p => Entity(Mem(p, p.zeroed), p)).eval(rng) +val particle = Position.createPosition(bounds).map(p => Entity(Mem(p, p.zeroed), p)).eval(rng) ``` ```tut:book Step.point(particle) @@ -58,7 +60,7 @@ Step.point(particle) Creates `Step` contained in `RVar`. ```tut:book:silent -val particle = Position.createPosition(env.bounds).map(p => Entity(Mem(p, p.zeroed), p)) +val particle = Position.createPosition(bounds).map(p => Entity(Mem(p, p.zeroed), p)) ``` ```tut:book Step.pointR(particle).run(env).eval(rng) @@ -66,50 +68,34 @@ Step.pointR(particle).run(env).eval(rng) ### eval -`eval` is used for evaluating `Entities`. -This function produces a `Step` which may be `run` using a function, `Environment => RVar[A]`. +`eval` is used for evaluating `Entities`. This function produces a +`Step` which may be `run` using a function, `Environment => RVar[A]`. ```tut:book -val particle = Position.createPosition(env.bounds).map(p => Entity(Mem(p, p.zeroed), p)).eval(rng) +val particle = Position.createPosition(bounds).map(p => Entity(Mem(p, p.zeroed), p)).eval(rng) def explore (position: Position[Double]): Position[Double] = position.map(x => x * 0.73) Step.eval(explore)(particle) ``` + ```tut:book:silent Step.eval(explore)(particle).run(env).run(rng) - -/* -particle = Entity( - Mem( - Point(NonEmpty[3.1645541615758654,-1.8652719649133465],NonEmpty[[-5.12, 5.12],[-5.12, 5.12]]), - Point(NonEmpty[0.0,0.0],NonEmpty[[-5.12, 5.12],[-5.12, 5.12]])) - ,Point( - NonEmpty[3.1645541615758654,-1.8652719649133465], - NonEmpty[[-5.12, 5.12],[-5.12, 5.12]])) - -Step.eval(explore)(particle).run(env).run(rng) = Entity( - Mem( - Point(NonEmpty[3.1645541615758654,-1.8652719649133465],NonEmpty[[-5.12, 5.12],[-5.12, 5.12]]), - Point(NonEmpty[0.0,0.0],NonEmpty[[-5.12, 5.12],[-5.12, 5.12]])) - ,Solution( - NonEmpty[2.3101245379503816,-1.3616485343867428], - NonEmpty[[-5.12, 5.12],[-5.12, 5.12]], - Single(Feasible(7.19076211203803),List())) - ) -*/ ``` -As you can see from the above code, when our `Entity` was evaluated it's `Point` changed to a `Solution`. -However it's `state` remained the same as that is up to us as to how we update it. +As you can see from the above code, when our `Entity` was evaluated +it's `Point` changed to a `Solution`. However it's `state` remained +the same as that is up to us as to how we update it. ### withCompare -An example of use would be comparing the current position of an `Entity` with it's best, and then returning a new `Entity` based on the comparison. +An example of use would be comparing the current position of an +`Entity` with it's best, and then returning a new `Entity` based on +the comparison. ```tut:book:silent import monocle._, Monocle._ -val particle = Position.createPosition(env.bounds).map(p => Entity(Mem(p, p.zeroed), p)).eval(rng) +val particle = Position.createPosition(bounds).map(p => Entity(Mem(p, p.zeroed), p)).eval(rng) def updatePBest[S](p: Entity[S,Double])(implicit M: HasMemory[S,Double]): Step[Double, Entity[S,Double]] = { val pbestL = M._memory @@ -117,26 +103,30 @@ def updatePBest[S](p: Entity[S,Double])(implicit M: HasMemory[S,Double]): Step[D Entity(p.state applyLens pbestL set x, p.pos)) } ``` + ```tut:book updatePBest(particle).run(env).eval(rng) ``` ### withCompareR -An example of use would be determining which un-evaluated `RVar[Entity]s` is fitter. +An example of use would be determining which un-evaluated +`RVar[Entity]s` is fitter. ```tut:book:silent def better[S,A](a: Entity[S,A], b: Entity[S,A]): Step[A,Boolean] = Step.withCompareR(comp => RVar.point(Comparison.fitter(a.pos, b.pos).apply(comp))) -val particle1 = Position.createPosition(env.bounds).map(p => Entity(Mem(p, p.zeroed), p)).eval(rng) -val particle2 = Position.createPosition(env.bounds).map(p => Entity(Mem(p, p.zeroed), p)).eval(RNG.fromTime) +val particle1 = Position.createPosition(bounds).map(p => Entity(Mem(p, p.zeroed), p)).eval(rng) +val particle2 = Position.createPosition(bounds).map(p => Entity(Mem(p, p.zeroed), p)).eval(RNG.fromTime) ``` + ```tut:book better(particle1, particle2).run(env).eval(rng) ``` ### evalF -`evalF` will take a `Position` an returns a `Step` that represents the evaluation of the position. -This is actually used in the `Step.eval` method. +`evalF` will take a `Position` an returns a `Step` that represents the +evaluation of the position. This is actually used in the `Step.eval` +method. diff --git a/src/pages/stepS/class.md b/src/pages/stepS/class.md index 3a8bf70..67ad0a4 100644 --- a/src/pages/stepS/class.md +++ b/src/pages/stepS/class.md @@ -2,10 +2,10 @@ `final case class StepS[A,S,B](run: StateT[Step[A,?],S,B])` -As you can see the class header bares some resemblance to that of `Step`. -Here, however, the parameter `run` is a state transformer, `StateT`. -`StateT` is defined in `scalaz`. -The other similarities are that `StepS` also has `map` and `flatmap` methods. +As you can see the class header bares some resemblance to that of +`Step`. Here, however, the parameter `run` is a state transformer, +`StateT`. `StateT` is defined in `scalaz`. The other similarities +are that `StepS` also has `map` and `flatmap` methods. ```scala def map[C](f: B => C): StepS[A,S,C] @@ -19,19 +19,20 @@ But what also makes `StepS` unique is it's `zoom` method. def zoom[S2](l: monocle.Lens[S2,S]): StepS[A,S2,B] ``` -The `zoom` method uses a type of lense from the `monocle` library, called `Iso`. -Information about `iso` can be found over here at this [link][iso-link]. -We will see how all of these new data types come as we start by creating our first `StepS`! +The `zoom` method uses a type of lense from the `monocle` library, +called `Iso`. Information about `iso` can be found over here at this +[link][iso-link]. We will see how all of these new data types come as +we start by creating our first `StepS`! ### Our First StepS -Imagine we had the following situation. -We wanted to update a position by adjusting each point by some factor, as well as producing a new factor. -We would end up with some return type of `(Position[Double], Double)`. -All while keeping the same *chaining* for comprehension ability of of `Step`. -Tada! `StepS` to save the day. -In this situation, our factor will be our state. -First, the basics. +Imagine we had the following situation. We wanted to update a +position by adjusting each point by some factor, as well as producing +a new factor. We would end up with some return type of +`(Position[Double], Double)`. All while keeping the same *chaining* +for comprehension ability of of `Step`. Tada! `StepS` to save the +day. In this situation, our factor will be our state. First, the +basics. ```tut:book:invisible import cilib._ @@ -41,50 +42,50 @@ import spire.implicits._ import spire.math.Interval ``` ```tut:book:silent +val bounds = Interval(-5.12,5.12)^2 + val env = Environment( cmp = Comparison.dominance(Min), eval = Eval.unconstrained[NonEmptyList,Double](_.map(x => x * - x).suml).eval, - bounds = Interval(-5.12,5.12)^2 + x).suml).eval ) val rng = RNG.init(12) ``` ```tut:book // Our Position -val position = Position.createPosition(env.bounds).eval(rng) +val position = Position.createPosition(bounds).eval(rng) ``` -And then here is our function that we will be using to get an updated `Position` and state. +And then here is our function that we will be using to get an updated +`Position` and state. ```tut:book def explore (position: Position[Double], factor: Double): (Position[Double], Double) = (position.map(x => x * factor), 0.73 * factor) ``` -Now, putting it all together to make a `StepS`. -Pay close attention to the resulting types. +Now, putting it all together to make a `StepS`. Pay close attention +to the resulting types. ```tut:book val myStepS = StepS(StateT[Step[Double, ?], Position[Double], Double](x => Step.point(explore(x, 0.96)))) val step = myStepS.run(position) // Supply an initial value val rvar = step.run(env) val result = rvar.eval(rng) - -// Or alternatively - -//StepS.apply((x: Position[Double]) => Step.point[Double, (Position[Double], Double)](explore(x, 0.96))).run(position).run(env).eval(rng) ``` -Now that we have a `StepS` at our disposal let's start looking at its class methods. +Now that we have a `StepS` at our disposal let's start looking at its +class methods. ### zoom -`zoom` allows us to plugin in a lens for our `StepS`. -In this case, using `zoom` with a `_position` lense we are able to pass an `Entity`. -This creates a `StepS` that offers the same functionality as our original but allows us to pass in a different data type. +`zoom` allows us to plugin in a lens for our `StepS`. In this case, +using `zoom` with a `_position` lense we are able to pass an `Entity`. +This creates a `StepS` that offers the same functionality as our +original but allows us to pass in a different data type. ```tut:book -val particle = Position.createPosition(env.bounds).map(p => Entity((), p)).eval(rng) +val particle = Position.createPosition(bounds).map(p => Entity((), p)).eval(rng) myStepS.zoom(Lenses._position[Unit, Double]).run(particle).run(env).eval(rng) ``` @@ -98,7 +99,8 @@ myStepS.map(x => 4.0 * x).run(position).run(env).eval(rng) ### flatMap -Similarly, using the `flatMap` method we are able to modify the state as well as the value at hand by chaining together `StepSs`. +Similarly, using the `flatMap` method we are able to modify the state +as well as the value at hand by chaining together `StepS`s. ```tut:book:silent def negate (position: Position[Double]): (Position[Double], Double) = (position.map(x => x * -1), -1.0) @@ -108,6 +110,7 @@ val myStepS2 = StepS(StateT[Step[Double, ?], Position[Double], Double](x => Step myStepS.flatMap(x => myStepS2).run(position).run(env).eval(rng) ``` -Although a simple example with having our state has a `Double`, we can begin to see it's usefulness. -Especially when we begin to use it in for comprehensions to chain multiple `StepSs` together. -The last focus of this chapter will be exploring the companion object. \ No newline at end of file +Although a simple example with having our state has a `Double`, we can +begin to see it's usefulness. Especially when we begin to use it in +for comprehensions to chain multiple `StepSs` together. The last +focus of this chapter will be exploring the companion object. diff --git a/src/pages/stepS/object.md b/src/pages/stepS/object.md index f6cf9e7..2e2dee0 100644 --- a/src/pages/stepS/object.md +++ b/src/pages/stepS/object.md @@ -1,6 +1,7 @@ ## StepS Companion Object -The companion object offers us several methods for us to use, which we will explore shortly. +The companion object offers us several methods for us to use, which we +will explore shortly. ```scala lensIso[A,B] @@ -16,7 +17,8 @@ liftK[A,S,B](a: Comparison => B): StepS[A,S,B] liftS[A,S,B](a: State[S, B]): StepS[A,S,B] ``` -Not only does it offer us `StepS` creation methods, there are two implicits that you should be mindful about. +Not only does it offer us `StepS` creation methods, there are two +implicits that you should be mindful about. ```scala implicit def stepSMonad[A,S]: Monad[StepS[A,S,?]] @@ -26,7 +28,8 @@ implicit def stepSMonadState[A,S]: MonadState[StepS[A,S,?], S] ### lensIso -This method allows us to transform a `scalaz` lense into a `monocle` lenses that we may use. +This method allows us to transform a `scalaz` lense into a `monocle` +lenses that we may use. ```tut:book:invisible import cilib._ @@ -42,24 +45,26 @@ StepS.lensIso.get(scalaz.Lens.firstLens[Unit, Double]) ### apply -`apply` we have seen before in the previous section, specifically "Our First StepS" where you can find a thorough example. +`apply` we have seen before in the previous section, specifically "Our +First StepS" where you can find a thorough example. ### pointR -Creating a `StepS` based on an `RVar` computation. -It is important to remember that the initial value for `run` is a state value, the second type parameter. -In this case `Double`. +Creating a `StepS` based on an `RVar` computation. It is important to +remember that the initial value for `run` is a state value, the second +type parameter. In this case `Double`. ```tut:book:invisible +val bounds = Interval(-5.12,5.12)^2 + val env = Environment( cmp = Comparison.dominance(Min), eval = Eval.unconstrained[NonEmptyList,Double](_.map(x => x * - x).suml).eval, - bounds = Interval(-5.12,5.12)^2 + x).suml).eval ) ``` ```tut:book -StepS.pointR[Double, Double, NonEmptyList[Entity[Unit,Double]]](Position.createCollection(x => Entity((), x))(env.bounds, 3)) +StepS.pointR[Double, Double, NonEmptyList[Entity[Unit,Double]]](Position.createCollection(x => Entity((), x))(bounds, 3)) ``` ### pointS @@ -68,8 +73,10 @@ Creating a `StepS` based on an `Step` computation. ### liftK -`liftK` when provided with a comparison will yield `StepS` based on a `Step.withCompare`. +`liftK` when provided with a comparison will yield `StepS` based on a +`Step.withCompare`. ### liftS -`liftS` when provided with a `State` will yield `StepS` with a state type of `State`. \ No newline at end of file +`liftS` when provided with a `State` will yield `StepS` with a state +type of `State`.