diff --git a/content/01_vectors.html b/content/01_vectors.html
index b532e2d..7d76d2a 100644
--- a/content/01_vectors.html
+++ b/content/01_vectors.html
@@ -601,7 +601,7 @@ function draw() {
let center = createVector(width / 2, height / 2);
mouse.sub(center);
- // The magnitude (that is, length) of a vector can be accessed via the `mag()` function. Here it is used as the width of a rectangle drawn at the top of the window.
+ // The magnitude (that is, length) of a vector can be accessed via the mag()
function. Here it is used as the width of a rectangle drawn at the top of the window.
let m = mouse.mag();
fill(0);
rect(0, 0, m, 10);
diff --git a/content/03_oscillation.html b/content/03_oscillation.html
index 26a88da..72ae81d 100644
--- a/content/03_oscillation.html
+++ b/content/03_oscillation.html
@@ -836,14 +836,14 @@ function draw() {
connect(bob) {
// Get a vector pointing from the anchor to the bob position.
let force = p5.Vector.sub(bob.position, this.anchor);
- // Calculate the displacement between distance and rest length. I’ll use the variable name “stretch” instead of “x” to be more descriptive.
+ // Calculate the displacement between distance and rest length. I’ll use the variable name stretch
instead of x
to be more descriptive.
let currentLength = force.mag();
let stretch = currentLength - this.restLength;
// Direction and magnitude together!
force.setMag(-1 * this.k * stretch);
- // Call applyForce() right here!
+ // Call applyForce()
right here!
bob.applyForce(force);
}
diff --git a/content/05_steering.html b/content/05_steering.html
index 404dfb7..d6390f4 100644
--- a/content/05_steering.html
+++ b/content/05_steering.html
@@ -963,7 +963,11 @@ for (let i = 0; i < path.points.length - 1; i++) {
Stated more evocatively, the theory is that a single butterfly flapping its wings on the other side of the world could cause a massive weather shift and ruin your weekend at the beach. It‘s called nonlinear because there isn’t a linear relationship between a change in initial conditions and a change in outcome. A small change in initial conditions can have a massive effect on the outcome. Nonlinear systems are a superset of chaotic systems. In Chapter 7, you’ll see how even in a system of many 0s and 1s, if you change just one bit, the result will be completely different.
Complexity will serve as a key theme for much of the remainder of the book. In this section, I’ll begin by introducing an additional feature to the Vehicle
class: the ability to perceive neighboring vehicles. This enhancement will pave the way for a culminating example of a complex system, in which the interplay of simple individual behaviors results in an emergent behavior: flocking.
First, this visual interpretation of the data is completely literal. It’s useful for demonstrating the algorithms and results of Wolfram’s elementary CA, but it shouldn’t necessarily drive your own personal work. You’re not likely building a project that needs precisely this algorithm with this visual style. So while learning to draw a CA in this way will help you understand and implement CA systems, this skill should exist only as a foundation.
Second, the fact that a 1D CA is visualized with a 2D image can be misleading. It’s very important to remember that this is not a 2D CA. I’m simply choosing to show a history of all the generations stacked vertically. This technique creates a 2D image out of many instances of 1D data, but the system itself is 1D. Later, I’ll show you an actual 2D CA (the Game of Life), and I’ll cover how to visualize such a system.
-The good news is that drawing an elementary CA isn’t particularly difficult. I’ll begin by rendering a single generation. Let’s say each cell should be a 10 by 10 square:
+The good news is that drawing an elementary CA isn’t particularly difficult. I’ll begin by rendering a single generation. Let’s say each cell should be a 10\times10 square:
let w = 10;
Assuming the canvas is 640 pixels wide, the CA will have 64 cells. Of course, I can calculate this value dynamically when I initialize the cells
array in setup()
:
//{!1} How many cells fit across, given a certain width @@ -558,7 +558,7 @@ if (board[i + 1][j ] === 1) sum++; if (board[i - 1][j + 1] === 1) sum++; if (board[i ][j + 1] === 1) sum++; if (board[i + 1][j + 1] === 1) sum++;-
Just as with the Wolfram CA, I find myself writing out a bunch of if
statements. This is another situation where, for teaching purposes, it’s useful and clear to write the code this way, explicitly stating every step (each time a neighbor has a state of 1, the counter increases). Nevertheless, it’s a bit silly to say, “If the cell state equals 1, add 1 to a counter” when I could instead just say, “Add every cell state to a counter.” After all, if the state can be only 0 or 1, the sum of all the neighbors’ states will yield the total number of live cells. Since the neighbors are arranged in a mini 3 by 3 grid, I can introduce another nested loop to compute the sum more efficiently:
Just as with the Wolfram CA, I find myself writing out a bunch of if
statements. This is another situation where, for teaching purposes, it’s useful and clear to write the code this way, explicitly stating every step (each time a neighbor has a state of 1, the counter increases). Nevertheless, it’s a bit silly to say, “If the cell state equals 1, add 1 to a counter” when I could instead just say, “Add every cell state to a counter.” After all, if the state can be only 0 or 1, the sum of all the neighbors’ states will yield the total number of live cells. Since the neighbors are arranged in a mini 3\times3 grid, I can introduce another nested loop to compute the sum more efficiently:
let sum = 0; //{!2} Use k and l as the counters since i and j are already used! diff --git a/content/08_fractals.html b/content/08_fractals.html index 9c24c03..d9df4f9 100644 --- a/content/08_fractals.html +++ b/content/08_fractals.html @@ -47,7 +47,7 @@Figure 8.4: Two coastlines -The absence of a scale in these illustrations is no accident. Am I showing the entire coastline or just a small portion of it? There’s no way for you to know without a scale reference because coastlines, as fractals, look essentially the same at any scale. (Incidentally, coastline B shows an approximately 3X magnified view of a specific section of coastline A. I’ve added the scales in Figure 8.5.)
+The absence of a scale in these illustrations is no accident. Am I showing the entire coastline or just a small portion of it? There’s no way for you to know without a scale reference because coastlines, as fractals, look essentially the same at any scale. (Incidentally, coastline B shows an approximately 3\times magnified view of a specific section of coastline A. I’ve added the scales in Figure 8.5.)
Figure 8.5: Two coastlines, with scale @@ -653,24 +653,24 @@ for (let i = 0; i < message.length; i++) {
- Alphabet: An L-system’s alphabet comprises the valid characters that can be included. For example, I could say the alphabet is ABC, meaning that any valid “sentence” (a string of characters) in an L-system can include only these three characters.
- Axiom: The axiom is a sentence (created with characters from the alphabet) that describes the initial state of the system. For example, with the alphabet ABC, a possible axiom could be AAA, or B, or ACBAB.
-- Rules: The production rules of an L-system describe ways of transforming the sentence. The rules are applied recursively, starting with the axiom, generating new sentences over and over again. An L-system rule includes two sentences, a predecessor and a successor. For example, the rule A —> AB means that wherever an A (the predecessor) occurs in a sentence, it should be replaced with AB (the successor) in the next generation.
+- Rules: The production rules of an L-system describe ways of transforming the sentence. The rules are applied recursively, starting with the axiom, generating new sentences over and over again. An L-system rule includes two sentences, a predecessor and a successor. For example, the rule A → AB means that wherever an A (the predecessor) occurs in a sentence, it should be replaced with AB (the successor) in the next generation.
I’ll begin with a simple L-system. In fact, it’s Lindenmayer’s original L-system, which models the growth of algae. Here are its components:
@@ -786,11 +786,11 @@ function generate() {
Alphabet -A, B +A, B Axiom -A +A @@ -746,17 +746,17 @@ function generate() { Rules - A→AB - B→A + A → AB + B → A Alphabet -A, B +A, B Axiom -A +A @@ -766,19 +766,19 @@ function generate() { Rules - A→ABA - B→BBB + A → ABA + B → BBB Generation 0 -A +A Generation 1 -ABA +ABA Generation 2 -ABABBBABA +ABABBBABA Generation 3 -ABABBBABABBBBBBBBBABABBBABA +ABABBBABABBBBBBBBBABABBBABA
- A +A Draw a line forward. - @@ -805,27 +805,27 @@ function generate() {B +B Move forward (without drawing a line). @@ -496,7 +496,7 @@ function draw() {
- F +F Draw a line and move forward. - G +G Move forward (without drawing a line). - + ++ Turn right. - - +– Turn left. - [ +[ Save current state. - @@ -834,38 +834,38 @@ function generate() {] +] Restore current state. diff --git a/content/09_ga.html b/content/09_ga.html index e6b6d7e..aae117e 100644 --- a/content/09_ga.html +++ b/content/09_ga.html @@ -55,7 +55,10 @@ console.log(s);
- F +F line(0, 0, 0, length); translate(0, length);
- G +G translate(0, length);
- + ++ rotate(angle);
- - +– rotate(-angle);
- [ +[ push();
- ] +] @@ -902,15 +902,15 @@ translate(0, length); pop();
Alphabet -F, G, +, -, [ , ] +F, G, +, –, [, ] Axiom -F +F Rules -F → FF+[+F-F-F]-[-F+F+F] +F → FF + [+ F – F – F] – [– F + F + F]
- Heredity: There must be a mechanism that allows parent creatures in one generation to pass their traits down to child creatures in the next generation.
- Variation: There must be a variety of traits present in the population of creatures or a means to introduce variation for evolution to take place. Imagine a population of beetles that were exactly the same: same color, same size, same wingspan, same everything. Without any variety in the population, the children would always be identical to the parents and to each other. New combinations of traits could never occur, and nothing could evolve.
-- Selection: There must be a mechanism by which some creatures have the opportunity to be parents and pass on their genetic information, while others don’t. This is commonly referred to as survival of the fittest. Take, for example, a population of gazelles that are chased by lions. The faster gazelles have a better chance of escaping the lions, increasing their chances of living longer, reproducing, and passing on their genetic information to offspring. The term fittest can be misleading, however. It’s often thought to mean biggest, fastest, or strongest, but while it can sometimes encompass physical attributes like size, speed, or strength, it doesn’t have to. The core of natural selection lies in whatever traits best suit an organism’s environment and increase its likelihood of survival and ultimately reproduction. Instead of asserting superiority, fittest can be better understood as “able to reproduce.” Take the Dolania americana (also known as the American sand-burrowing mayfly), which is believed to have the shortest lifespan of any insect. An adult female lives for only five minutes, but as long as it has managed to deposit its egg in the water, it will pass its genetic information to the next generation. For the typing cats, a more fit cat, one that I will assign as more likely to reproduce, is one that has typed more characters present in a given phrase of Shakespeare.
+- + Selection: There must be a mechanism by which some creatures have the opportunity to be parents and pass on their genetic information, while others don’t. This is commonly referred to as survival of the fittest. Take, for example, a population of gazelles that are chased by lions. The faster gazelles have a better chance of escaping the lions, increasing their chances of living longer, reproducing, and passing on their genetic information to offspring. + The term fittest can be misleading, however. It’s often thought to mean biggest, fastest, or strongest, but while it can sometimes encompass physical attributes like size, speed, or strength, it doesn’t have to. The core of natural selection lies in whatever traits best suit an organism’s environment and increase its likelihood of survival and ultimately reproduction. Instead of asserting superiority, fittest can be better understood as “able to reproduce.” Take the Dolania americana (also known as the American sand-burrowing mayfly), which is believed to have the shortest lifespan of any insect. An adult female lives for only five minutes, but as long as it has managed to deposit its egg in the water, it will pass its genetic information to the next generation. For the typing cats, a more fit cat, one that I will assign as more likely to reproduce, is one that has typed more characters present in a given phrase of Shakespeare. +
I want to emphasize the context in which I’m applying these Darwinian concepts: a simulated, artificial environment where specific goals can be quantified, all for the sake of creative exploration. Throughout history, the principles of genetics have been used to harm those who have been marginalized and oppressed by dominant societal structures. I believe it is essential to approach projects involving GAs with careful consideration of the language used, and to ensure that the documentation and descriptions of the work are framed inclusively.
With these concepts established, I’ll begin walking through the GA narrative. I’ll do this in the context of typing cats. The algorithm will be divided into several steps that unfold over two parts: a set of conditions for initialization, and the steps that are repeated over and over again until the correct phrase is found.
@@ -648,7 +651,7 @@ function draw() { population[i] = child; } - // Step 4: Repeat—go back to the beginning of draw()! + // Step 4: Repeat — go back to the beginning of draw()! }The sketch.js file precisely mirrors the steps of the GA. However, most of the functionality called upon is encapsulated in the
DNA
class:diff --git a/content/10_nn.html b/content/10_nn.html index 844da26..802e2ee 100644 --- a/content/10_nn.html +++ b/content/10_nn.html @@ -288,24 +288,24 @@ let guess = perceptron.feedForward(inputs);- -1 --1 -0 +–1 +–1 +0 - -1 -+1 --2 +–1 ++1 +–2 - +1 --1 -+2 ++1 +–1 ++2 - +1 -+1 -0 ++1 ++1 +0 Exercise 10.1
Modify the code from Example 10.1 to also draw the perceptron’s current decision boundary during the training process—its best guess for where the line should be. Hint: Use the perceptron’s current weights to calculate the line’s equation.
-While this perceptron example offers a conceptual foundation, real-world datasets often feature more diverse and dynamic ranges of input values. For the simplified scenario here, the range of values for x is larger than that for y because of the canvas size of 640 by 240. Despite this, the example still works—after all, the sign activation function doesn’t rely on specific input ranges, and it’s such a straightforward binary classification task.
+While this perceptron example offers a conceptual foundation, real-world datasets often feature more diverse and dynamic ranges of input values. For the simplified scenario here, the range of values for x is larger than that for y because of the canvas size of 640\times240. Despite this, the example still works—after all, the sign activation function doesn’t rely on specific input ranges, and it’s such a straightforward binary classification task.
However, real-world data often has much greater complexity in terms of input ranges. To this end, data normalization is a critical step in machine learning. Normalizing data involves mapping the training data to ensure that all inputs (and outputs) conform to a uniform range—typically 0 to 1, or perhaps –1 to 1. This process can improve training efficiency and prevent individual inputs from dominating the learning process. In the next section, using the ml5.js library, I’ll build data normalization into the process.
Exercise 10.2
@@ -572,7 +572,7 @@ function draw() {Figure 10.14: Labeling images as cats or dogs Classification doesn’t happen by magic. The model must first be shown many examples of dogs and cats with the correct labels in order to properly configure the weights of all the connections. This is the training part of supervised learning.
-The classic “Hello, world!” demonstration of machine learning and supervised learning is a classification problem of the MNIST dataset. Short for Modified National Institute of Standards and Technology, MNIST is a dataset that was collected and processed by Yann LeCun (Courant Institute, NYU), Corinna Cortes (Google Labs), and Christopher J. C. Burges (Microsoft Research). Widely used for training and testing in the field of machine learning, this dataset consists of 70,000 handwritten digits from 0 to 9; each is a 28 by 28-pixel grayscale image (see Figure 10.15 for examples). Each image is labeled with its corresponding digit.
+The classic “Hello, world!” demonstration of machine learning and supervised learning is a classification problem of the MNIST dataset. Short for Modified National Institute of Standards and Technology, MNIST is a dataset that was collected and processed by Yann LeCun (Courant Institute, NYU), Corinna Cortes (Google Labs), and Christopher J. C. Burges (Microsoft Research). Widely used for training and testing in the field of machine learning, this dataset consists of 70,000 handwritten digits from 0 to 9; each is a 28\times28 pixel grayscale image (see Figure 10.15 for examples). Each image is labeled with its corresponding digit.