From f2de1cdefc240ee1da8a68e7f20ef8b30e7cf8d4 Mon Sep 17 00:00:00 2001 From: jverzani Date: Tue, 11 Aug 2026 17:45:57 -0400 Subject: [PATCH] fix typos --- quarto/ODEs/differential_equations.qmd | 2 +- quarto/ODEs/euler.qmd | 2 +- quarto/alternatives/giac.qmd | 10 +- quarto/alternatives/makie_plotting.qmd | 6 +- quarto/alternatives/symbolics.qmd | 2 +- quarto/basics/numbers_types-II.html | 2804 ----------------- quarto/basics/numbers_types-II.qmd | 2 +- quarto/basics/numbers_types.qmd | 2 +- quarto/basics/vectors.qmd | 8 +- quarto/derivatives/curve_sketching.qmd | 2 +- .../derivatives/first_second_derivatives.qmd | 2 +- .../differentiable_vector_calculus/test.html | 641 ---- quarto/differentiable_vector_calculus/test.jl | 827 ----- .../differentiable_vector_calculus/test.qmd | 98 - quarto/integrals/area_between_curves.qmd | 2 +- quarto/integrals/center_of_mass.qmd | 4 +- quarto/integrals/substitution.qmd | 2 +- quarto/integrals/surface_area.qmd | 2 +- quarto/precalc/julia_overview.qmd | 2 +- quarto/precalc/transformations.qmd | 2 +- quarto/precalc/trig_functions.qmd | 4 +- 21 files changed, 28 insertions(+), 4398 deletions(-) delete mode 100644 quarto/basics/numbers_types-II.html delete mode 100644 quarto/differentiable_vector_calculus/test.html delete mode 100644 quarto/differentiable_vector_calculus/test.jl delete mode 100644 quarto/differentiable_vector_calculus/test.qmd diff --git a/quarto/ODEs/differential_equations.qmd b/quarto/ODEs/differential_equations.qmd index 5b5ff45..d98970f 100644 --- a/quarto/ODEs/differential_equations.qmd +++ b/quarto/ODEs/differential_equations.qmd @@ -260,7 +260,7 @@ This very clearly shows the sharp dependence on the value of $b$; below some lev The function `recovered` is of two variables returning a single value. In subsequent sections we will see a few $3$-dimensional plots that are common for such functions, here we skip ahead and show how to visualize multiple function plots at once using "`z`" values in a graph. -::: {#fig-recoverd-over-various-k-values} +::: {#fig-recovered-over-various-k-values} ```{julia} #| hold: true k, ks = 0.1, 0.2:0.1:0.9 # first `k` and then the rest diff --git a/quarto/ODEs/euler.qmd b/quarto/ODEs/euler.qmd index 682ec9e..d94a9fe 100644 --- a/quarto/ODEs/euler.qmd +++ b/quarto/ODEs/euler.qmd @@ -184,7 +184,7 @@ for i in 1:n end ``` -So how did we do? @fig-euler-yp-yx-n-5 shows the graph of the exact answer and the stiched-together answer. +So how did we do? @fig-euler-yp-yx-n-5 shows the graph of the exact answer and the stitched-together answer. ::: {#fig-euler-yp-yx-n-5} diff --git a/quarto/alternatives/giac.qmd b/quarto/alternatives/giac.qmd index b2b3dcd..42b8cae 100644 --- a/quarto/alternatives/giac.qmd +++ b/quarto/alternatives/giac.qmd @@ -9,7 +9,7 @@ format: # Using the Giac symbolic math engine within Julia -This page describes the use of symbolic math for some topics of Calculus within `Julia` utilizing the [Giac](http://www-fourier.ujf-grenoble.fr/~parisse/giac.html) library. Giac is accessed through `Giac.jl`. Giac is a computer algebra system (CAS) implemented in C++; `Giac.jl` is an interface. See this [pdf documentation](https://www-fourier.univ-grenoble-alpes.fr/~parisse/giac/cascmd_en.pdf) for a comprehensive set of topics or the `Julia` documention for the different commands discussed. +This page describes the use of symbolic math for some topics of Calculus within `Julia` utilizing the [Giac](http://www-fourier.ujf-grenoble.fr/~parisse/giac.html) library. Giac is accessed through `Giac.jl`. Giac is a computer algebra system (CAS) implemented in C++; `Giac.jl` is an interface. See this [pdf documentation](https://www-fourier.univ-grenoble-alpes.fr/~parisse/giac/cascmd_en.pdf) for a comprehensive set of topics or the `Julia` documentation for the different commands discussed. There are other possible choices for symbolic math within the Julia ecosystem: @@ -1680,7 +1680,7 @@ This new object can be manipulated as any other symbolic expression. ## Parametric description of functions -Vectors can be used to describe curves parameterically (where the $x$ and $y$ motions are modeled by a third variable, typically $t$ for time). We describe this in a bit more detail later when discussing univariate, vector-valued functions. +Vectors can be used to describe curves parametrically (where the $x$ and $y$ motions are modeled by a third variable, typically $t$ for time). We describe this in a bit more detail later when discussing univariate, vector-valued functions. Consider a person on an advanced ferris wheel with coordinates $x(t)$ and $y(t)$ describing position. The wheel of radius $r$ is centered $R$ units above and circles at radius $\omega$, the car has radius $r_0$ and rotates $6$ times faster. @@ -2176,7 +2176,7 @@ integrate.(spiral, t, 0, pi) ##### Line integrals -A line integral might be generically written over a curve $C$ or with a paramterization, $r(t)$, of $C$, yielding +A line integral might be generically written over a curve $C$ or with a parameterization, $r(t)$, of $C$, yielding $$ I = \int_C f(\vec{x}) ds = \int_a^b f(r(t)) dt @@ -2379,8 +2379,8 @@ For example, to integrate $F(x,y) = x^2 \cdot y^3$ over the triangular region fo ```{julia} @giac_var x y F = x^2 * y^3 -Iy = integrate(F, y, 0, 1-x) # integrating int_{x=0}^1 int_{y=0}^{1-x} F(x,y) dy dx -integrate(Iy, x, 0, 1) +I_y = integrate(F, y, 0, 1-x) # integrating int_{x=0}^1 int_{y=0}^{1-x} F(x,y) dy dx +integrate(I_y, x, 0, 1) ``` (Integrating is made easy, but *not* the task of identifying valid endpoints to describe the region integrated over.) diff --git a/quarto/alternatives/makie_plotting.qmd b/quarto/alternatives/makie_plotting.qmd index 50669d9..14435dd 100644 --- a/quarto/alternatives/makie_plotting.qmd +++ b/quarto/alternatives/makie_plotting.qmd @@ -510,7 +510,7 @@ arrows3d!(Point3.(us), Point3.(dus)) current_figure() ``` -Plot of tangent lines in both two and three dimenstions +Plot of tangent lines in both two and three dimensions ::: @@ -851,9 +851,9 @@ The manual construction of a figure and an axis object will be further discussed ### Three dimensional contour plots -The `contour` function can also plot $3$-dimensional contour plots. Concentric spheres, contours of $x^2 + y^2 + z^2 = c$ for $c > 0$ are presented in @fig-makie-countour-three-d. +The `contour` function can also plot $3$-dimensional contour plots. Concentric spheres, contours of $x^2 + y^2 + z^2 = c$ for $c > 0$ are presented in @fig-makie-contour-three-d. -::: {#fig-makie-countour-three-d} +::: {#fig-makie-contour-three-d} ```{julia} f(x,y,z) = x^2 + y^2 + z^2 xs = ys = zs = range(-3, 3, length=100) diff --git a/quarto/alternatives/symbolics.qmd b/quarto/alternatives/symbolics.qmd index 26b45bd..0393228 100644 --- a/quarto/alternatives/symbolics.qmd +++ b/quarto/alternatives/symbolics.qmd @@ -762,7 +762,7 @@ Symbolics.jacobian(eqs, [x,y]) ## Integration -The `SymbolicIntegration` package provides two means to integration *univariate* functions using either the Risch alogorithm or a rules-based approach. +The `SymbolicIntegration` package provides two means to integration *univariate* functions using either the Risch algorithm or a rules-based approach. ```{julia} using SymbolicIntegration, Symbolics diff --git a/quarto/basics/numbers_types-II.html b/quarto/basics/numbers_types-II.html deleted file mode 100644 index 86c4b3c..0000000 --- a/quarto/basics/numbers_types-II.html +++ /dev/null @@ -1,2804 +0,0 @@ - - - - - - - - - -numbers_types-ii - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- -
-
-

Number systems

-
- - - -
- - - - -
- - - -
- - -

In mathematics there are many different number systems in common use. For example by the end of pre-calculus, all of the following have been introduced:

-
    -
  • The integers, \(\{\dots, -3, -2, -1, 0, 1, 2, 3, \dots\}\);

  • -
  • The rational numbers, \(\{p/q: p, q \text{ are integers}, q \neq 0\}\);

  • -
  • The real numbers, \(\{x: -\infty < x < \infty\}\);

  • -
  • The complex numbers, \(\{a + bi: a,b \text{ are real numbers and } i^2=-1\}\).

  • -
-

On top of these, we have special subsets, such as the natural numbers \(\{1, 2, \dots\}\) (sometimes including \(0\)), the even numbers, the odd numbers, the positive numbers, the non-negative numbers, etc.

-

Mathematically, these number systems are naturally nested within each other as integers are rational numbers which are real numbers, which can be viewed as part of the complex numbers.

-

Calculators typically have just one type of number—floating point values. These model the real numbers.

-

Julia, on the other hand, has a rich type system, and within that has several different number types. There are types that model each of the four main systems above, and within each type, specializations for how these values are stored.

-

For now, let’s consider the number \(1\). It can be viewed as either an integer, rational, real, or complex number. To construct “\(1\)” in each type within Julia we have these different styles:

-
-
1, 1.0, 1//1, 1 + 0im
-
-
(1, 1.0, 1//1, 1 + 0im)
-
-
-

The basic number types in Julia are Int, Float64, Rational and Complex, though in fact there are many more, and the last two aren’t even concrete types. This distinction is important, as the type of number dictates how it will be displayed, how it will be stored, and how precisely the stored value can be expected to be to the mathematical value it models.

-

Though there are explicit constructors for these types, these notes avoid them unless necessary, as Julia’s parser can distinguish these types through an easy to understand syntax:

-
    -
  • integers have no decimal point;

  • -
  • floating point numbers have a decimal point (or are written with scientific notation);

  • -
  • rationals are constructed from integers using the double division operator, //; and

  • -
  • complex numbers are formed by including a term with the imaginary unit, im.

  • -
-
-
-
- -
-
-NoteWarning -
-
-
-

Heads up, the difference between 1 and 1.0 is subtle. Even more so, as 1. will parse as 1.0. This means some expressions, such as 2.*3, are ambiguous, as the . might be part of the 2 (as in 2. * 3) or the operation * (as in 2 .* 3).

-
-
-

The key distinction is between integers and floating points. While floating point values include integers, and so can be used exclusively on the calculator, the difference is that an integer is guaranteed to be an exact value, whereas a floating point value, while often an exact representation of a number is also often just an approximate value. This can be an advantage—floating point values can model a much wider range of numbers.

-

In nearly all cases the differences are not noticeable. To see why take, for instance, this simple calculation involving mixed types.

-
-
1 + 1.25 + 3//2
-
-
3.75
-
-
-

The sum of an integer, a floating point number and rational number returns a floating point number without a complaint.

-
-

Promotion

-

This is because behind the scenes, Julia will often “promote” the two numbers to a common type. In particular, before adding mixed-type numbers, the two are promoted to a common type by promote. In the example, first when computing 1 + 1.25 the integer 1 will be promoted to a floating point value, 1.0, and then the two values are added. Similarly, with 2.25 + 3//2, where the fraction is promoted to the floating point value 1.5 and afterwards addition is carried out.

-

We can see the promotion here:

-
-
promote(1, 1.25)
-
-
(1.0, 1.25)
-
-
-

and

-
-
promote(2.25, 3//2)
-
-
(2.25, 1.5)
-
-
-
-
-

Integers

-

Integers are often used casually, as they come about from parsing. As with a calculator, floating point numbers could be used for integers, but in Julia—and other languages—it proves useful to have numbers known to have exact values. Integers are needed for indexing and counting.

-

Except on older machines, the default integer is stored with 64 bits, though there are many available types for integers. With \(64\) bits, the range of integers that can be represented is \(-9223372036854775808=-(2^{63})\) to \(9223372036854775807 = 2^{63}-1\).

-
-
-

Floating point numbers

-

Floating point numbers are a model for the real numbers. With the same size storage, the integers provide exact numbers evenly spaced between the smallest and largest integer. Floating point values are exact for some values but as there are infinitely many real numbers are only approximations except in special cases. This leads to some differences between math done by hand and math done on the computer.

-
-

Float64

-

Float64 is the most common type of floating point number, as it is the most supported by the underlying hardware. Julia has other floating point types, notably Float32 and BigFloat for certain uses, but our focus here is on 64-bit floating point numbers.

-

The double-precision model for floating point numbers has three parts: a sign, an exponent (for a base of \(2\)), and a significand (in base \(2\)) representing numbers as \(\pm a \cdot 2^n\). The 64 bits are apportioned as follows: \(1\) is for the sign, \(11\) for the exponent, \(52\) for the significand.

-

The \(52\) bits of the significand are used to represent \(1.a_1a_2a_3\cdots a_{52}\) in base \(2\) or \(1 + a_12^{-1} + a_22^{-2} + a_32^{-3} + \cdots a_{52}2^{-52} = b/2^{52}\) for some integer \(b\). This means the significand represents a rational number.

-

The following shows the bits in the significand for a given number written in the form above:1

-
-
bitstring(1 + 1/2 + 1/4 + 0/8 + 1/16 + 1/32 + 0/64)[13:end] # 1101100…
-
-
"1101100000000000000000000000000000000000000000000000"
-
-
-

The 11 bits for the exponent covers a range from \(-1023\) to \(1024\) which in base \(10\) is around \(10^{-308}\) to \(10^{308}\).

-

Together these can represent exactly any rational number of the form \(\pm a \cdot 2^b\) where \(a\) is a sum of powers of \(1/2\) and \(b\) is an integer with \(1.0 \leq a \leq 1 + (1/2^1) + (1/2^2) + \cdots + (1/2^{52})\) and \(-1023 \leq b \leq 1024\).

-

Figure 1 shows the possible positive values were there only \(2\) bits for the exponent (for \(-1, 0, 1, 2\)) and \(2\) bits for the significand (\(1 + 0/4 + 0/2\), \(1 + 1/4 + 0/2\), \(1 + 0/4 + 1/2\), \(1 + 1/4 + 1/2\)). The main takeaway is that numbers get less concentrated the farther they get from \(0\).

-
-
-
-
-
-
- -
-
-
-
-
-Figure 1: Figure showing concentration of floating point values. The vertical ticks represent representable floating point values (were there only 2 bits (not 52) for the mantissa) and 2 bits (not 11) for the exponent. This leaves a range from a range of \(-1/2\) to not quite \(8\) being representable without using subnormal numbers. When the intervals double in length (from \([2^{i},2^{i+1}]\) to \([2^{i+1}, 2^{i+2}]\)) there are the same number of representable floating point values, so the concentration of representable values halves. With more bits there is a higher concentration, but the discrete nature is always present and leads to necessary approximations for modeling most all real numbers. -
-
-
-

In addition, there are special bit patterns recognized as 0.0 and even -0.0, which is a distinct number. There are also patterns for \(+\infty\) (Inf) and \(-\infty\) (-Inf). There are also patterns for NaN, or “not a number”, a value that is the result of some mathematical operations, such as 0.0 / 0.0. Finally, there are subnormal numbers representing even smaller numbers near \(0\) than described above, which are as small as \(2^{-1023} \approx 1.11 \cdot 10^{-308}\).

-
-
-

Scientific notation

-

Floating point numbers smaller than \(10^{-4}\) or bigger or equal to \(10^6\) (in absolute value) are displayed in scientific notation. Internally, most floating point numbers are stored in base \(2\) scientific notation as \(a \cdot 2^b\) with \(a=1.xxx\dots\). But when displayed, numbers are represented in base \(10\) and when scientific notation is used the numbers are normalized in the from \(a \cdot 10^b\) where \(1.0 \leq a < 10\).

-

The significand and exponent are separated by the character e—which is not the same as the constant \(e\)—rather denotes a 64-bit number separated into a significand and an exponent by a formatting character. (Float32 uses an f as a separator.)

-

Consider these two numbers one close to \(0\) one far from \(0\):

-
-
0.0000000123456789, 123456789.0
-
-
(1.23456789e-8, 1.23456789e8)
-
-
-

Their display is subtly different, as only a minus sign after e distinguishes them.

-

The parser will read in numbers with an e in the proper format as though they are scientific notation:

-
-
1e8
-
-
1.0e8
-
-
-

The above creates the same value as 10.0^8, but not 1e^8 which will error unless a value for e has been assigned.

-
-
-

Inexactness and consequences

-

For numbers not representable in floating point, some rounding must go on to fit the number into a representable floating point value. As such, some computed values are not quite what they would be mathematically:

-
-
sqrt(2) * sqrt(2) - 2, sin(1pi)
-
-
(4.440892098500626e-16, 1.2246467991473532e-16)
-
-
-

These values are very small numbers, but not exactly \(0\), as they are mathematically.

-

More surprisingly, simple fractions may also lead to mathematically different results:

-
-
1/10 + 2/10 - 3/10
-
-
5.551115123125783e-17
-
-
-

This, of course, is due to none of these fractions being of the form \(a\cdot 2^b\) for integers \(a, b\).

-

Another surprise: floating point addition is not necessarily associative. That is the property \(a + (b+c) = (a+b) + c\) may not hold exactly. For example:

-
-
l2r = (1/10 + 2/10) + 3/10
-r2l = 1/10 + (2/10 + 3/10)
-l2r - r2l
-
-
1.1102230246251565e-16
-
-
-

One other surprise. Mathematically, for real numbers, subtraction of similar-sized numbers is not exceptional, for example \(1 - \cos(x)\) is positive if \(0 < x < \pi/2\), say. This will not be the case for floating point values. If \(x\) is close enough to \(0\), then \(\cos(x)\) and \(1\) will be so close, that they will be represented by the same floating point value, 1.0, so the difference will be zero:

-
-
1.0 - cos(1e-8)
-
-
0.0
-
-
-
-
-
-

Rational numbers

-

Rational numbers can be used when the exactness of the number is more important than the speed or wider range of values offered by floating point numbers. In Julia a rational number is comprised of a numerator and a denominator, each an integer of the same type, and reduced to lowest terms. The operations of addition, subtraction, multiplication, and division will keep their answers as rational numbers. As well, raising a rational number to an integer value will produce a rational number.

-

As mentioned, these are constructed using double slashes:

-
-
1//2, 2//1, 6//4
-
-
(1//2, 2//1, 3//2)
-
-
-

Rational numbers are exact, so the following are identical to their mathematical counterparts:

-
-
1//10 + 2//10 == 3//10
-
-
true
-
-
-

and associativity:

-
-
(1//10 + 2//10) + 3//10 == 1//10 + (2//10 + 3//10)
-
-
true
-
-
-

Here we see that the type is preserved under the basic operations:

-
-
(1//2 + 1//3 * 1//4 / 1//5) ^ 6
-
-
1771561//2985984
-
-
-

For powers, a non-integer exponent is converted to floating point, so this operation is defined, though will always return a floating point value:

-
-
(1//2)^(1//2)   # the first parentheses are necessary as `^` will be evaluated before `//`.
-
-
0.7071067811865476
-
-
-
-
-

Complex numbers

-

Complex numbers in Julia are stored as two numbers, a real and imaginary part, each some type of Real number. The special constant im is used to represent \(i=\sqrt{-1}\). This makes the construction of complex numbers fairly standard:

-
-
1 + 2im, 3 + 4.0im
-
-
(1 + 2im, 3.0 + 4.0im)
-
-
-

(These two aren’t exactly the same, the 3 is promoted from an integer to a float to match the 4.0. Each of the components must be of the same type of number.)

-

Mathematically, complex numbers are needed so that certain equations can be satisfied. For example \(x^2 = -2\) has solutions \(-\sqrt{2}i\) and \(\sqrt{2}i\) over the complex numbers. Finding this in Julia requires some attention, as we have both sqrt(-2) and sqrt(-2.0) throwing a DomainError, as the sqrt function expects non-negative real arguments. However first creating a complex number and then taking a square root does work:

-
-
sqrt(-2 + 0im)
-
-
0.0 + 1.4142135623730951im
-
-
-

For complex arguments, the sqrt function will return complex values (even if the answer is a real number).

-

This means, if you wanted to perform the quadratic equation for any real inputs, your computations might involve something like the following:

-
-
a,b,c = 1,2,3  ## x^2 + 2x + 3
-discr = b^2 - 4a*c
-(-b + sqrt(discr + 0im))/(2a), (-b - sqrt(discr + 0im))/(2a)
-
-
(-1.0 + 1.4142135623730951im, -1.0 - 1.4142135623730951im)
-
-
-

When learning calculus, the only common usage of complex numbers arises when solving polynomial equations for roots, or zeros, though they are very important for subsequent work using the concepts of calculus.

-
-
-

Irrational numbers

-

Julia has a a few mathematical constants that are stored with a special type Irrational. One such value is pi. There are others in the Base.MathConstants module, and an external package IrrationalConstants.jl.

-

Irrational values may have special methods defined for them which can lead to subtle differences, such as:

-
-
sin(pi), sin(2pi)
-
-
(0.0, -2.4492935982947064e-16)
-
-
-

In computing the product 2pi first the two values are promoted to Float64 and then multiplied, leaving a floating-point approximation of \(2\pi\) for sin to evaluate.

-
-
-

Other types of data: strings and symbols

-

For text, Julia has a String type. When double quotes are used to specify a string, the parser creates this type:

-
-
x = "The quick brown fox jumped over the lazy dog"
-typeof(x)
-
-
String
-
-
-

Values can be inserted into a string through interpolation using a dollar sign.

-
-
animal = "lion"
-x = "The quick brown $(animal) jumped over the lazy dog"
-
-
"The quick brown lion jumped over the lazy dog"
-
-
-

The use of parentheses allows more complicated expressions; it isn’t always necessary.

-

Longer strings can be produced using triple quotes:

-
-
lincoln = """
-Four score and seven years ago our fathers brought forth, upon this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal.
-"""
-
-
"Four score and seven years ago our fathers brought forth, upon this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal.\n"
-
-
-

Strings are comprised of characters which can be produced directly using single quotes:

-
-
'c'
-
-
'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
-
-
-

We won’t use characters in these notes.

-

Finally, Julia has symbols which are interned strings which are used as identifiers. Symbols are used for advanced programming techniques; we will only see them as shortcuts to specify plotting arguments.

-
-
-

Questions

-
-
Question
-

The number created by pi/2 is?

-
-
- -
-
-
-
- -
-
-Select an item -
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
- - - - -
-
-
-
-
Question
-

The number created by 2/2 is?

-
-
- -
-
-
-
- -
-
-Select an item -
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
- - - - -
-
-
-
-
Question
-

The number created by 2//2 is?

-
-
- -
-
-
-
- -
-
-Select an item -
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
- - - - -
-
-
-
-
Question
-

The number created by 1 + 1//2 + 1/3 is?

-
-
- -
-
-
-
- -
-
-Select an item -
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
- - - - -
-
-
-
-
Question
-

The number created by 2^3 is?

-
-
- -
-
-
-
- -
-
-Select an item -
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
- - - - -
-
-
-
-
Question
-

The number created by sqrt(im) is?

-
-
- -
-
-
-
- -
-
-Select an item -
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
- - - - -
-
-
-
-
Question
-

The number created by 2^(-1) is?

-
-
- -
-
-
-
- -
-
-Select an item -
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
- - - - -
-
-
-
-
Question
-

The “number” created by 1/0 is?

-
-
- -
-
-
-
- -
-
-Select an item -
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
- - - - -
-
-
-
-
Question
-

Is (2 + 6) + 7 equal to 2 + (6 + 7)?

-
-
- -
-
-
-
- -
-
-Select an item -
- -
-
- -
-
- -
-
-
-
- - - - -
-
-
-
-
Question
-

Is (2/10 + 6/10) + 7/10 equal to 2/10 + (6/10 + 7/10)?

-
-
- -
-
-
-
- -
-
-Select an item -
- -
-
- -
-
- -
-
-
-
- - - - -
-
-
-
-
Question
-

The following should compute 2^(-1), which if entered directly will return 0.5. Does it?

-
-
a, b = 2, -1
-a^b
-
-
-
- -
-
-
-
- -
-
-Select an item -
- -
-
- -
-
- -
-
-
-
- - - - -
-
-

(This shows the special casing that is done when powers use literal numbers.)

-
-
-
Question
-

In NewScientist we learn “For the first time, physicists have measured changes in an atom to the level of zeptoseconds, or trillionths of a billionth of a second—the smallest division of time yet observed.”

-

That is

-
-
1e-9 / 1e12
-
-
1.0000000000000001e-21
-
-
-

Finding the value through division introduces a floating point deviation. Which of the following values will directly represent a zeptosecond?

-
-
- -
-
-
-
- -
-
- - -
- - -
-
-
- -
- - - - -
-
-
-
-
Question
-

Signed integers are stored on a computer in a special manner. We will see with 8 bit integers, formed by Int8. Eight bit means only 8 0’s or 1’s are used to store a given number. This is a useful format for storing many small integers but for this example, useful as we can more easily track the values.

-

The first bit is a sign bit. Based on these two outputs, can you guess how that works:

-
-
bitstring(Int8(-1)), bitstring(Int8(1))
-
-
("11111111", "00000001")
-
-
-
-
- -
-
-
-
- -
-
- - -
- - -
-
-
-
- - - - -
-
-

Positive numbers and negative numbers are stored a bit differently. Positive numbers just use binary: \(a_0 \cdot 2^0 + a_1 \cdot 2^1 + a_2 \cdot 2^2 + \cdots a_7 \cdot 2^7\). The number \(27\) is \(1 + 2 + 8 + 16\). so have \(a_0 = a_1 = a_3 = a_4 = 1\), the others are \(0\). The bitstring shows:

-
-
bitstring(Int8(27))
-
-
"00011011"
-
-
-

Which bit pattern is used?

-
-
- -
-
-
-
- -
-
- - -
- - -
-
-
-
- - - - -
-
-

Negative numbers are stored using two’s complement format:

-
    -
  • represent the positive number
  • -
  • flip 0 to 1; 1 to 0
  • -
  • add 1 to the value (long addition with carrying)
  • -
-

For \(-27\) we have

-
    -
  • first \(27\): 00011011
  • -
  • then flip each: 11100100
  • -
  • finally add \(1\): 11100101
  • -
-
-
bitstring(Int8(-27))
-
-
"11100101"
-
-
-

The largest positive number is \(127\) for 8-bits and is represented by 01111111. What is the bit pattern of \(-127\)?

-
-
- -
-
-
-
- -
-
- - -
- - -
-
-
- -
- - - - -
-
-

The smallest negative number is \(-128\). Why?

-
-
- -
-
-
-
- -
-
- - -
- - -
-
-
-
- - - - -
-
-

Why all this fuss? Couldn’t there be an easier way?

-

This storage has a big advantage when adding numbers. Let’s look at adding \(-5\) to \(6\). we have:

-
-5 => 11111011
- 6 => 00000110
-      --------
-     100000001  => 00000001
-

The addition is done by carrying a 1 across and then dropping the 9th number when there is such a carry. This leaves the representation for what number?

-
-
- -
-
-
-
- -
-
- - - -
- - -
-
-
-
- - - - -
-
-

The largest positive number that can be represented is \(2^0 + 2^1 + 2^2 + \cdots + 2^7\), where \(7\) is the number of bits minus \(1\). The representation is 01111111. What happens if we add 1 to this number?

-
-
- -
-
-
-
- -
-
- - -
- - -
-
-
-
- - - - -
-
-

The largest possible number for a type is returned by typemax. For Int64 (just Int on most systems) what is the largest number?

-
-
- -
-
-
-
- -
-
-
- -
- -
-
-
-
- - - - -
-
-
-
-
Question
-

The Float64 type uses \(11\) bits for an exponent (base \(2\)) between \(-1023\) and \(1024\). We can see how these are stored as follows:

-
-
bitstring(2.0^(-1023))[2:12], bitstring(2.0^(1024))[2:12]
-
-
("00000000000", "11111111111")
-
-
-

This is the full range of values. However the values are shifted with \(0\) representing \(-1023\) and \(x\) representing \(1024\). The value \(x\) is can be found from:

-
-
2^0 + 2^1 + 2^2 + 2^3 + 2^4 + 2^5 + 2^6 + 2^7 + 2^8 + 2^9 + 2^10
-
-

What is the value of \(x\)?

-
-
- -
-
-
-
- -
-
-
- -
- -
-
-
-
- - - - -
-
-

The value 1023 is called a bias. The exponent is coded as the binary value as a positve integer minus \(1023\). A bias is used, and not the two’s complement format, as storage with a bias makes multiplying by powers of \(2\) as easy as shifting the bits.

-

To find the storage for, say, \(2^4 + 2^2 + 2^0\) or 00000010101 we would add 1023 or 01111111111 and see:

-
  00000010101
-+ 01111111111
-  -----------
-  10000010100
-

Which we can see:

-
-
bitstring(2.0^(2^4 + 2^2 + 2^0))[2:12]
-
-
"10000010100"
-
-
-
-
- - -

Footnotes

- -
    -
  1. The output of bitstring is 64 characters. The first is the sign bit, the second through twelfth the exponent, the rest the significand. The notation [13:end] is used to return just those for the significand. A value of [2:12] would return the bits for the exponent.↩︎

  2. -
-
- - -
- - - - - \ No newline at end of file diff --git a/quarto/basics/numbers_types-II.qmd b/quarto/basics/numbers_types-II.qmd index 8e56a0b..b3df377 100644 --- a/quarto/basics/numbers_types-II.qmd +++ b/quarto/basics/numbers_types-II.qmd @@ -657,7 +657,7 @@ val = sum(2^i for i in 0:10) numericq(val) ``` -The value `1023` is called a bias. The exponent is coded as the binary value as a positve integer minus $1023$. A bias is used, and not the two's complement format, as storage with a bias makes multiplying by powers of $2$ as easy as shifting the bits. +The value `1023` is called a bias. The exponent is coded as the binary value as a positive integer minus $1023$. A bias is used, and not the two's complement format, as storage with a bias makes multiplying by powers of $2$ as easy as shifting the bits. To find the storage for, say, $2^4 + 2^2 + 2^0$ or `00000010101` we would add `1023` or `01111111111` and see: diff --git a/quarto/basics/numbers_types.qmd b/quarto/basics/numbers_types.qmd index da47b11..399e784 100644 --- a/quarto/basics/numbers_types.qmd +++ b/quarto/basics/numbers_types.qmd @@ -677,7 +677,7 @@ val = sum(2^i for i in 0:10) numericq(val) ``` -The value `1023` is called a bias. The exponent is coded as the binary value as a positve integer minus $1023$. A bias is used, and not the two's complement format, as storage with a bias makes multiplying by powers of $2$ as easy as shifting the bits. +The value `1023` is called a bias. The exponent is coded as the binary value as a positive integer minus $1023$. A bias is used, and not the two's complement format, as storage with a bias makes multiplying by powers of $2$ as easy as shifting the bits. To find the storage for, say, $2^4 + 2^2 + 2^0$ or `00000010101` we would add `1023` or `01111111111` and see: diff --git a/quarto/basics/vectors.qmd b/quarto/basics/vectors.qmd index 1247b5e..83c8d9c 100644 --- a/quarto/basics/vectors.qmd +++ b/quarto/basics/vectors.qmd @@ -33,7 +33,7 @@ $$ This formula agrees with Pythagorean's theorem for right triangles. -For $n$-dimensional points, the same formula may be used with adjustements to the notation. Suppose $P = (x_1, x_2, \dots, x_n)$ and $Q = (y_1, y_2, \cdots, y_n)$. then +For $n$-dimensional points, the same formula may be used with adjustments to the notation. Suppose $P = (x_1, x_2, \dots, x_n)$ and $Q = (y_1, y_2, \cdots, y_n)$. then $$ d = \overline{PQ} = \sqrt{(x_1 - y_1)^2 + (x_2 - y_2)^2 + \cdots + (x_n - y_n)^2}. @@ -56,7 +56,7 @@ A two-dimensional vector has two components, as does a point in the Cartesian pl Suppose a vector is defined as being between two points $P = (x_1, y_1)$ and $Q = (x_2, y_2)$ with $P$ the endpoint, then the vector connecting $P$ to $Q$ would be $\vec{v} = \langle x_2 - x_1, ~ y_2 - y_1 \rangle$. -When $P = (0,0)$, the the point $Q = (x_2, y_2)$ has the same components as the vector $\vec{v} = \langle x_2, ~ y_2 \rangle$ leading to a natural indentification between a point and vector, though they represent different things. +When $P = (0,0)$, the the point $Q = (x_2, y_2)$ has the same components as the vector $\vec{v} = \langle x_2, ~ y_2 \rangle$ leading to a natural identification between a point and vector, though they represent different things. @@ -767,7 +767,7 @@ Broadcasting is a widely used and powerful surface syntax which we will employ o #### Mapping a function over a collection -The `map` function is very much related to broadcasting, in that it applies a function to each element of an iterable. When more than one iterable is specifed, `map` applies the function to the `zip`ped iterables. Unlike broadcasting, `map` does not reshape the underlying iterables. +The `map` function is very much related to broadcasting, in that it applies a function to each element of an iterable. When more than one iterable is specified, `map` applies the function to the `zip`ped iterables. Unlike broadcasting, `map` does not reshape the underlying iterables. Similarly named functions are found in many different programming languages, as `map` is one of the foundational higher-order, functional programming operations. (The "dot" broadcast is mostly limited to `Julia` and mirrors a similar usage of a dot in `MATLAB`.) For those familiar with other programming languages, using `map` may seem more natural. Its syntax is `map(f, xs)`. Additional iterables are passed after `xs`. @@ -787,7 +787,7 @@ sum(map(sin, xs)) This has a performance drawback---there are two passes through the container, one to apply `sin` another to add. -For this task, the `sum` reduction, as others, allows a function to be specified that is applied to each value in the container while the sum is being computed. This argument comes first. A recommened alternative to the previous would be: +For this task, the `sum` reduction, as others, allows a function to be specified that is applied to each value in the container while the sum is being computed. This argument comes first. A recommended alternative to the previous would be: ```{julia} sum(sin, xs) diff --git a/quarto/derivatives/curve_sketching.qmd b/quarto/derivatives/curve_sketching.qmd index e9aa229..ee27dee 100644 --- a/quarto/derivatives/curve_sketching.qmd +++ b/quarto/derivatives/curve_sketching.qmd @@ -112,7 +112,7 @@ let end # (2) periodic behaviour, - i == 2 && (title = "No periodic behavious") + i == 2 && (title = "No periodic behaviours") if i >= 2 end diff --git a/quarto/derivatives/first_second_derivatives.qmd b/quarto/derivatives/first_second_derivatives.qmd index 869d4b4..2a85f45 100644 --- a/quarto/derivatives/first_second_derivatives.qmd +++ b/quarto/derivatives/first_second_derivatives.qmd @@ -58,7 +58,7 @@ A parallel definition with $a < b$ implying $f(a) > f(b)$ would be used for a *s ::: -We introduce a helper function `plotif` from the `CalculusWithJulia` package that highlights the graph of a function $f$ when another function $g(x)$ satisifies $g(x) \geq 0$. This function is called as `plotif(f, g, a, b)`. +We introduce a helper function `plotif` from the `CalculusWithJulia` package that highlights the graph of a function $f$ when another function $g(x)$ satisfies $g(x) \geq 0$. This function is called as `plotif(f, g, a, b)`. To see where a function is positive, we simply pass the function object in for *both* `f` and `g` above. For example, in @fig-plotif-sin-sin-minus-2pi-2pi we look at where $f(x) = \sin(x)$ is positive. diff --git a/quarto/differentiable_vector_calculus/test.html b/quarto/differentiable_vector_calculus/test.html deleted file mode 100644 index 26d9d85..0000000 --- a/quarto/differentiable_vector_calculus/test.html +++ /dev/null @@ -1,641 +0,0 @@ - - - - - - - - - -test - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- -
-
-

Applications with scalar functions

-
- - - -
- - - - -
- - - -
- - -

This section uses these add-on packages:

-
-
using CalculusWithJulia
-using Plots
-plotly()
-using SymPy
-using Roots
-
-
-
Example
-

Consider the function \(f(x,y) = x^2 + 3y^2 -x\) over the region \(x^2 + y^2 \leq 1\). This is a continuous function over a closed set, so will have both an absolute maximum and minimum. Find these from an investigation of the critical points and the boundary points.

-

The gradient is easily found: \(\nabla{f} = \langle 2x - 1, 6y \rangle\), and is \(\vec{0}\) only at \(\vec{a} = \langle 1/2, 0 \rangle\). The Hessian is:

-

\[ -H = -\begin{bmatrix} -2 & 0\\ -0 & 6 -\end{bmatrix}. -\]

-

At \(\vec{a}\) this has positive determinant and \(f_{xx} > 0\), so \(\vec{a}\) corresponds to a local minimum with values \(f(\vec{a}) = (1/2)^2 + 3(0) - 1/2 = -1/4\). The absolute maximum and minimum may occur here (well, not the maximum) or on the boundary, so that must be considered. In this case we can easily parameterize the boundary and turn this into the univariate case:

-
-
fₗ(x,y) = x^2 + 2y^2 - x
-gammaₗ(t) = [cos(t), sin(t)]  # traces out x^2 + y^2 = 1 over [0, 2pi]
-gₗ = splat(fₗ)  gammaₗ
-
-cpsₗ = find_zeros(gₗ', 0, 2pi) # critical points of g
-append!(cpsₗ, [0, 2pi])
-unique!(cpsₗ)
-gₗ.(cpsₗ)
-
-
5-element Vector{Float64}:
- 0.0
- 2.25
- 2.0
- 2.25
- 0.0
-
-
-

We see that maximum value is 2.25 and that the interior point, \(\vec{a}\), will be where the minimum value occurs. To see exactly where the maximum occurs, we look at the values of gamma:

-
-
inds = [2,4]
-cpsₗ[inds]
-
-
2-element Vector{Float64}:
- 2.0943951023931953
- 4.1887902047863905
-
-
-

These are multiples of \(\pi\):

-
-
cpsₗ[inds]/pi
-
-
2-element Vector{Float64}:
- 0.6666666666666666
- 1.3333333333333333
-
-
-

So we have the maximum occurs at the angles \(2\pi/3\) and \(4\pi/3\). Here we visualize, using a hacky trick of assigning NaN values to the function to avoid plotting outside the circle:

-
-
hₗ(x,y) = fₗ(x,y) * (x^2 + y^2 <= 1 ? 1 : NaN)
-
-
hₗ (generic function with 1 method)
-
-
-
-
gr()
-
-
Plots.GRBackend()
-
-
-
-
xs = ys = range(-1,1, length=100)
-plt = surface(xs, ys, hₗ)
-
-ts = cpsₗ  # 2pi/3 and 4pi/3 by above
-xs, ys = cos.(ts), sin.(ts)
-zs = fₗ.(xs, ys)
-scatter3d!(xs, ys, zs)
-#tuple.(xs, ys, zs)
-#plot!(plt, tuple.(xs, ys, zs); linetype=:scatter)
-#plt
-
- -
-
-

A contour plot also shows that some—and only one—extrema happens on the interior:

- -
- -
- - -
- - - - - \ No newline at end of file diff --git a/quarto/differentiable_vector_calculus/test.jl b/quarto/differentiable_vector_calculus/test.jl deleted file mode 100644 index fe58175..0000000 --- a/quarto/differentiable_vector_calculus/test.jl +++ /dev/null @@ -1,827 +0,0 @@ -@show 4 -using QuizQuestions -using LaTeXStrings -using CalculusWithJulia -using Plots -plotly() -using SymPy -using Roots -@show 6 -import Contour: contours, levels, level, lines, coordinates -@show 15 -@syms f_x f_y -n = [1, 0, f_x] × [0, 1, f_y] -@show 27 -#| hold: true -f(x,y) = 6 - x^2 -y^2 -f(x)= f(x...) - -a,b = 1, -1/2 - - -# draw surface -xr = 7/4 -xs = ys = range(-xr, xr, length=100) -surface(xs, ys, f, legend=false) - -# visualize tangent plane as 3d polygon -pt = [a,b] -tplane(x) = f(pt) + gradient(f)(pt) ⋅ (x - [a,b]) - -pts = [[a-1,b-1], [a+1, b-1], [a+1, b+1], [a-1, b+1], [a-1, b-1]] -plot!(unzip([[pt..., tplane(pt)] for pt in pts])...) - -# plot paths in x and y direction through (a,b) -γ_x(t) = pt + t*[1,0] -γ_y(t) = pt + t*[0,1] - -plot_parametric!((-xr-a)..(xr-a), t -> [γ_x(t)..., (f∘γ_x)(t)], linewidth=3) -plot_parametric!((-xr-b)..(xr-b), t -> [γ_y(t)..., (f∘γ_y)(t)], linewidth=3) - -# draw directional derivatives in 3d and normal -pt = [a, b, f(a,b)] -fx, fy = gradient(f)(a,b) -arrow!(pt, [1, 0, fx], linewidth=3) -arrow!(pt, [0, 1, fy], linewidth=3) -arrow!(pt, [-fx, -fy, 1], linewidth=3) # normal - -# draw point in base, x-y, plane -pt = [a, b, 0] -scatter!(unzip([pt])...) -arrow!(pt, [1,0,0], linestyle=:dash) -arrow!(pt, [0,1,0], linestyle=:dash) -@show 33 -function tangent_plane_1st_crack(f, pt) - fx, fy = ForwardDiff.gradient(f, pt) - x -> f(x...) + fx * (x[1]-pt[1]) + fy * (x[2]-pt[2]) -end -@show 35 -function tangent_plane(f, pt) - ∇f = ForwardDiff.gradient(f, pt) # using a variable ∇f - x -> f(pt) + ∇f ⋅ (x - pt) -end -@show 46 -@syms x, y -@show 47 -#| hold: true -f(x,y) = sin(x) * cos(x-y) -f(x) = f(x...) -vars = [x, y] - -gradf = diff.(f(x,y), vars) # or use gradient(f, vars) or ∇((f,vars)) - -pt = [PI/4, PI/3] -gradfa = subs.(gradf, x=>pt[1], y=>pt[2]) - -f(pt) + gradfa ⋅ (vars - pt) -@show 55 -#| hold: true -a = 1 -gamma(t) = a * [1 + cos(t), sin(t), 2sin(t/2) ] -P = gamma(1/2) -n1(x,y,z)= [2*(x-a), 2y, 0] -n2(x,y,z) = [2x,2y,2z] -n1(x) = n1(x...) -n2(x) = n2(x...) - -t = 1/2 -(n1(gamma(t)) × n2(gamma(t))) × gamma'(t) -@show 60 -#| hold: true -a, b = 1, 3 -f(x,y,z) = (x^2 + ((1+b) * y)^2 + z^2 - 1)^3 - x^2 * z^3 - a * y^2 * z^3 - -CalculusWithJulia.plot_implicit_surface(f, xlim=-2..2, ylim=-1..1, zlim=-1..2) -@show 71 -V(r, h) = pi * r^2 * h -V(v) = V(v...) -a₁ = [1,2] -dx₁ = [0.01, 0.01] -ForwardDiff.gradient(V, a₁) ⋅ dx₁ # or use ∇(V)(a) -@show 73 -V(a₁ + dx₁) - V(a₁) -@show 85 -#| hold: true -f(x,y,z) = x^4 -x^3 + y^2 + z^2 -f(v) = f(v...) -a, b,c = ∇(f)(2,2,2) -"$a x + $b y + $c z = $([a,b,c] ⋅ [2,2,2])" -#@show 92 -#| hold: true -@syms a b c d u v -M = [a b; c d] -B = [u, v] -M \ B .|> simplify -@show 96 -#| hold: true -#| echo: false -f(x,y) = 2 - x^2 - y^2 -g(x,y) = 3 - 2x^2 - (1/3)y^2 -xs = ys = range(-3, stop=3, length=100) -zfs = [f(x,y) for x in xs, y in ys] -zgs = [g(x,y) for x in xs, y in ys] - - -ps = Any[] -pf = surface(xs, ys, f, alpha=0.5, legend=false) - -for cl in levels(contours(xs, ys, zfs, [0.0])) - for line in lines(cl) - _xs, _ys = coordinates(line) - plot!(pf, _xs, _ys, 0*_xs, linewidth=3, color=:blue) - end -end - - -pg = surface(xs, ys, g, alpha=0.5, legend=false) -for cl in levels(contours(xs, ys, zgs, [0.0])) - for line in lines(cl) - _xs, _ys = coordinates(line) - plot!(pg, _xs, _ys, 0*_xs, linewidth=3, color=:red) - end -end - -pcnt = plot(legend=false) -for cl in levels(contours(xs, ys, zfs, [0.0])) - for line in lines(cl) - _xs, _ys = coordinates(line) - plot!(pcnt, _xs, _ys, linewidth=3, color=:blue) - end -end - -for cl in levels(contours(xs, ys, zgs, [0.0])) - for line in lines(cl) - _xs, _ys = coordinates(line) - plot!(pcnt, _xs, _ys, linewidth=3, color=:red) - end -end - -l = @layout([a b c]) -plot(pf, pg, pcnt, layout=l) -@show 106 -function newton_step(f, g, xn) - M = [ForwardDiff.gradient(f, xn)'; ForwardDiff.gradient(g, xn)'] - b = -[f(xn), g(xn)] - Delta = M \ b - xn + Delta -end -@show 108 -𝒇(x,y) = 2 - x^2 - y^2 -𝒈(x,y) = 3 - 2x^2 - (1/3)y^2 -𝒇(v) = 𝒇(v...); 𝒈(v) = 𝒈(v...) -𝒙₀ = [1,1] -𝒙₁ = newton_step(𝒇, 𝒈, 𝒙₀) -@show 110 -𝒇(𝒙₁), 𝒈(𝒙₁) -@show 112 -𝒙₂ = newton_step(𝒇, 𝒈, 𝒙₁) -𝒙₃ = newton_step(𝒇, 𝒈, 𝒙₂) -𝒙₄ = newton_step(𝒇, 𝒈, 𝒙₃) -𝒙₅ = newton_step(𝒇, 𝒈, 𝒙₄) -𝒙₅, 𝒇(𝒙₅), 𝒈(𝒙₅) -@show 116 -function nm(f, g, x, n=5) - for i in 1:n - x = newton_step(f, g, x) - end - x -end -@show 123 -#| hold: true -c = 1/2 -f(x,y) = 1 - y^2 - c^2 -g(x,y) = (1 - x^2) - c^2 -f(v) = f(v...); g(v) = g(v...) -nm(f, g, [1/2, 1/3]) -@show 148 -#| hold: true -@syms x, y, Z() -∂x = solve(diff(x^4 -x^3 + y^2 + Z(x,y)^2, x), diff(Z(x,y),x)) -∂y = solve(diff(x^4 -x^3 + y^2 + Z(x,y)^2, y), diff(Z(x,y),y)) -∂x, ∂y -@show 158 -f(x, p) = cos(x) - p*x -p = 2 -xᵅ = find_zero(f, (0, pi/2), p) -@show 160 -p = 2 -xᵅ = find_zero(f, (0, pi/2), p) -fₓ = ForwardDiff.derivative(x -> f(x,p), xᵅ) -fₚ = ForwardDiff.derivative(p -> f(xᵅ, p), p) -- fₚ / fₓ -@show 163 -function find_zero_derivative(f, x₀, p) - xᵅ = find_zero(f, x₀, p) - fₓ = ForwardDiff.derivative(x -> f(x,p), xᵅ) - fₚ = ForwardDiff.derivative(p -> f(xᵅ, p), p) - - fₚ / fₓ -end -F(p) = find_zero_derivative(f, (0, pi/2), p) -plot(F, 0.01, 5) # p > 0 -@show 183 -#| hold: true -f(x,y)= exp(-(x^2 + y^2)/5) * cos(x^2 + y^2) -xs = ys = range(-4, 4, length=100) -surface(xs, ys, f, legend=false) -@show 190 -#| hold: true -f(x,y) = x*y -xs = ys = range(-3, 3, length=100) -surface(xs, ys, f, legend=false) - -plot_parametric!(-4..4, t -> [t, 0, f(t, 0)], linewidth=5) -plot_parametric!(-4..4, t -> [0, t, f(0, t)], linewidth=5) -@show 203 -fₖ(x,y) = exp(-(x^2 + y^2)/5) * cos(x^2 + y^2) -Hₖ = sympy.hessian(fₖ(x,y), (x,y)) -@show 205 -H₀₀ = subs.(Hₖ, x=>0, y=>0) -@show 207 -H₀₀[1,1] < 0 && det(H₀₀) > 0 -@show 209 -#| hold: true -gradfₖ = diff.(fₖ(x,y), [x,y]) -a = [sqrt(2PI + atan(-Sym(1)//5)), 0] -subs.(gradfₖ, x => a[1], y => a[2]) -@show 211 -#| hold: true -a = [sqrt(PI + atan(-Sym(1)//5)), 0] -H_a = subs.(Hₖ, x => a[1], y => a[2]) -det(H_a) -@show 216 -fⱼ(x,y) = 4x*y - x^4 - y^4 -gradfⱼ = diff.(fⱼ(x,y), [x,y]) -@show 217 -all_ptsⱼ = solve(gradfⱼ, [x,y]) -ptsⱼ = filter(u -> all(isreal.(u)), all_ptsⱼ) -@show 219 -Hⱼ = sympy.hessian(fⱼ(x,y), (x,y)) -function classify(H, pt) - Ha = subs.(H, x => pt[1], y => pt[2]) - (det=det(Ha), f_xx=Ha[1,1]) -end -[classify(Hⱼ, pt) for pt in ptsⱼ] -@show 221 -#| hold: true -xs = ys = range(-3/2, 3/2, length=100) -p = surface(xs, ys, fⱼ, legend=false) -for pt ∈ ptsⱼ - scatter!(p, unzip([N.([pt...,fⱼ(pt...)])])..., - markercolor=:black, markersize=5) # add each pt on surface -end -p -@show 228 -fₗ(x,y) = x^2 + 2y^2 - x -fₗ(v) = fₗ(v...) -gammaₗ(t) = [cos(t), sin(t)] # traces out x^2 + y^2 = 1 over [0, 2pi] -gₗ = fₗ ∘ gammaₗ - -cpsₗ = find_zeros(gₗ', 0, 2pi) # critical points of g -append!(cpsₗ, [0, 2pi]) -unique!(cpsₗ) -gₗ.(cpsₗ) -@show 230 -inds = [2,4] -cpsₗ[inds] -@show 232 -cpsₗ[inds]/pi -@show 234 -hₗ(x,y) = fₗ(x,y) * (x^2 + y^2 <= 1 ? 1 : NaN) -@show 235 -#| hold: true -xs = ys = range(-1,1, length=100) -surface(xs, ys, hₗ) - -ts = cpsₗ # 2pi/3 and 4pi/3 by above -xs, ys = cos.(ts), sin.(ts) -zs = fₗ.(xs, ys) -scatter3d!(xs, ys, zs) -@show 237 -#| hold: true -xs = ys = range(-1,1, length=100) -contour(xs, ys, hₗ) -@show 243 -@syms x1 y1 x2 y2 x3 y3 -d2(p,x) = (p[1] - x[1])^2 + (p[2]-x[2])^2 -d2_1, d2_2, d2_3 = d2((x,y), (x1, y1)), d2((x,y), (x2, y2)), d2((x,y), (x3, y3)) -exₛ = d2_1 + d2_2 + d2_3 -@show 245 -gradfₛ = diff.(exₛ, [x,y]) -xstarₛ = solve(gradfₛ, [x,y]) -@show 248 -Hₛ = subs.(hessian(exₛ, [x,y]), x=>xstarₛ[x], y=>xstarₛ[y]) -@show 259 -usₛ = [[cos(t), sin(t)] for t in (0, 2pi/3, 4pi/3)] -polygon(ps) = unzip(vcat(ps, ps[1:1])) # easier way to plot a polygon - -pₛ = scatter([0],[0], markersize=2, legend=false, aspect_ratio=:equal) - -asₛ = (1,2,3) -plot!(polygon([a*u for (a,u) in zip(asₛ, usₛ)])...) -[arrow!([0,0], a*u, alpha=0.5) for (a,u) in zip(asₛ, usₛ)] -pₛ -@show 261 -asₛ₁ = (1, -1, 3) -scatter([0],[0], markersize=2, legend=false) -psₛₗ = [a*u for (a,u) in zip(asₛ₁, usₛ)] -plot!(polygon(psₛₗ)...) -@show 263 -euclid_dist(x; ps=psₛₗ) = sum(norm(x-p) for p in ps) -euclid_dist(x,y; ps=psₛₗ) = euclid_dist([x,y]; ps=ps) -@show 264 -#| hold: true -xs = range(-1.5, 1.5, length=100) -ys = range(-3, 1.0, length=100) - -p = plot(polygon(psₛₗ)..., linewidth=3, legend=false) -scatter!(p, unzip(psₛₗ)..., markersize=3) -contour!(p, xs, ys, euclid_dist) - -# add some gradients along boundary -li(t, p1, p2) = p1 + t*(p2-p1) # t in [0,1] -for t in range(1/100, 1/2, length=3) - pt = li(t, psₛₗ[2], psₛₗ[3]) - arrow!(pt, ForwardDiff.gradient(euclid_dist, pt)) - pt = li(t, psₛₗ[2], psₛₗ[1]) - arrow!(pt, ForwardDiff.gradient(euclid_dist, pt)) -end - -p -@show 266 -#| hold : true -li(t, p1, p2) = p1 + t*(p2-p1) -p = plot(legend=false) -for i in 1:2, j in (i+1):3 - plot!(p, t -> euclid_dist(li(t, psₛₗ[i], psₛₗ[j]); ps=psₛₗ), 0, 1) -end -p -@show 280 -@syms xₗₛ[1:3] yₗₛ[1:3] α β -li(x, alpha, beta) = alpha + beta * x -d₂(alpha, beta) = sum((y - li(x, alpha, beta))^2 for (y,x) in zip(yₗₛ, xₗₛ)) -d₂(α, β) -@show 282 -grad_d₂ = diff.(d₂(α, β), [α, β]) -@show 283 -outₗₛ = solve(grad_d₂, [α, β]) -@show 285 -subs(outₗₛ[β], sum(xₗₛ) => 0) -@show 292 -[k => subs(v, xₗₛ[1]=>1, yₗₛ[1]=>1, xₗₛ[2]=>2, yₗₛ[2]=>3, - xₗₛ[3]=>5, yₗₛ[3]=>8) for (k,v) in outₗₛ] -@show 302 -f₂(x,y) = -exp(-((x-1)^2 + 2(y-1/2)^2)) -f₂(x) = f₂(x...) - -xs₂ = [[0.0, 0.0]] # we store a vector -gammas₂ = [1.0] - -for n in 1:5 - xn = xs₂[end] - gamma₀ = gammas₂[end] - xn1 = xn - gamma₀ * gradient(f₂)(xn) - dx, dy = xn1 - xn, gradient(f₂)(xn1) - gradient(f₂)(xn) - gamman1 = abs( (dx ⋅ dy) / (dy ⋅ dy) ) - - push!(xs₂, xn1) - push!(gammas₂, gamman1) -end - -[(x, f₂(x)) for x in xs₂] -@show 304 -#| hold: true -function surface_contour(xs, ys, f; offset=0) - p = surface(xs, ys, f, legend=false, fillalpha=0.5) - - ## we add to the graphic p, then plot - zs = [f(x,y) for x in xs, y in ys] # reverse order for use with Contour package - for cl in levels(contours(xs, ys, zs)) - lvl = level(cl) # the z-value of this contour level - for line in lines(cl) - _xs, _ys = coordinates(line) # coordinates of this line segment - _zs = offset * _xs - plot!(p, _xs, _ys, _zs, alpha=0.5) # add curve on x-y plane - end - end - p -end - - -offset = 0 -us = vs = range(-1, 2, length=100) -surface_contour(us, vs, f₂, offset=offset) -pts = [[pt..., offset] for pt in xs₂] -scatter3d!(unzip(pts)...) -plot!(unzip(pts)..., linewidth=3) -@show 314 -function peaks(x, y) - z = 3 * (1 - x)^2 * exp(-x^2 - (y + 1)^2) - z += -10 * (x / 5 - x^3 - y^5) * exp(-x^2 - y^2) - z += -1/3 * exp(-(x+1)^2 - y^2) - return z -end -peaks(v) = peaks(v...) -@show 315 -#| hold: true -xs = range(-3, stop=3, length=100) -ys = range(-2, stop=2, length=100) -Ps = surface(xs, ys, peaks, legend=false) -Pc = contour(xs, ys, peaks, legend=false) -plot(Ps, Pc, layout=2) # combine plots -@show 319 -function newton_stepₚ(f, x) - M = ForwardDiff.hessian(f, x) - b = ForwardDiff.gradient(f, x) - x - M \ b -end -@show 321 -xₚ = [0, 1.5] -xₚ = newton_stepₚ(peaks, xₚ) -xₚ = newton_stepₚ(peaks, xₚ) -xₚ = newton_stepₚ(peaks, xₚ) -xₚ, ForwardDiff.gradient(peaks, xₚ) -@show 323 -Hₚ = ForwardDiff.hessian(peaks, xₚ) -@show 325 -#| hold: true -fxx = Hₚ[1,1] -d = det(Hₚ) -fxx, d -@show 335 -#| hold: true -g(x,y) = x^2 + 2y^2 -1 -g(v) = g(v...) - -xs = range(-3, 3, length=100) -ys = range(-1, 4, length=100) - -p = plot(aspect_ratio=:equal, legend=false) -contour!(xs, ys, g, levels=[0]) - -gi(x) = sqrt(1/2*(1-x^2)) # solve for y in terms of x -pts = [[x, gi(x)] for x in (-3/4, -1/4, 1/4, 3/4)] - -for pt in pts - arrow!(pt, ForwardDiff.gradient(g, pt) ) -end - -p -@show 338 -#| hold: true -#| echo: false -r(t) = [cos(t), sin(t)/2] -plot_parametric(pi/12..pi/3, r, legend=false, aspect_ratio=true, linewidth=3) -T(t) = -r'(t) / norm(r'(t)) -No(t) = T'(t) / norm(T'(t)) -t = pi/4 -lambda=1/10 -scatter!(unzip([r(t)])...) -arrow!(r(t), T(t)*lambda) -arrow!(r(t), No(t)* lambda) - -f(x,y)= x^2 + y^2 -f(v) = f(v...) -arrow!(r(t), lambda*ForwardDiff.gradient(f, r(t))) - -xs = range(0.5,1, length=100) -ys = range(0.1, 0.5, length=100) -contour!(xs, ys, f) -@show 344 -#| hold: true -#| echo: false -r(t) = [cos(t), sin(t)/2] -plot_parametric(-pi/6..pi/6,r, legend=false, aspect_ratio=true, linewidth=3) -T(t) = -r'(t) / norm(r'(t)) -No(t) = T'(t) / norm(T'(t)) -t = 0 -lambda=1/10 -scatter!(unzip([r(t)])...) -arrow!(r(t), T(t)*lambda) -arrow!(r(t), No(t)* lambda) - -f(x,y)= x^2 + y^2 -f(v) = f(v...) -arrow!(r(t), lambda*ForwardDiff.gradient(f, r(t))) - -xs = range(0.5,1.5, length=100) -ys = range(-0.5, 0.5, length=100) -contour!(xs, ys, f, levels = [.7, .85, 1, 1.15, 1.3]) -@show 381 -@syms lambda -fₗₐ(x, y) = x^2 - y^2 -gₗₐ(x, y) = x^2 + y^2 -Lₗₐ(x, y, lambda) = fₗₐ(x,y) - lambda * (gₗₐ(x,y) - 1) -dsₗₐ = solve(diff.(Lₗₐ(x, y, lambda), [x, y, lambda])) -@show 383 -[fₗₐ(d[x], d[y]) for d in dsₗₐ] -@show 432 -#| hold: true -@syms y y′ λ C -ex = Eq(-λ*y′^2/sqrt(1 + y′^2) + λ*sqrt(1 + y′^2), y - C) -Δ = sqrt(1 + y′^2) / (y - C) -ex1 = Eq(simplify(ex.lhs()*Δ), simplify(ex.rhs() * Δ)) -ex2 = Eq(ex1.lhs()^2 - 1, simplify(ex1.rhs()^2) - 1) -@show 457 -@syms z lambda1 lambda2 -g1(x, y, z) = x^2 + y^2 - z^2 -g2(x, y, z) = x - 2z - 3 -fₘ(x,y,z)= x^2 + y^2 + z^2 -Lₘ(x,y,z,lambda1, lambda2) = fₘ(x,y,z) - lambda1*(g1(x,y,z) - 0) - lambda2*(g2(x,y,z) - 0) - -∇Lₘ = diff.(Lₘ(x,y,z,lambda1, lambda2), [x, y, z,lambda1, lambda2]) -@show 459 -solve(subs.(∇Lₘ, lambda1 .=> 1)) -@show 461 -outₘ = solve(subs.(∇Lₘ, y .=> 0)) -@show 463 -[fₘ(d[x], 0, d[z]) for d in outₘ] -@show 498 -struct MultiIndex - alpha::Vector{Int} - end -Base.show(io::IO, α::MultiIndex) = println(io, "α = ($(join(α.alpha, ", ")))") - -## |α| = α_1 + ... + α_m -Base.length(α::MultiIndex) = sum(α.alpha) - -## factorial(α) computes α! -Base.factorial(α::MultiIndex) = prod(factorial(Sym(a)) for a in α.alpha) - -## x^α = x_1^α_1 * x_2^α^2 * ... * x_n^α_n -import Base: ^ -^(x, α::MultiIndex) = prod(u^a for (u,a) in zip(x, α.alpha)) - -## ∂^α(ex) = ∂_1^α_1 ∘ ∂_2^α_2 ∘ ... ∘ ∂_n^α_n (ex) -partial(ex::SymPy.SymbolicObject, α::MultiIndex, vars=free_symbols(ex)) = diff(ex, zip(vars, α.alpha)...) -@show 499 -@syms w -alpha = MultiIndex([1,2,1,3]) -length(alpha) # 1 + 2 + 1 + 3=7 -[1,2,3,4]^alpha -exₜ = x^3 * cos(w*y*z) -partial(exₜ, alpha, [w,x,y,z]) -@show 501 -struct MultiIndices - n::Int - k::Int -end - -function Base.length(as::MultiIndices) - n,k = as.n, as.k - n == 1 && return 1 - sum(length(MultiIndices(n-1, j)) for j in 0:k) # recursively identify length -end - -function Base.iterate(alphas::MultiIndices) - k, n = alphas.k, alphas.n - n == 1 && return ([k],(0, MultiIndices(0,0), nothing)) - - m = zeros(Int, n) - m[1] = k - betas = MultiIndices(n-1, 0) - stb = iterate(betas) - st = (k, MultiIndices(n-1, 0), stb) - return (m, st) -end - -function Base.iterate(alphas::MultiIndices, st) - - st == nothing && return nothing - k,n = alphas.k, alphas.n - k == 0 && return nothing - n == 1 && return nothing - - # can we iterate the next on - bk, bs, stb = st - - if stb==nothing - bk = bk-1 - bk < 0 && return nothing - bs = MultiIndices(bs.n, bs.k+1) - val, stb = iterate(bs) - return (vcat(bk,val), (bk, bs, stb)) - end - - resp = iterate(bs, stb) - if resp == nothing - bk = bk-1 - bk < 0 && return nothing - bs = MultiIndices(bs.n, bs.k+1) - val, stb = iterate(bs) - return (vcat(bk, val), (bk, bs, stb)) - end - - val, stb = resp - return (vcat(bk, val), (bk, bs, stb)) - -end -@show 503 -collect(MultiIndices(2, 3)) -@show 505 -union((collect(MultiIndices(2, i)) for i in 0:3)...) -@show 507 -k = 4 -length(MultiIndices(3, k+1)) -@show 509 -#| hold: true -@syms 𝐅() a[1:3] dx[1:3] - -sum(partial(𝐅(a...), α, a) / factorial(α) * dx^α for k in 0:3 for α in MultiIndex.(MultiIndices(3, k))) # 3rd order -@show 513 -#| hold: true -#| echo: false -f(x,y) = sqrt(x + y) -f(v) = f(v...) -pt = [2,2] -dxdy = [.1, .2] -val = f(pt) + dot(ForwardDiff.gradient(f, pt), dxdy) -numericq(val) -@show 516 -#| hold: true -#| echo: false -f(x,y,z) = x*y + y*z + z*x -f(v) = f(v...) -pt = [1,1,1] -dx = [0.1, 0.0, -0.1] -val = f(pt) + ∇(f)(pt) ⋅ dx -numericq(val) -@show 519 -#| hold: true -#| echo: false -f(x,y,z) = x*y + y*z + z*x - 8 -f(v) = f(v...) -pt = [1,1,1] -n = ∇(f)(pt) -d = dot(n, pt) -choices = [ - raw"`` x + y + z = 3``", - raw"`` 2x + y - 2z = 1``", - raw"`` x + 2y + 3z = 6``" -] -answ = 1 -radioq(choices, answ) -@show 523 -#| hold: true -#| echo: false -choices = [ - raw"`` \langle 2xy + y^2 + y, 2xy + x^2 + x\rangle``", - raw"`` y^2 + y, x^2 + x``", - raw"`` \langle 2y + y^2, 2x + x^2``" -] -answ = 1 -radioq(choices, answ) -@show 527 -#| hold: true -#| echo: false -yesnoq(true) -@show 529 -#| hold: true -#| echo: false -f(x,y) = x*y + x*y^2 + x^2 * y -f(v) = f(v...) -val = det(ForwardDiff.hessian(f, [-1/3, -1/3])) -numericq(val) -@show 531 -#| hold: true -#| echo: false -choices = [ - L"The function $f$ has a local minimum, as $f_{xx} > 0$ and $d >0$", - L"The function $f$ has a local maximum, as $f_{xx} < 0$ and $d >0$", - L"The function $f$ has a saddle point, as $d < 0$", - L"Nothing can be said, as $d=0$" -] -answ = 2 -radioq(choices, answ, keep_order=true) -@show 535 -#| hold: true -#| results: "hidden" -f(x,y) = x + 2x^2 + x^3 + y + 2x*y + y^2 -@syms x::real y::real -gradf = gradient(f(x,y), [x,y]) -@show 536 -#| hold: true -#| echo: false -yesnoq(true) -@show 538 -#| hold: true -#| results: "hidden" -f(x,y) = x + 2x^2 + x^3 + y + 2x*y + y^2 -@syms x::real y::real -gradf = gradient(f(x,y), [x,y]) - -solve(gradf, [x,y]) -@show 539 -#| hold: true -#| echo: false -numericq(2) -@show 541 -#| hold: true -f(x,y) = x + 2x^2 + x^3 + y + 2x*y + y^2 -@syms x::real y::real -gradf = gradient(f(x,y), [x,y]) - -sympy.hessian(f(x,y), [x,y]) -@show 543 -#| hold: true -#| echo: false -choices = [ - L"The function $f$ has a local minimum, as $f_{xx} > 0$ and $d >0$", - L"The function $f$ has a local maximum, as $f_{xx} < 0$ and $d >0$", - L"The function $f$ has a saddle point, as $d < 0$", - L"Nothing can be said, as $d=0$", - L"The test does not apply, as $\nabla{f}$ is not $0$ at this point." -] -answ = 3 -radioq(choices, answ, keep_order=true) -@show 545 -#| hold: true -#| echo: false -choices = [ - L"The function $f$ has a local minimum, as $f_{xx} > 0$ and $d >0$", - L"The function $f$ has a local maximum, as $f_{xx} < 0$ and $d >0$", - L"The function $f$ has a saddle point, as $d < 0$", - L"Nothing can be said, as $d=0$", - L"The test does not apply, as $\nabla{f}$ is not $0$ at this point." -] -answ = 1 -radioq(choices, answ, keep_order=true) -@show 547 -#| hold: true -#| echo: false -choices = [ - L"The function $f$ has a local minimum, as $f_{xx} > 0$ and $d >0$", - L"The function $f$ has a local maximum, as $f_{xx} < 0$ and $d >0$", - L"The function $f$ has a saddle point, as $d < 0$", - L"Nothing can be said, as $d=0$", - L"The test does not apply, as $\nabla{f}$ is not $0$ at this point." -] -answ = 5 -radioq(choices, answ, keep_order=true) -@show 553 -#| hold: true -#| echo: false -yesnoq(true) -@show 557 -#| hold: true -#| echo: false -yesnoq(false) -@show 559 -#| hold: true -#| echo: false -choices =[ - "It is the determinant of the Hessian", - L"It isn't, $b^2-4ac$ is from the quadratic formula" -] -answ = 1 -radioq(choices, answ) -@show 561 -#| hold: true -#| echo: false -choices = [ - L"That $a>0$ and $4ac-b^2 > 0$", - L"That $a<0$ and $4ac-b^2 > 0$", - L"That $4ac-b^2 < 0$" -] -answ = 2 -radioq(choices, answ, keep_order=true) -@show 563 -#| hold: true -#| echo: false -choices = [ - L"That $a>0$ and $4ac-b^2 > 0$", - L"That $a<0$ and $4ac-b^2 > 0$", - L"That $4ac-b^2 < 0$" -] -answ = 3 -radioq(choices, answ, keep_order=true) -@show 569 -#| hold: true -#| echo: false -yesnoq(true) -@show 571 -#| echo: false -choices = [ - raw"`` \langle 2x, 2y\rangle``", - raw"`` \langle 2x, y^2\rangle``", - raw"`` \langle x^2, 2y \rangle``" -] -answ = 1 -radioq(choices, answ) -@show 573 -f(x,y) = exp(-x^2-y^2) * (2x^2 + y^2) -f(v) = f(v...) -r(t) = sqrt(3)*[cos(t), sin(t)] -rat(x) = abs(x[1]/x[2]) - 1 -fn = rat ∘ ∇(f) ∘ r -ts = fzeros(fn, 0, 2pi) -@show 575 -#| eval: false -#| echo: false -f(x,y) = exp(-x^2-y^2) * (2x^2 + y^2) -r(t) = sqrt(3)*[cos(t), sin(t)] -rat(x) = abs(x[1]/x[2]) - 1 -fn = rat ∘ ∇(splat(f)) ∘ r -ts = fzeros(fn, 0, 2pi) - -val = maximum((splat(u)∘r).(ts)) -numericq(val) diff --git a/quarto/differentiable_vector_calculus/test.qmd b/quarto/differentiable_vector_calculus/test.qmd deleted file mode 100644 index 37ab0eb..0000000 --- a/quarto/differentiable_vector_calculus/test.qmd +++ /dev/null @@ -1,98 +0,0 @@ -# Applications with scalar functions - - -{{< include ../_common_code.qmd >}} - -This section uses these add-on packages: - - -```{julia} -using CalculusWithJulia -using Plots -plotly() -using SymPy -using Roots -``` - -##### Example - - -Consider the function $f(x,y) = x^2 + 3y^2 -x$ over the region $x^2 + y^2 \leq 1$. This is a continuous function over a closed set, so will have both an absolute maximum and minimum. Find these from an investigation of the critical points and the boundary points. - - -The gradient is easily found: $\nabla{f} = \langle 2x - 1, 6y \rangle$, and is $\vec{0}$ only at $\vec{a} = \langle 1/2, 0 \rangle$. The Hessian is: - - -$$ -H = -\begin{bmatrix} -2 & 0\\ -0 & 6 -\end{bmatrix}. -$$ - -At $\vec{a}$ this has positive determinant and $f_{xx} > 0$, so $\vec{a}$ corresponds to a *local* minimum with values $f(\vec{a}) = (1/2)^2 + 3(0) - 1/2 = -1/4$. The absolute maximum and minimum may occur here (well, not the maximum) or on the boundary, so that must be considered. In this case we can easily parameterize the boundary and turn this into the univariate case: - - -```{julia} -fₗ(x,y) = x^2 + 2y^2 - x -gammaₗ(t) = [cos(t), sin(t)] # traces out x^2 + y^2 = 1 over [0, 2pi] -gₗ = splat(fₗ) ∘ gammaₗ - -cpsₗ = find_zeros(gₗ', 0, 2pi) # critical points of g -append!(cpsₗ, [0, 2pi]) -unique!(cpsₗ) -gₗ.(cpsₗ) -``` - -We see that maximum value is `2.25` and that the interior point, $\vec{a}$, will be where the minimum value occurs. To see exactly where the maximum occurs, we look at the values of gamma: - -```{julia} -inds = [2,4] -cpsₗ[inds] -``` - -These are multiples of $\pi$: - - -```{julia} -cpsₗ[inds]/pi -``` - -So we have the maximum occurs at the angles $2\pi/3$ and $4\pi/3$. Here we visualize, using a hacky trick of assigning `NaN` values to the function to avoid plotting outside the circle: - - -```{julia} -hₗ(x,y) = fₗ(x,y) * (x^2 + y^2 <= 1 ? 1 : NaN) -``` - -```{julia} -gr() -``` - -```{julia} -#| hold: true -xs = ys = range(-1,1, length=100) -plt = surface(xs, ys, hₗ) - -ts = cpsₗ # 2pi/3 and 4pi/3 by above -xs, ys = cos.(ts), sin.(ts) -zs = fₗ.(xs, ys) -scatter3d!(xs, ys, zs) -#tuple.(xs, ys, zs) -#plot!(plt, tuple.(xs, ys, zs); linetype=:scatter) -#plt -``` - -A contour plot also shows that some---and only one---extrema happens on the interior: - - diff --git a/quarto/integrals/area_between_curves.qmd b/quarto/integrals/area_between_curves.qmd index 490b87c..34017de 100644 --- a/quarto/integrals/area_between_curves.qmd +++ b/quarto/integrals/area_between_curves.qmd @@ -718,7 +718,7 @@ let O = (0, 0) x1, y1 = P = (2, 2) x2, y2 = Q = (1, 3) - plt = plot(; legend=false, aspect_ratio=:equal, framestyle=:orgin) + plt = plot(; legend=false, aspect_ratio=:equal, framestyle=:origin) plot!(plt, [O,P,Q,O]; line=(1, :black)) scatter!(plt, [O, P, Q]; marker=(5, :black)) annotate!(plt, [ diff --git a/quarto/integrals/center_of_mass.qmd b/quarto/integrals/center_of_mass.qmd index 9a1d058..e1f579a 100644 --- a/quarto/integrals/center_of_mass.qmd +++ b/quarto/integrals/center_of_mass.qmd @@ -227,10 +227,10 @@ The bottom integral is just the area (or total mass if the $\rho$ were not cance ##### Example -Find the center of mass formed by the intersection of the parabolas $y=1 - x^2$ and $y=(x-1)^2 - 2$. @fig-center-of-mass-of-two-parabola-1-minus-xsquared-and-x-minus-1-sqared-minus-2 shows that for the $x$ direction, it is close to $1/2$. +Find the center of mass formed by the intersection of the parabolas $y=1 - x^2$ and $y=(x-1)^2 - 2$. @fig-center-of-mass-of-two-parabola-1-minus-xsquared-and-x-minus-1-squared-minus-2 shows that for the $x$ direction, it is close to $1/2$. -::: {#fig-center-of-mass-of-two-parabola-1-minus-xsquared-and-x-minus-1-sqared-minus-2} +::: {#fig-center-of-mass-of-two-parabola-1-minus-xsquared-and-x-minus-1-squared-minus-2} ```{julia} #| echo: false f1(x) = 1 - x^2 diff --git a/quarto/integrals/substitution.qmd b/quarto/integrals/substitution.qmd index 7e97f85..5924a4a 100644 --- a/quarto/integrals/substitution.qmd +++ b/quarto/integrals/substitution.qmd @@ -22,7 +22,7 @@ using SymPy The technique of $u$-[substitution](https://en.wikipedia.org/wiki/Integration_by_substitution) is derived from reversing the chain rule: $[f(g(x))]' = f'(g(x)) g'(x)$. -::: {.definition title="Subsitution"} +::: {.definition title="Substitution"} Suppose that $g$ is continuous and $u(x)$ is differentiable with $u'(x)$ being Riemann integrable. Then both these integrals are defined and are equal: diff --git a/quarto/integrals/surface_area.qmd b/quarto/integrals/surface_area.qmd index 321fd7d..2d80bdd 100644 --- a/quarto/integrals/surface_area.qmd +++ b/quarto/integrals/surface_area.qmd @@ -668,7 +668,7 @@ f(t) = 2(1 + cos(t)) * sin(t) plot(g, f, 0, 1pi) ``` -Paremeterized curve to rotate about $x$ axis +Parameterized curve to rotate about $x$ axis ::: The integrand simplifies to $8\sqrt{2}\pi \sin(t) (1 + \cos(t))^{3/2}$. This lends itself to $u$-substitution with $u=\cos(t)$. diff --git a/quarto/precalc/julia_overview.qmd b/quarto/precalc/julia_overview.qmd index 4fa6389..7eed97b 100644 --- a/quarto/precalc/julia_overview.qmd +++ b/quarto/precalc/julia_overview.qmd @@ -626,7 +626,7 @@ xs = range(0, 2pi, length=251) ys = [sin(2x) + sin(3x) + sin(4x) for x in xs] plot(xs, ys) ``` -Plot of $f(x) = \sin(2x) + \sin(3x) + \sin(4x)$ over $[0, 2\pi]$ made by constructing vectors `xs` , `ys` holding $x$ and $y$ coordiinates of points to include +Plot of $f(x) = \sin(2x) + \sin(3x) + \sin(4x)$ over $[0, 2\pi]$ made by constructing vectors `xs` , `ys` holding $x$ and $y$ coordinates of points to include ::: There are different plotting interfaces. Though not shown, all of these `plot` commands produce a plot of `f`, though with minor differences: diff --git a/quarto/precalc/transformations.qmd b/quarto/precalc/transformations.qmd index c70df7e..a7a8772 100644 --- a/quarto/precalc/transformations.qmd +++ b/quarto/precalc/transformations.qmd @@ -89,7 +89,7 @@ Starting with two functions and composing them requires nothing more than a soli ::: {.callout-note} ## Infix operator -Composition of two functions does have an infix operator, `∘`, entered as `\circ[tab]`. This mirrors the mathematical usage of this syntax, though the order of operations are such that calling the composed function on a value requires an extra set of parentheses: `(f∘g)(x)`, as the expresssion `f∘g(x)` evaluates `g(x)` before the composition. +Composition of two functions does have an infix operator, `∘`, entered as `\circ[tab]`. This mirrors the mathematical usage of this syntax, though the order of operations are such that calling the composed function on a value requires an extra set of parentheses: `(f∘g)(x)`, as the expression `f∘g(x)` evaluates `g(x)` before the composition. ::: diff --git a/quarto/precalc/trig_functions.qmd b/quarto/precalc/trig_functions.qmd index 16de81e..7c3693c 100644 --- a/quarto/precalc/trig_functions.qmd +++ b/quarto/precalc/trig_functions.qmd @@ -1173,7 +1173,7 @@ The sine function is an *odd* function. #| echo: false choices = ["odd", "even", "neither"] answer = 1 -explanation = "subsitute `-x` into the exponential formula to see" +explanation = "substitute `-x` into the exponential formula to see" buttonq(choices, answer; explanation) ``` @@ -1185,7 +1185,7 @@ buttonq(choices, answer; explanation) #| echo: false choices = ["odd", "even", "neither"] answer = 2 -explanation = L"The value of $\cosh(-x)$ is the $y$ position of the point $(x,y)$ refelected through the $y$ axis, so is unchanged." +explanation = L"The value of $\cosh(-x)$ is the $y$ position of the point $(x,y)$ reflected through the $y$ axis, so is unchanged." buttonq(choices, answer; explanation) ```