From 88e4dc1f862d3d019573aa218d8d1bb162c6b608 Mon Sep 17 00:00:00 2001 From: Aron T Date: Sun, 2 Nov 2025 17:10:28 +0200 Subject: [PATCH 1/9] Add basics for circles chapter --- docs/make.jl | 1 + docs/src/Geometry/04 Circles.md | 3 ++ .../{04 Hyperbola.md => 05 Hyperbola.md} | 0 notebooks/Basics.ipynb | 43 ++++++++----------- 4 files changed, 23 insertions(+), 24 deletions(-) create mode 100644 docs/src/Geometry/04 Circles.md rename docs/src/Geometry/{04 Hyperbola.md => 05 Hyperbola.md} (100%) diff --git a/docs/make.jl b/docs/make.jl index 5f3b2ea..97eae71 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -21,6 +21,7 @@ makedocs(; "Geometry/01 Triangles.md", "Geometry/02 Quadrilaterals.md", "Geometry/03 Polygons.md", + "Geometry/04 Circles.md", # "Geometry/04 Hyperbola.md" # TODO: Uncomment when ready to show ], # "Linear Algebra" => [ # TODO: Uncomment when ready to show diff --git a/docs/src/Geometry/04 Circles.md b/docs/src/Geometry/04 Circles.md new file mode 100644 index 0000000..c0a58c3 --- /dev/null +++ b/docs/src/Geometry/04 Circles.md @@ -0,0 +1,3 @@ +# Circles + +## Introduction diff --git a/docs/src/Geometry/04 Hyperbola.md b/docs/src/Geometry/05 Hyperbola.md similarity index 100% rename from docs/src/Geometry/04 Hyperbola.md rename to docs/src/Geometry/05 Hyperbola.md diff --git a/notebooks/Basics.ipynb b/notebooks/Basics.ipynb index a565b3a..b6820ce 100644 --- a/notebooks/Basics.ipynb +++ b/notebooks/Basics.ipynb @@ -2463,7 +2463,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -3257,7 +3257,7 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -3298,7 +3298,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -3377,7 +3377,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -3414,7 +3414,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -3519,7 +3519,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -3568,7 +3568,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -3653,7 +3653,7 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -3675,18 +3675,6 @@ "Total area = N * triangle_area = 1.0313237694360806e6\n", "Difference (previous - current): 0.0\n", "Difference: 0.0000 (0.00000000% relative error)\n", - "Excellent agreement!\n", - "2sin(π / N))\n", - "lets calculate r with b = 1 and N = 3600\n", - "Circumradius r = b/(2*sin(π/N)) = 572.9578678528818\n", - "Now calculate the apothem (height) of one triangle\n", - "Apothem = r * cos(π/N) = [b/(2*sin(π/N))] * cos(π/N) = (1//2)*b*cot(π / N)\n", - "Apothem for b=1 and N=3600 = 572.9576496867114\n", - "Now calculate the area of one triangle\n", - "Area of one triangle = (1/2) * base * height = (1/2) * b * apothem = 286.4788248433557\n", - "Total area = N * triangle_area = 1.0313237694360806e6\n", - "Difference (previous - current): 0.0\n", - "Difference: 0.0000 (0.00000000% relative error)\n", "Excellent agreement!\n" ] } @@ -3731,7 +3719,7 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -3755,19 +3743,26 @@ "@printf(\"Difference: %.4f (%.8f%% relative error)\\n\", diff_value, rel_error * 100)\n", "println(rel_error < 1e-5 ? \"Excellent agreement!\" : \"Values differ\")" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Circles" + ] } ], "metadata": { "kernelspec": { - "display_name": "Math_Foundations 1.11.7", + "display_name": "Julia 1.12.1", "language": "julia", - "name": "math_foundations-1.11" + "name": "julia-1.12" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", - "version": "1.11.7" + "version": "1.12.1" } }, "nbformat": 4, From 4915caedb0bd7e0eaa8c001b1588fa557ee7ae20 Mon Sep 17 00:00:00 2001 From: Aron T Date: Wed, 5 Nov 2025 17:55:08 +0200 Subject: [PATCH 2/9] Add comprehensive Circle documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Basic definitions: circle, center, radius, diameter, chord, arc, circumference - Fundamental measurements: circumference (C = 2πr) and area (A = πr²) with derivations - Parts of a circle: chords, arcs (minor/major/semicircle), sectors, and segments with formulas - Circle equations: standard form, parametric form, and general form - Angles in circles: central angles, inscribed angles, and angle relationships - Common theorems: chord properties, tangent properties, and Thales' theorem - Applications: geometry, trigonometry, engineering, physics, and real-world uses - All mathematical notation uses LaTeX (degree signs as ^\circ) - Comprehensive MathWorld links for all key terms - Follows same documentation pattern as Triangles and Quadrilaterals chapters --- docs/src/Geometry/04 Circles.md | 183 +++++++++++++++++++++++++++++++- 1 file changed, 182 insertions(+), 1 deletion(-) diff --git a/docs/src/Geometry/04 Circles.md b/docs/src/Geometry/04 Circles.md index c0a58c3..3c4bf30 100644 --- a/docs/src/Geometry/04 Circles.md +++ b/docs/src/Geometry/04 Circles.md @@ -1,3 +1,184 @@ # Circles -## Introduction +[Circles](https://mathworld.wolfram.com/Circle.html) are fundamental geometric shapes defined as the set of all points in a plane that are equidistant from a fixed center point. + +## Basic Definitions + +- **[Circle](https://mathworld.wolfram.com/Circle.html):** The set of all points in a plane at a fixed distance (radius) from a center point +- **[Center](https://mathworld.wolfram.com/Center.html):** The fixed point from which all points on the circle are equidistant +- **[Radius](https://mathworld.wolfram.com/Radius.html):** The distance from the center to any point on the circle, denoted by $r$ +- **[Diameter](https://mathworld.wolfram.com/Diameter.html):** A line segment passing through the center with endpoints on the circle, denoted by $d = 2r$ +- **[Chord](https://mathworld.wolfram.com/Chord.html):** A line segment with both endpoints on the circle +- **[Arc](https://mathworld.wolfram.com/Arc.html):** A portion of the circle's circumference between two points +- **[Circumference](https://mathworld.wolfram.com/Circumference.html):** The total distance around the circle, denoted by $C$ + +## Fundamental Measurements + +### Circumference + +The circumference of a circle is the distance around it, given by: $$C = 2\pi r = \pi d$$ + +where: + +- circumference: $C$ +- radius: $r$ +- diameter: $d$ +- [pi](https://mathworld.wolfram.com/Pi.html) / $\pi$ ≈ 3.14159... + +**Key Properties:** + +- The ratio of circumference to diameter is always $\pi$, regardless of the circle's size +- This relationship is the defining property of $\pi$ +- For a circle with radius $r = 1$, the circumference is $2\pi$ + +### Area + +The area enclosed by a circle is: $$A = \pi r^2$$ + +where: + +- area: $A$ +- radius: $r$ + +**Derivation:** + +The area formula can be derived by dividing the circle into infinitely many thin triangular sectors. Each sector has: + +- Base = infinitesimal arc length +- Height = radius $r$ + +When summed, the total base length equals the circumference $2\pi r$, giving: + +$$\begin{aligned} +A &= \sum \frac{1}{2} \times \text{base} \times \text{height} \\ +&= \frac{1}{2} \times 2\pi r \times r \\ +&= \pi r^2 +\end{aligned}$$ + +**Alternative formulas:** + +- In terms of diameter: $A = \frac{\pi d^2}{4}$ +- In terms of circumference: $A = \frac{C^2}{4\pi}$ + +## Parts of a Circle + +### Chords and Arcs + +- **[Chord](https://mathworld.wolfram.com/Chord.html):** Any line segment connecting two points on the circle + - The diameter is the longest chord + - A chord divides the circle into two arcs + +- **[Arc](https://mathworld.wolfram.com/Arc.html):** A portion of the circumference + - **Minor arc:** The shorter arc between two points (less than $180^\circ$) + - **Major arc:** The longer arc between two points (greater than $180^\circ$) + - **Semicircle:** An arc that is exactly half the circle ($180^\circ$) + +- **Arc Length:** For an arc [subtending](https://mathworld.wolfram.com/Subtend.html) angle $\theta$ (in radians) at the center: + $$s = r\theta$$ + + For angle in degrees: + $$s = \frac{\pi r \theta}{180}$$ + +### Sectors and Segments + +- **[Sector](https://mathworld.wolfram.com/CircularSector.html):** The region bounded by two radii and the arc between them (like a "slice of pie") + - Area of sector with central angle $\theta$ (in radians): + $$A_{\text{sector}} = \frac{1}{2}r^2\theta$$ + + - For angle in degrees: + $$A_{\text{sector}} = \frac{\pi r^2 \theta}{360}$$ + +- **[Segment](https://mathworld.wolfram.com/CircularSegment.html):** The region bounded by a chord and the arc it subtends + - Area of segment: + $$A_{\text{segment}} = A_{\text{sector}} - A_{\text{triangle}} = \frac{1}{2}r^2(\theta - \sin\theta)$$ + + where $\theta$ is in radians + +## Circle Equations + +### Standard Form (Cartesian) + +A circle with center $(h, k)$ and radius $r$ has equation: +$$(x - h)^2 + (y - k)^2 = r^2$$ + +**Special case:** Circle centered at origin $(0, 0)$: +$$x^2 + y^2 = r^2$$ + +### Parametric Form + +A circle with center $(h, k)$ and radius $r$ can be expressed parametrically: + +$$\begin{aligned} +x &= h + r\cos\theta \\ +y &= k + r\sin\theta +\end{aligned}$$ + +where $\theta$ ranges from $0$ to $2\pi$ (or $0^\circ$ to $360^\circ$) + +### General Form + +The general quadratic equation: +$$x^2 + y^2 + Dx + Ey + F = 0$$ + +represents a circle when the coefficients of $x^2$ and $y^2$ are equal. Converting to standard form: + +- Center: $\left(-\frac{D}{2}, -\frac{E}{2}\right)$ +- Radius: $r = \sqrt{\frac{D^2 + E^2}{4} - F}$ + +## Angles in Circles + +### Central Angle + +- **[Central Angle](https://mathworld.wolfram.com/CentralAngle.html):** An angle whose vertex is at the center of the circle +- The measure of a central angle equals the measure of its intercepted arc +- A central angle of $\theta$ radians intercepts an arc of length $s = r\theta$ + +### Inscribed Angle + +- **[Inscribed Angle](https://mathworld.wolfram.com/InscribedAngle.html):** An angle formed by two chords with vertex on the circle +- **Inscribed Angle Theorem:** An inscribed angle is half the measure of its intercepted arc + $$\theta_{\text{inscribed}} = \frac{1}{2}\theta_{\text{central}}$$ + +### Angle Relationships + +- **Angles subtended by the same arc:** All inscribed angles subtending the same arc are equal +- **[Thales' Theorem](https://mathworld.wolfram.com/ThalesTheorem.html):** An angle inscribed in a semicircle is always a right angle ($90^\circ$) + +## Common Circle Theorems + +### Chord Properties + +1. **Perpendicular from center:** A perpendicular from the center to a chord bisects the chord +2. **Equal chords:** Chords equidistant from the center are equal in length +3. **Chord length formula:** For a chord at distance $d$ from center in a circle of radius $r$: + $$\text{chord length} = 2\sqrt{r^2 - d^2}$$ + +### Tangent Properties + +- **[Tangent](https://mathworld.wolfram.com/CircleTangentLine.html):** A line that touches the circle at exactly one point +- **Tangent perpendicularity:** A tangent is perpendicular to the radius at the point of tangency +- **Tangent length:** For an external point $P$ at distance $d$ from center, tangent length is: + $$\text{tangent length} = \sqrt{d^2 - r^2}$$ +- **Two tangents from external point:** Tangent segments from an external point to a circle are equal in length + +## Applications + +### Geometry and Trigonometry + +- **Unit circle:** A circle with radius 1, fundamental to trigonometry +- **Coordinate geometry:** Circles are conic sections (intersection of cone and plane) +- **Angle measurement:** Radians are defined using the unit circle + +### Real-World Applications + +- **Engineering:** Wheels, gears, pulleys +- **Architecture:** Arches, domes, circular structures +- **Physics:** Circular motion, orbits, waves +- **Navigation:** Distance calculations on Earth's surface +- **Design:** Circular patterns, logos, decorative elements + +## Further Information + +More information about circles and their properties can be found in: + +- [Trigonometry](../Trigonometry/02 Trigonometric Functions.md) for the unit circle and angle relationships From b930828368e2728657ca92748835007302816de3 Mon Sep 17 00:00:00 2001 From: Aron T Date: Tue, 18 Nov 2025 15:11:20 +0200 Subject: [PATCH 3/9] Add circumcircle definition and radian/degree conversion section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added alternative circle definition via three non-collinear points (circumcircle) - Added comprehensive Angle Measurement section explaining radians and degrees - Defined radian as natural angular unit (arc length = radius) - Added conversion formulas between radians and degrees - Added centered HTML table with common angle conversions (90°, 180°, 270°, 360°) - Reorganized Arc Length as its own subsection for better structure - All degree symbols use LaTeX notation (^\circ) --- docs/src/Geometry/04 Circles.md | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/docs/src/Geometry/04 Circles.md b/docs/src/Geometry/04 Circles.md index 3c4bf30..4e6c567 100644 --- a/docs/src/Geometry/04 Circles.md +++ b/docs/src/Geometry/04 Circles.md @@ -5,12 +5,14 @@ ## Basic Definitions - **[Circle](https://mathworld.wolfram.com/Circle.html):** The set of all points in a plane at a fixed distance (radius) from a center point + - **Alternative definition:** Three points that do not lie on a common straight line (i.e., they form a triangle) uniquely define a plane circle (the [circumcircle](https://mathworld.wolfram.com/Circumcircle.html) of the triangle) - **[Center](https://mathworld.wolfram.com/Center.html):** The fixed point from which all points on the circle are equidistant - **[Radius](https://mathworld.wolfram.com/Radius.html):** The distance from the center to any point on the circle, denoted by $r$ - **[Diameter](https://mathworld.wolfram.com/Diameter.html):** A line segment passing through the center with endpoints on the circle, denoted by $d = 2r$ - **[Chord](https://mathworld.wolfram.com/Chord.html):** A line segment with both endpoints on the circle - **[Arc](https://mathworld.wolfram.com/Arc.html):** A portion of the circle's circumference between two points - **[Circumference](https://mathworld.wolfram.com/Circumference.html):** The total distance around the circle, denoted by $C$ +- **[Degree](https://mathworld.wolfram.com/Degree.html):** $1^\circ$ is 1/360 of a complete rotation around a circle ## Fundamental Measurements @@ -73,7 +75,31 @@ A &= \sum \frac{1}{2} \times \text{base} \times \text{height} \\ - **Major arc:** The longer arc between two points (greater than $180^\circ$) - **Semicircle:** An arc that is exactly half the circle ($180^\circ$) -- **Arc Length:** For an arc [subtending](https://mathworld.wolfram.com/Subtend.html) angle $\theta$ (in radians) at the center: +### Angle Measurement: Radians and Degrees + +#### Definitions +- **[Radian](https://mathworld.wolfram.com/Radian.html):** A unit of angular measure where one radian is the angle [subtended](https://mathworld.wolfram.com/Subtend.html) at the center of a circle by an arc equal in length to the radius + - The radian is the natural unit for measuring angles in mathematics + - A full circle contains $2\pi$ radians + - One radian ≈ 57.2958° + - One degree = $\frac{1}{360}*2\pi = \frac{\pi}{180}$ radians + +- **Conversion between radians and degrees:** + - To convert from degrees to radians: $\theta_{\text{radians}} = \theta_{\text{degrees}} \times \frac{\pi}{180}$ + - To convert from radians to degrees: $\theta_{\text{degrees}} = \theta_{\text{radians}} \times \frac{180}{\pi}$ + +#### Common Angles + +| Degrees | Radians | +|:-------:|:-------:| +| $90^\circ$ | $\frac{\pi}{2}$ | +| $180^\circ$ | $\pi$ | +| $270^\circ$ | $\frac{3\pi}{2}$ | +| $360^\circ$ | $2\pi$ | + +### Arc Length + +- **Arc Length:** For an arc subtending angle $\theta$ (in radians) at the center: $$s = r\theta$$ For angle in degrees: @@ -88,7 +114,7 @@ A &= \sum \frac{1}{2} \times \text{base} \times \text{height} \\ - For angle in degrees: $$A_{\text{sector}} = \frac{\pi r^2 \theta}{360}$$ -- **[Segment](https://mathworld.wolfram.com/CircularSegment.html):** The region bounded by a chord and the arc it subtends +- **[Segment](https://mathworld.wolfram.com/CircularSegment.html):** The region bounded by a chord and the arc it subtends[subtending](https://mathworld.wolfram.com/Subtend.html) - Area of segment: $$A_{\text{segment}} = A_{\text{sector}} - A_{\text{triangle}} = \frac{1}{2}r^2(\theta - \sin\theta)$$ @@ -181,4 +207,5 @@ represents a circle when the coefficients of $x^2$ and $y^2$ are equal. Converti More information about circles and their properties can be found in: +- [Triangles](../Geometry/01 Triangles.md) for circumcircles and incircles - [Trigonometry](../Trigonometry/02 Trigonometric Functions.md) for the unit circle and angle relationships From e342c5cea37587a957e38dacc76153bf83e1247c Mon Sep 17 00:00:00 2001 From: Aron T Date: Fri, 21 Nov 2025 14:55:44 +0200 Subject: [PATCH 4/9] Add detailed circle derivation and fix Symbolics.jl numeric evaluation - Add Circles section with step-by-step derivation of circle through three points - Use standard notation: [h,k] for center, [x,y] for points - Add aligned equations for clear step-by-step algebra - Fix Symbolics.jl numeric evaluation using build_function with expression=Val{false} - Document alternative method using Symbolics.value with unwrap parameter - Preserve both methods for learning purposes --- notebooks/Basics.ipynb | 231 +++++++++++++++++++++++++++++++++-------- 1 file changed, 187 insertions(+), 44 deletions(-) diff --git a/notebooks/Basics.ipynb b/notebooks/Basics.ipynb index b6820ce..4c4796e 100644 --- a/notebooks/Basics.ipynb +++ b/notebooks/Basics.ipynb @@ -2463,7 +2463,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -3257,7 +3257,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 47, "metadata": {}, "outputs": [ { @@ -3298,7 +3298,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 1, "metadata": {}, "outputs": [ { @@ -3377,7 +3377,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -3414,7 +3414,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -3519,7 +3519,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -3527,48 +3527,72 @@ "output_type": "stream", "text": [ "Calculating area of regular polygon with N = 3600 sides and side length b\n", - "Area Formula = 0.25N*(b^2)*cot(π / N)\n", - "Using substitute, calculate symbolic area with N= 3600 sides = 1.0313237694360806e6(b^2)\n", - "Area for b=1 and N=3600 sides (full substitution): 1.0313237694360806e6\n", + "Area Formula = \u001b[34m0.25\u001b[39mN*(b^2)*cot(\u001b[34mπ\u001b[39m / N)\n", + "Using substitute, calculate symbolic area with N= 3600 sides and b = 1:\u001b[34m900.0\u001b[39mcot(\u001b[34m0.0008726646259971648\u001b[39m)\n", "\n", "--- Test for value of b - with controlled precision ---\n", "Method 1: Use Symbolics.value() to extract numerical value, then round\n", + "Numerical value before rounding: 1.0313237694360806e6\n", "Area for b=1 and N=3600 sides (4 digits after decimal): 1.0313237694e6\n", "Method 2: Format with Printf\n", "Area for b=1 and N=3600 sides (formatted): 1031323.7694\n", "Method 3: Printf with Scientific notation and controlled precision\n", - "Area for b=1 and N=3600 sides (scientific): 1.0313237694e+06\n" + "Area for b=1 and N=3600 sides (scientific): 1.0313237694e+06\n", + "\n", + "--- Build numerical function for area calculation ---\n", + "Numerical value before rounding: 1.0313237694360806e6\n", + "Area for b=1 and N=3600 sides (4 digits after decimal): 1.0313237694e6\n", + "Method 2: Format with Printf\n", + "Area for b=1 and N=3600 sides (formatted): 1031323.7694\n", + "Method 3: Printf with Scientific notation and controlled precision\n", + "Area for b=1 and N=3600 sides (scientific): 1.0313237694e+06\n", + "\n", + "--- Build numerical function for area calculation ---\n" ] } ], "source": [ - "@variables b\n", "println(\"Calculating area of regular polygon with N = 3600 sides and side length b\")\n", "@variables b, N\n", "# Area formula: A = (1/4) * N * s^2 * cot(π/N)\n", "area_formula = (1/4) * N * b^2 * cot(π/N)\n", "println(\"Area Formula = \", area_formula)\n", "# Simplify the expression\n", - "area_symbolic = substitute(area_formula, N=>3600)\n", - "println(\"Using substitute, calculate symbolic area with N= 3600 sides = \", area_symbolic)\n", - "area_test = substitute(area_symbolic, b=>1)\n", - "println(\"Area for b=1 and N=3600 sides (full substitution): \", area_test)\n", + "area_symbolic = substitute(area_formula, Dict(N=>3600, b=>1))\n", + "println(\"Using substitute, calculate symbolic area with N= 3600 sides and b = 1:\", area_symbolic)\n", "using Printf\n", "println(\"\")\n", "println(\"--- Test for value of b - with controlled precision ---\")\n", "println(\"Method 1: Use Symbolics.value() to extract numerical value, then round\")\n", - "area_numerical_value = Symbolics.value(area_test)\n", + "# Substitute all variables and simplify to force evaluation of cot(π/N)\n", + "# old way\n", + "area_test_simplified = substitute(area_formula, Dict(N=>3600, b=>1); fold=Val(true))\n", + "area_numerical_value = Symbolics.value(area_test_simplified)\n", + "println(\"Numerical value before rounding: \", area_numerical_value)\n", + "area_rounded = round(area_numerical_value, digits=4)\n", + "println(\"Area for b=1 and N=3600 sides (4 digits after decimal): \", area_rounded)\n", + "println(\"Method 2: Format with Printf\")\n", + "@printf(\"Area for b=1 and N=3600 sides (formatted): %.4f\\n\", area_numerical_value)\n", + "println(\"Method 3: Printf with Scientific notation and controlled precision\")\n", + "@printf(\"Area for b=1 and N=3600 sides (scientific): %.10e\\n\", area_numerical_value)\n", + "println(\"\")\n", + "println(\"--- Build numerical function for area calculation ---\")\n", + "area_numerical_function = build_function(area_formula,b,N, expression=Val{false})\n", + "area_numerical_value = area_numerical_function(1,3600)\n", + "println(\"Numerical value before rounding: \", area_numerical_value)\n", "area_rounded = round(area_numerical_value, digits=4)\n", "println(\"Area for b=1 and N=3600 sides (4 digits after decimal): \", area_rounded)\n", "println(\"Method 2: Format with Printf\")\n", "@printf(\"Area for b=1 and N=3600 sides (formatted): %.4f\\n\", area_numerical_value)\n", "println(\"Method 3: Printf with Scientific notation and controlled precision\")\n", - "@printf(\"Area for b=1 and N=3600 sides (scientific): %.10e\\n\", area_numerical_value)\n" + "@printf(\"Area for b=1 and N=3600 sides (scientific): %.10e\\n\", area_numerical_value)\n", + "println(\"\")\n", + "\n" ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 25, "metadata": {}, "outputs": [ { @@ -3606,7 +3630,6 @@ "area_approx = (N_large^2 * b_value^2) / (4 * π)\n", "println(\"Numerical approximation of area for b=1 and N=3600 sides: \", area_approx)\n", "println(\"This approximation should be close to the exact symbolic calculation.\")\n", - "\n", "# Quantitative comparison with absolute and relative error\n", "diff_value = abs(area_numerical_value - area_approx)\n", "rel_error = diff_value / area_approx\n", @@ -3653,7 +3676,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 26, "metadata": {}, "outputs": [ { @@ -3664,18 +3687,31 @@ "Find the area using trianglulation method:\n", "A regular polygon with N sides can be divided into N isosceles triangles\n", "First find the radius r from the side length b\n", - "In a regular N-gon: b = 2*r*sin(π/N), so r = b / (2sin(π / N))\n", + "In a regular N-gon: b = 2*r*sin(π/N), so r = b / (\u001b[34m2\u001b[39msin(\u001b[34mπ\u001b[39m / N))\n", "lets calculate r with b = 1 and N = 3600\n", - "Circumradius r = b/(2*sin(π/N)) = 572.9578678528818\n", + "Circumradius r = b/(2*sin(π/N)) = \u001b[34m1\u001b[39m / (\u001b[34m2\u001b[39msin(\u001b[34m0.0008726646259971648\u001b[39m))\n", "Now calculate the apothem (height) of one triangle\n", - "Apothem = r * cos(π/N) = [b/(2*sin(π/N))] * cos(π/N) = (1//2)*b*cot(π / N)\n", - "Apothem for b=1 and N=3600 = 572.9576496867114\n", + "Apothem = r * cos(π/N) = [b/(2*sin(π/N))] * cos(π/N) = \u001b[34m1//2\u001b[39m*b*cot(\u001b[34mπ\u001b[39m / N)\n", + "Apothem for b=1 and N=3600 = \u001b[34m1//2\u001b[39m*cot(\u001b[34m0.0008726646259971648\u001b[39m)\n", "Now calculate the area of one triangle\n", - "Area of one triangle = (1/2) * base * height = (1/2) * b * apothem = 286.4788248433557\n", - "Total area = N * triangle_area = 1.0313237694360806e6\n", - "Difference (previous - current): 0.0\n", - "Difference: 0.0000 (0.00000000% relative error)\n", - "Excellent agreement!\n" + "Area of one triangle = (1/2) * base * height = (1/2) * b * apothem = \u001b[34m0.25\u001b[39mcot(\u001b[34m0.0008726646259971648\u001b[39m)\n", + "Total area = N * triangle_area = \u001b[34m900.0\u001b[39mcot(\u001b[34m0.0008726646259971648\u001b[39m)\n" + ] + }, + { + "ename": "LoadError", + "evalue": "MethodError: no method matching round(::SymbolicUtils.BasicSymbolicImpl.var\"typeof(BasicSymbolicImpl)\"{SymReal}, ::RoundingMode{:Nearest}; digits::Int64)\nThe function `round` exists, but no method is defined for this combination of argument types.\n\n\u001b[0mClosest candidates are:\n\u001b[0m round(\u001b[91m::QQBarFieldElem\u001b[39m, ::RoundingMode{:Nearest})\u001b[91m got unsupported keyword argument \"digits\"\u001b[39m\n\u001b[0m\u001b[90m @\u001b[39m \u001b[36mNemo\u001b[39m \u001b[90m~/.julia/packages/Nemo/kdloy/src/calcium/\u001b[39m\u001b[90m\u001b[4mqqbar.jl:733\u001b[24m\u001b[39m\n\u001b[0m round(\u001b[91m::BigFloat\u001b[39m, ::RoundingMode{:Nearest})\u001b[91m got unsupported keyword argument \"digits\"\u001b[39m\n\u001b[0m\u001b[90m @\u001b[39m \u001b[90mBase\u001b[39m \u001b[90m\u001b[4mmpfr.jl:1123\u001b[24m\u001b[39m\n\u001b[0m round(\u001b[91m::Missing\u001b[39m, ::RoundingMode; sigdigits, digits, base)\n\u001b[0m\u001b[90m @\u001b[39m \u001b[90mBase\u001b[39m \u001b[90m\u001b[4mmissing.jl:144\u001b[24m\u001b[39m\n\u001b[0m ...\n", + "output_type": "error", + "traceback": [ + "MethodError: no method matching round(::SymbolicUtils.BasicSymbolicImpl.var\"typeof(BasicSymbolicImpl)\"{SymReal}, ::RoundingMode{:Nearest}; digits::Int64)\nThe function `round` exists, but no method is defined for this combination of argument types.\n\n\u001b[0mClosest candidates are:\n\u001b[0m round(\u001b[91m::QQBarFieldElem\u001b[39m, ::RoundingMode{:Nearest})\u001b[91m got unsupported keyword argument \"digits\"\u001b[39m\n\u001b[0m\u001b[90m @\u001b[39m \u001b[36mNemo\u001b[39m \u001b[90m~/.julia/packages/Nemo/kdloy/src/calcium/\u001b[39m\u001b[90m\u001b[4mqqbar.jl:733\u001b[24m\u001b[39m\n\u001b[0m round(\u001b[91m::BigFloat\u001b[39m, ::RoundingMode{:Nearest})\u001b[91m got unsupported keyword argument \"digits\"\u001b[39m\n\u001b[0m\u001b[90m @\u001b[39m \u001b[90mBase\u001b[39m \u001b[90m\u001b[4mmpfr.jl:1123\u001b[24m\u001b[39m\n\u001b[0m round(\u001b[91m::Missing\u001b[39m, ::RoundingMode; sigdigits, digits, base)\n\u001b[0m\u001b[90m @\u001b[39m \u001b[90mBase\u001b[39m \u001b[90m\u001b[4mmissing.jl:144\u001b[24m\u001b[39m\n\u001b[0m ...\n", + "", + "Stacktrace:", + " [1] \u001b[0m\u001b[1mround\u001b[22m\u001b[0m\u001b[1m(\u001b[22m\u001b[90mx\u001b[39m::\u001b[0mSymbolicUtils.BasicSymbolicImpl.var\"typeof(BasicSymbolicImpl)\"\u001b[90m{SymReal}\u001b[39m; \u001b[90mkws\u001b[39m::\u001b[0m@Kwargs\u001b[90m{digits::Int64}\u001b[39m\u001b[0m\u001b[1m)\u001b[22m", + "\u001b[90m @\u001b[39m \u001b[90mBase\u001b[39m \u001b[90m./\u001b[39m\u001b[90m\u001b[4mrounding.jl:472\u001b[24m\u001b[39m", + " [2] top-level scope", + "\u001b[90m @\u001b[39m \u001b[90m\u001b[4mIn[26]:24\u001b[24m\u001b[39m", + " [3] \u001b[0m\u001b[1meval\u001b[22m\u001b[0m\u001b[1m(\u001b[22m\u001b[90mm\u001b[39m::\u001b[0mModule, \u001b[90me\u001b[39m::\u001b[0mAny\u001b[0m\u001b[1m)\u001b[22m", + "\u001b[90m @\u001b[39m \u001b[90mCore\u001b[39m \u001b[90m./\u001b[39m\u001b[90m\u001b[4mboot.jl:489\u001b[24m\u001b[39m" ] } ], @@ -3719,20 +3755,9 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Area using another formula F = 1/2 * N * r^2 * sin(2π/N) = 1.0313237694360806e6\n", - "Difference (previous - current): 0.0\n", - "Difference: 0.0000 (0.00000000% relative error)\n", - "Excellent agreement!\n" - ] - } - ], + "outputs": [], "source": [ "F = 1/2 * 3600 * r^2 * sind(360/3600)\n", "println(\"Area using another formula F = 1/2 * N * r^2 * sin(2π/N) = \", F)\n", @@ -3748,13 +3773,131 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Circles" + "## Circles\n", + "\n", + "### Finding a Circle Through Three Points\n", + "\n", + "I determine the circle through the points $[0, 0]$, $[1, 0]$, and $[1, 1]$.\n", + "\n", + "**General Form of a Circle:**\n", + "The general equation of a circle with center $[h, k]$ and radius $r$ is:\n", + "$$(x - h)^2 + (y - k)^2 = r^2$$\n", + "\n", + "**Step 1: Substitute the three points into the general equation**\n", + "\n", + "For point $[0, 0]$:\n", + "$$\n", + "\\begin{align}\n", + "(0 - h)^2 + (0 - k)^2 &= r^2 \\\\\n", + "h^2 + k^2 &= r^2 \\quad \\text{...(Equation 1)}\n", + "\\end{align}\n", + "$$\n", + "\n", + "For point $[1, 0]$:\n", + "$$\n", + "\\begin{align}\n", + "(1 - h)^2 + (0 - k)^2 &= r^2 \\\\\n", + "(1 - h)^2 + k^2 &= r^2 \\quad \\text{...(Equation 2)}\n", + "\\end{align}\n", + "$$\n", + "\n", + "For point $[1, 1]$:\n", + "$$(1 - h)^2 + (1 - k)^2 = r^2 \\quad \\text{...(Equation 3)}$$\n", + "\n", + "**Step 2: Subtract Equation 1 from Equation 2 to find $h$**\n", + "$$\n", + "\\begin{align}\n", + "(1 - h)^2 + k^2 - (h^2 + k^2) &= 0 \\\\\n", + "(1 - h)^2 - h^2 &= 0\n", + "\\end{align}\n", + "$$\n", + "\n", + "Applying the binomial formula $(1 - h)^2 = 1 - 2h + h^2$:\n", + "$$\n", + "\\begin{align}\n", + "1 - 2h + h^2 - h^2 &= 0 \\\\\n", + "1 - 2h &= 0 \\\\\n", + "h &= \\frac{1}{2}\n", + "\\end{align}\n", + "$$\n", + "\n", + "**Step 3: Subtract Equation 2 from Equation 3 to find $k$**\n", + "$$\n", + "\\begin{align}\n", + "(1 - h)^2 + (1 - k)^2 - [(1 - h)^2 + k^2] &= 0 \\\\\n", + "(1 - k)^2 - k^2 &= 0\n", + "\\end{align}\n", + "$$\n", + "\n", + "Applying the binomial formula $(1 - k)^2 = 1 - 2k + k^2$:\n", + "$$\n", + "\\begin{align}\n", + "1 - 2k + k^2 - k^2 &= 0 \\\\\n", + "1 - 2k &= 0 \\\\\n", + "k &= \\frac{1}{2}\n", + "\\end{align}\n", + "$$\n", + "\n", + "**Step 4: Find the radius $r$**\n", + "\n", + "The center point is $M = \\left[\\frac{1}{2}, \\frac{1}{2}\\right]$. \n", + "\n", + "Substituting $h = k = \\frac{1}{2}$ into Equation 1:\n", + "$$\n", + "\\begin{align}\n", + "\\left(\\frac{1}{2}\\right)^2 + \\left(\\frac{1}{2}\\right)^2 &= r^2 \\\\\n", + "\\frac{1}{4} + \\frac{1}{4} &= r^2 \\\\\n", + "\\frac{1}{2} &= r^2 \\\\\n", + "r &= \\frac{1}{\\sqrt{2}} = \\frac{\\sqrt{2}}{2}\n", + "\\end{align}\n", + "$$\n", + "\n", + "**Final Circle Equation:**\n", + "$$\\left(x - \\frac{1}{2}\\right)^2 + \\left(y - \\frac{1}{2}\\right)^2 = \\frac{1}{2}$$\n", + "\n", + "**Alternative Method:** I could also calculate the center point as the intersection of two perpendicular bisectors and then find the radius as shown above." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "ename": "LoadError", + "evalue": "MethodError: objects of type Expr are not callable\nThe object of type `Expr` exists, but no method is defined for this combination of argument types when trying to treat it as a callable object.", + "output_type": "error", + "traceback": [ + "MethodError: objects of type Expr are not callable\nThe object of type `Expr` exists, but no method is defined for this combination of argument types when trying to treat it as a callable object.", + "", + "Stacktrace:", + " [1] top-level scope", + "\u001b[90m @\u001b[39m \u001b[90m\u001b[4mIn[23]:12\u001b[24m\u001b[39m", + " [2] \u001b[0m\u001b[1meval\u001b[22m\u001b[0m\u001b[1m(\u001b[22m\u001b[90mm\u001b[39m::\u001b[0mModule, \u001b[90me\u001b[39m::\u001b[0mAny\u001b[0m\u001b[1m)\u001b[22m", + "\u001b[90m @\u001b[39m \u001b[90mCore\u001b[39m \u001b[90m./\u001b[39m\u001b[90m\u001b[4mboot.jl:489\u001b[24m\u001b[39m" + ] + } + ], + "source": [ + "using Symbolics\n", + "\n", + "@variables x\n", + "expr = sin(x) + cos(x)\n", + "\n", + "# Build a function from the symbolic expression\n", + "# The first argument is the expression, the second is the variable(s) it depends on\n", + "f = build_function(expr, x)\n", + "\n", + "# 'f' is now a regular Julia function that can be evaluated numerically\n", + "# For example, evaluate at x = pi/4\n", + "val = f(π/4)\n", + "println(val)" ] } ], "metadata": { "kernelspec": { - "display_name": "Julia 1.12.1", + "display_name": "Julia 1.12", "language": "julia", "name": "julia-1.12" }, From d46565e2af627626fe2c8b260135470422d8a54a Mon Sep 17 00:00:00 2001 From: Aron T Date: Sat, 22 Nov 2025 20:50:38 +0200 Subject: [PATCH 5/9] Add fold parameter to Symbolics substitute calls in notebook - Update all substitute() calls to include fold=true parameter - Ensures proper evaluation of numeric expressions - Completes the Symbolics.jl numeric evaluation fixes --- notebooks/Basics.ipynb | 169 ++++++++++++++++++++--------------------- 1 file changed, 82 insertions(+), 87 deletions(-) diff --git a/notebooks/Basics.ipynb b/notebooks/Basics.ipynb index 4c4796e..b418b98 100644 --- a/notebooks/Basics.ipynb +++ b/notebooks/Basics.ipynb @@ -644,7 +644,7 @@ }, { "cell_type": "code", - "execution_count": 60, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -652,7 +652,7 @@ "output_type": "stream", "text": [ "0.25\n", - "1.0\n" + "1\n" ] }, { @@ -662,59 +662,59 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", + "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", + "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" ], "text/html": [ "" ] }, - "execution_count": 60, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -730,14 +730,14 @@ }, { "cell_type": "code", - "execution_count": 61, + "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "2(x^2)\n" + "\u001b[34m2\u001b[39m(x^2)\n" ] } ], @@ -3519,7 +3519,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -3528,7 +3528,7 @@ "text": [ "Calculating area of regular polygon with N = 3600 sides and side length b\n", "Area Formula = \u001b[34m0.25\u001b[39mN*(b^2)*cot(\u001b[34mπ\u001b[39m / N)\n", - "Using substitute, calculate symbolic area with N= 3600 sides and b = 1:\u001b[34m900.0\u001b[39mcot(\u001b[34m0.0008726646259971648\u001b[39m)\n", + "Using substitute, calculate symbolic area with N= 3600 sides and b = 1: 1.0313237694360806e6\n", "\n", "--- Test for value of b - with controlled precision ---\n", "Method 1: Use Symbolics.value() to extract numerical value, then round\n", @@ -3546,8 +3546,7 @@ "Area for b=1 and N=3600 sides (formatted): 1031323.7694\n", "Method 3: Printf with Scientific notation and controlled precision\n", "Area for b=1 and N=3600 sides (scientific): 1.0313237694e+06\n", - "\n", - "--- Build numerical function for area calculation ---\n" + "\n" ] } ], @@ -3558,8 +3557,8 @@ "area_formula = (1/4) * N * b^2 * cot(π/N)\n", "println(\"Area Formula = \", area_formula)\n", "# Simplify the expression\n", - "area_symbolic = substitute(area_formula, Dict(N=>3600, b=>1))\n", - "println(\"Using substitute, calculate symbolic area with N= 3600 sides and b = 1:\", area_symbolic)\n", + "area_symbolic = substitute(area_formula, Dict(N=>3600, b=>1); fold=Val(true))\n", + "println(\"Using substitute, calculate symbolic area with N= 3600 sides and b = 1: \", area_symbolic)\n", "using Printf\n", "println(\"\")\n", "println(\"--- Test for value of b - with controlled precision ---\")\n", @@ -3592,7 +3591,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -3645,7 +3644,7 @@ "# Calculate circle coefficient symbolically\n", "@variables N_sym\n", "circle_coefficient_symbolic = N_sym^2 / (4*π)\n", - "circle_coefficient_3600 = substitute(circle_coefficient_symbolic, N_sym=>3600)\n", + "circle_coefficient_3600 = substitute(circle_coefficient_symbolic, N_sym=>3600 ; fold=Val(true))\n", "circle_area_3600 = Symbolics.value(circle_coefficient_3600) * b_value^2\n", "\n", "println(\"Circle coefficient for N=3600: N²/(4π) = \", round(Symbolics.value(circle_coefficient_3600), digits=4))\n", @@ -3676,7 +3675,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -3689,29 +3688,16 @@ "First find the radius r from the side length b\n", "In a regular N-gon: b = 2*r*sin(π/N), so r = b / (\u001b[34m2\u001b[39msin(\u001b[34mπ\u001b[39m / N))\n", "lets calculate r with b = 1 and N = 3600\n", - "Circumradius r = b/(2*sin(π/N)) = \u001b[34m1\u001b[39m / (\u001b[34m2\u001b[39msin(\u001b[34m0.0008726646259971648\u001b[39m))\n", + "Circumradius r = b/(2*sin(π/N)) = 572.9578678528818\n", "Now calculate the apothem (height) of one triangle\n", "Apothem = r * cos(π/N) = [b/(2*sin(π/N))] * cos(π/N) = \u001b[34m1//2\u001b[39m*b*cot(\u001b[34mπ\u001b[39m / N)\n", - "Apothem for b=1 and N=3600 = \u001b[34m1//2\u001b[39m*cot(\u001b[34m0.0008726646259971648\u001b[39m)\n", + "Apothem for b=1 and N=3600 = 572.9576496867114\n", "Now calculate the area of one triangle\n", - "Area of one triangle = (1/2) * base * height = (1/2) * b * apothem = \u001b[34m0.25\u001b[39mcot(\u001b[34m0.0008726646259971648\u001b[39m)\n", - "Total area = N * triangle_area = \u001b[34m900.0\u001b[39mcot(\u001b[34m0.0008726646259971648\u001b[39m)\n" - ] - }, - { - "ename": "LoadError", - "evalue": "MethodError: no method matching round(::SymbolicUtils.BasicSymbolicImpl.var\"typeof(BasicSymbolicImpl)\"{SymReal}, ::RoundingMode{:Nearest}; digits::Int64)\nThe function `round` exists, but no method is defined for this combination of argument types.\n\n\u001b[0mClosest candidates are:\n\u001b[0m round(\u001b[91m::QQBarFieldElem\u001b[39m, ::RoundingMode{:Nearest})\u001b[91m got unsupported keyword argument \"digits\"\u001b[39m\n\u001b[0m\u001b[90m @\u001b[39m \u001b[36mNemo\u001b[39m \u001b[90m~/.julia/packages/Nemo/kdloy/src/calcium/\u001b[39m\u001b[90m\u001b[4mqqbar.jl:733\u001b[24m\u001b[39m\n\u001b[0m round(\u001b[91m::BigFloat\u001b[39m, ::RoundingMode{:Nearest})\u001b[91m got unsupported keyword argument \"digits\"\u001b[39m\n\u001b[0m\u001b[90m @\u001b[39m \u001b[90mBase\u001b[39m \u001b[90m\u001b[4mmpfr.jl:1123\u001b[24m\u001b[39m\n\u001b[0m round(\u001b[91m::Missing\u001b[39m, ::RoundingMode; sigdigits, digits, base)\n\u001b[0m\u001b[90m @\u001b[39m \u001b[90mBase\u001b[39m \u001b[90m\u001b[4mmissing.jl:144\u001b[24m\u001b[39m\n\u001b[0m ...\n", - "output_type": "error", - "traceback": [ - "MethodError: no method matching round(::SymbolicUtils.BasicSymbolicImpl.var\"typeof(BasicSymbolicImpl)\"{SymReal}, ::RoundingMode{:Nearest}; digits::Int64)\nThe function `round` exists, but no method is defined for this combination of argument types.\n\n\u001b[0mClosest candidates are:\n\u001b[0m round(\u001b[91m::QQBarFieldElem\u001b[39m, ::RoundingMode{:Nearest})\u001b[91m got unsupported keyword argument \"digits\"\u001b[39m\n\u001b[0m\u001b[90m @\u001b[39m \u001b[36mNemo\u001b[39m \u001b[90m~/.julia/packages/Nemo/kdloy/src/calcium/\u001b[39m\u001b[90m\u001b[4mqqbar.jl:733\u001b[24m\u001b[39m\n\u001b[0m round(\u001b[91m::BigFloat\u001b[39m, ::RoundingMode{:Nearest})\u001b[91m got unsupported keyword argument \"digits\"\u001b[39m\n\u001b[0m\u001b[90m @\u001b[39m \u001b[90mBase\u001b[39m \u001b[90m\u001b[4mmpfr.jl:1123\u001b[24m\u001b[39m\n\u001b[0m round(\u001b[91m::Missing\u001b[39m, ::RoundingMode; sigdigits, digits, base)\n\u001b[0m\u001b[90m @\u001b[39m \u001b[90mBase\u001b[39m \u001b[90m\u001b[4mmissing.jl:144\u001b[24m\u001b[39m\n\u001b[0m ...\n", - "", - "Stacktrace:", - " [1] \u001b[0m\u001b[1mround\u001b[22m\u001b[0m\u001b[1m(\u001b[22m\u001b[90mx\u001b[39m::\u001b[0mSymbolicUtils.BasicSymbolicImpl.var\"typeof(BasicSymbolicImpl)\"\u001b[90m{SymReal}\u001b[39m; \u001b[90mkws\u001b[39m::\u001b[0m@Kwargs\u001b[90m{digits::Int64}\u001b[39m\u001b[0m\u001b[1m)\u001b[22m", - "\u001b[90m @\u001b[39m \u001b[90mBase\u001b[39m \u001b[90m./\u001b[39m\u001b[90m\u001b[4mrounding.jl:472\u001b[24m\u001b[39m", - " [2] top-level scope", - "\u001b[90m @\u001b[39m \u001b[90m\u001b[4mIn[26]:24\u001b[24m\u001b[39m", - " [3] \u001b[0m\u001b[1meval\u001b[22m\u001b[0m\u001b[1m(\u001b[22m\u001b[90mm\u001b[39m::\u001b[0mModule, \u001b[90me\u001b[39m::\u001b[0mAny\u001b[0m\u001b[1m)\u001b[22m", - "\u001b[90m @\u001b[39m \u001b[90mCore\u001b[39m \u001b[90m./\u001b[39m\u001b[90m\u001b[4mboot.jl:489\u001b[24m\u001b[39m" + "Area of one triangle = (1/2) * base * height = (1/2) * b * apothem = 286.4788248433557\n", + "Total area = N * triangle_area = 1.0313237694360806e6\n", + "Difference (previous - current): 0.0\n", + "Difference: 0.0000 (0.00000000% relative error)\n", + "Excellent agreement!\n" ] } ], @@ -3723,13 +3709,13 @@ "r_symbolic = b / (2 * sin(π/N))\n", "println(\"In a regular N-gon: b = 2*r*sin(π/N), so r = \", r_symbolic)\n", "println(\"lets calculate r with b = 1 and N = 3600\")\n", - "r_substitute = substitute(r_symbolic, Dict(b=>1, N=>3600))\n", + "r_substitute = substitute(r_symbolic, Dict(b=>1, N=>3600); fold=Val(true))\n", "r = Symbolics.value(r_substitute)\n", "println(\"Circumradius r = b/(2*sin(π/N)) = \", r)\n", "println(\"Now calculate the apothem (height) of one triangle\")\n", "apothem_symbolic = (b/2) * cot(π/N)\n", "println(\"Apothem = r * cos(π/N) = [b/(2*sin(π/N))] * cos(π/N) = \", apothem_symbolic)\n", - "apothem_substitute = substitute(apothem_symbolic, Dict(b=>1, N=>3600))\n", + "apothem_substitute = substitute(apothem_symbolic, Dict(b=>1, N=>3600); fold=Val(true))\n", "apothem = Symbolics.value(apothem_substitute)\n", "println(\"Apothem for b=1 and N=3600 = \", apothem)\n", "println(\"Now calculate the area of one triangle\")\n", @@ -3860,38 +3846,47 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 26, "metadata": {}, "outputs": [ { - "ename": "LoadError", - "evalue": "MethodError: objects of type Expr are not callable\nThe object of type `Expr` exists, but no method is defined for this combination of argument types when trying to treat it as a callable object.", - "output_type": "error", - "traceback": [ - "MethodError: objects of type Expr are not callable\nThe object of type `Expr` exists, but no method is defined for this combination of argument types when trying to treat it as a callable object.", - "", - "Stacktrace:", - " [1] top-level scope", - "\u001b[90m @\u001b[39m \u001b[90m\u001b[4mIn[23]:12\u001b[24m\u001b[39m", - " [2] \u001b[0m\u001b[1meval\u001b[22m\u001b[0m\u001b[1m(\u001b[22m\u001b[90mm\u001b[39m::\u001b[0mModule, \u001b[90me\u001b[39m::\u001b[0mAny\u001b[0m\u001b[1m)\u001b[22m", - "\u001b[90m @\u001b[39m \u001b[90mCore\u001b[39m \u001b[90m./\u001b[39m\u001b[90m\u001b[4mboot.jl:489\u001b[24m\u001b[39m" + "name": "stdout", + "output_type": "stream", + "text": [ + "Two methods to get numerical functions' values from symbolic expressions\n", + "Symbolic expression: sin(x) + cos(x)\n", + "\n", + "Method 1: Using 'substitute' and 'Symbolics.value'. Be sure to use 'fold=Val(true)' to simplify the expression after substitution. \n", + "Numerical value at x = π/4 using substitute and value: 1.414213562373095\n", + "\n", + "Method 2: Using 'build_function' to create a numerical function directly from the symbolic expression. \n", + "Be sure to set 'expression=Val{false}' to get a standard Julia function that doesn't require eval. \n", + "Numerical value at x = π/4 using build_function: 1.414213562373095\n" ] } ], "source": [ + "println(\"Two methods to get numerical functions' values from symbolic expressions\")\n", "using Symbolics\n", "\n", "@variables x\n", "expr = sin(x) + cos(x)\n", - "\n", + "println(\"Symbolic expression: \", expr, \"\\n\")\n", + "println(\"Method 1: Using 'substitute' and 'Symbolics.value'. Be sure to use 'fold=Val(true)' to simplify the expression after substitution. \")\n", + "# Substitute a numerical value into the expression\n", + "expr_substituted = substitute(expr, x => π/4; fold=Val(true))\n", + "# Extract the numerical value\n", + "numerical_value = Symbolics.value(expr_substituted) \n", + "println(\"Numerical value at x = π/4 using substitute and value: \", numerical_value, \"\\n\")\n", + "println(\"Method 2: Using 'build_function' to create a numerical function directly from the symbolic expression. \\nBe sure to set 'expression=Val{false}' to get a standard Julia function that doesn't require eval. \")\n", "# Build a function from the symbolic expression\n", "# The first argument is the expression, the second is the variable(s) it depends on\n", - "f = build_function(expr, x)\n", + "f = build_function(expr, x, expression=Val{false})\n", "\n", "# 'f' is now a regular Julia function that can be evaluated numerically\n", "# For example, evaluate at x = pi/4\n", "val = f(π/4)\n", - "println(val)" + "println(\"Numerical value at x = π/4 using build_function: \", val)\n" ] } ], From b07e0c5e3050d63907103a40cd26c61a093ee7b5 Mon Sep 17 00:00:00 2001 From: Aron T Date: Sat, 22 Nov 2025 21:12:16 +0200 Subject: [PATCH 6/9] =?UTF-8?q?Fix=20=CF=80=20display=20to=20show=20numeri?= =?UTF-8?q?c=20value=20using=20Float64()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Convert π from Irrational type to Float64 for numeric display - Ensures the value prints as decimal approximation rather than symbol --- notebooks/Basics.ipynb | 99 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 91 insertions(+), 8 deletions(-) diff --git a/notebooks/Basics.ipynb b/notebooks/Basics.ipynb index b418b98..f47806f 100644 --- a/notebooks/Basics.ipynb +++ b/notebooks/Basics.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 28, "metadata": {}, "outputs": [], "source": [ @@ -3759,10 +3759,20 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Circles\n", - "\n", - "### Finding a Circle Through Three Points\n", - "\n", + "## Circles" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Finding a Circle Through Three Points" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ "I determine the circle through the points $[0, 0]$, $[1, 0]$, and $[1, 1]$.\n", "\n", "**General Form of a Circle:**\n", @@ -3844,9 +3854,16 @@ "**Alternative Method:** I could also calculate the center point as the intersection of two perpendicular bisectors and then find the radius as shown above." ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Interlude: Numerical Evaluation of Symbolic Expressions" + ] + }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 29, "metadata": {}, "outputs": [ { @@ -3861,7 +3878,8 @@ "\n", "Method 2: Using 'build_function' to create a numerical function directly from the symbolic expression. \n", "Be sure to set 'expression=Val{false}' to get a standard Julia function that doesn't require eval. \n", - "Numerical value at x = π/4 using build_function: 1.414213562373095\n" + "Numerical value at x = π/4 using build_function: 1.414213562373095\n", + "Both methods give the same result: true\n" ] } ], @@ -3886,7 +3904,72 @@ "# 'f' is now a regular Julia function that can be evaluated numerically\n", "# For example, evaluate at x = pi/4\n", "val = f(π/4)\n", - "println(\"Numerical value at x = π/4 using build_function: \", val)\n" + "println(\"Numerical value at x = π/4 using build_function: \", val)\n", + "println(\"Both methods give the same result: \", isapprox(numerical_value, val))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Using the area of n-gons to approximate the area of a circle" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "--- Area of regular n-gon as N → ∞ ---\n", + "We will derive the area expression symbolically and then evaluate it numerically for increasing N \n", + "to show it approaches π for r = 1.\n", + "\n", + "Symbolic area expression for regular n-gon: N*(r^2)*(sin(\u001b[34mπ\u001b[39m / N)^2)*cot(\u001b[34mπ\u001b[39m / N)\n", + "Numerical area for r = 1 and N = 3 is: 1.2990381056766582\n", + "Numerical area for r = 1 and N = 6 is: 2.5980762113533156\n", + "Numerical area for r = 1 and N = 12 is: 2.9999999999999996\n", + "Numerical area for r = 1 and N = 24 is: 3.1058285412302484\n", + "Numerical area for r = 1 and N = 48 is: 3.132628613281238\n", + "Numerical area for r = 1 and N = 96 is: 3.1393502030468663\n", + "Numerical area for r = 1 and N = 192 is: 3.14103195089051\n", + "Numerical area for r = 1 and N = 384 is: 3.1414524722854615\n", + "Numerical area for r = 1 and N = 768 is: 3.141557607911857\n", + "Numerical area for r = 1 and N = 1536 is: 3.141583892148318\n", + "Numerical area for r = 1 and N = 3072 is: 3.1415904632280505\n", + "Numerical area for r = 1 and N = 3600 is: 3.1415910586169558\n", + "Numerical area for r = 1 and N = 6400 is: 3.141592148930367\n", + "This should be close to π: 3.141592653589793\n", + "Difference from π: 5.046594262481108e-7\n" + ] + } + ], + "source": [ + "# Create a symbolic expression for the area of a regular n-gon using radius r\n", + "println(\"\\n--- Area of regular n-gon as N → ∞ ---\")\n", + "println(\"We will derive the area expression symbolically and then evaluate it numerically for increasing N \\nto show it approaches π for r = 1.\\n\")\n", + "@variables r N\n", + "area_expr = (1/4) * N * (2 * r * sin(π/N))^2 * cot(π/N)\n", + "println(\"Symbolic area expression for regular n-gon: \", area_expr)\n", + "# Build a numerical function from the symbolic area expression\n", + "area_function = build_function(area_expr, r, N, expression=Val{false})\n", + "# Evaluate the area function with r always being 1 and iterating over various values of N\n", + "# the point is we want to show that the larger N the closer it is to pi\n", + "r_value = 1\n", + "for N_value in [3, 6, 12, 24, 48, 96, 192, 384, 768, 1536, 3072,3600]\n", + " area_value = area_function(r_value, N_value)\n", + " println(\"Numerical area for r = \", r_value, \" and N = \", N_value, \" is: \", area_value)\n", + "end \n", + "# Final test with N = 3600\n", + "N_value = 6400\n", + "area_value = area_function(r_value, N_value)\n", + "println(\"Numerical area for r = \", r_value, \" and N = \", N_value, \" is: \", area_value)\n", + "println(\"This should be close to π: \", Float64(π))\n", + "println(\"Difference from π: \", abs(area_value - Float64(π)))" ] } ], From 4ffc066ebf0c488b822423fa5bb1f85f9e72d2f7 Mon Sep 17 00:00:00 2001 From: Aron T Date: Sat, 22 Nov 2025 21:26:06 +0200 Subject: [PATCH 7/9] Add r>1 calculation to polygon area notebook - Include radius calculation for r>1 case - Complete the polygon area calculation examples --- notebooks/Basics.ipynb | 48 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/notebooks/Basics.ipynb b/notebooks/Basics.ipynb index f47806f..1358d16 100644 --- a/notebooks/Basics.ipynb +++ b/notebooks/Basics.ipynb @@ -3917,7 +3917,7 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 44, "metadata": {}, "outputs": [ { @@ -3925,10 +3925,7 @@ "output_type": "stream", "text": [ "\n", - "--- Area of regular n-gon as N → ∞ ---\n", - "We will derive the area expression symbolically and then evaluate it numerically for increasing N \n", - "to show it approaches π for r = 1.\n", - "\n", + "--- Area of regular n-gon as N → ∞ approaches π for r = 1---\n", "Symbolic area expression for regular n-gon: N*(r^2)*(sin(\u001b[34mπ\u001b[39m / N)^2)*cot(\u001b[34mπ\u001b[39m / N)\n", "Numerical area for r = 1 and N = 3 is: 1.2990381056766582\n", "Numerical area for r = 1 and N = 6 is: 2.5980762113533156\n", @@ -3944,14 +3941,31 @@ "Numerical area for r = 1 and N = 3600 is: 3.1415910586169558\n", "Numerical area for r = 1 and N = 6400 is: 3.141592148930367\n", "This should be close to π: 3.141592653589793\n", - "Difference from π: 5.046594262481108e-7\n" + "Difference from π: 5.046594262481108e-7\n", + "\n", + "--- Area of regular n-gon as N → ∞ approaches πr^2 for r > 1---\n", + "Using r from earlier example which = 0.7071067811865476\n", + "Numerical area for r = 0.7071067811865476 and N = 3 is: 0.6495190528383293\n", + "Numerical area for r = 0.7071067811865476 and N = 6 is: 1.299038105676658\n", + "Numerical area for r = 0.7071067811865476 and N = 12 is: 1.5000000000000002\n", + "Numerical area for r = 0.7071067811865476 and N = 24 is: 1.5529142706151247\n", + "Numerical area for r = 0.7071067811865476 and N = 48 is: 1.5663143066406198\n", + "Numerical area for r = 0.7071067811865476 and N = 96 is: 1.5696751015234338\n", + "Numerical area for r = 0.7071067811865476 and N = 192 is: 1.5705159754452551\n", + "Numerical area for r = 0.7071067811865476 and N = 384 is: 1.5707262361427314\n", + "Numerical area for r = 0.7071067811865476 and N = 768 is: 1.570778803955929\n", + "Numerical area for r = 0.7071067811865476 and N = 1536 is: 1.5707919460741597\n", + "Numerical area for r = 0.7071067811865476 and N = 3072 is: 1.5707952316140257\n", + "Numerical area for r = 0.7071067811865476 and N = 3600 is: 1.570795529308478\n", + "Numerical area for r = 0.7071067811865476 and N = 6400 is: 1.5707960744651839\n", + "This should be close to πr^2: 1.570796326794897\n", + "Difference from πr^2: 2.523297131240554e-7\n" ] } ], "source": [ "# Create a symbolic expression for the area of a regular n-gon using radius r\n", - "println(\"\\n--- Area of regular n-gon as N → ∞ ---\")\n", - "println(\"We will derive the area expression symbolically and then evaluate it numerically for increasing N \\nto show it approaches π for r = 1.\\n\")\n", + "println(\"\\n--- Area of regular n-gon as N → ∞ approaches π for r = 1---\")\n", "@variables r N\n", "area_expr = (1/4) * N * (2 * r * sin(π/N))^2 * cot(π/N)\n", "println(\"Symbolic area expression for regular n-gon: \", area_expr)\n", @@ -3969,7 +3983,23 @@ "area_value = area_function(r_value, N_value)\n", "println(\"Numerical area for r = \", r_value, \" and N = \", N_value, \" is: \", area_value)\n", "println(\"This should be close to π: \", Float64(π))\n", - "println(\"Difference from π: \", abs(area_value - Float64(π)))" + "println(\"Difference from π: \", abs(area_value - Float64(π)))\n", + "\n", + "println(\"\\n--- Area of regular n-gon as N → ∞ approaches πr^2 for r > 1---\")\n", + "# Evaluate the area function with r > 1 and iterating over various values of N\n", + "# the point is we want to show that the larger N the closer it is to pi\n", + "r_value = sqrt(2)/2\n", + "println(\"Using r from earlier example which = \", r_value)\n", + "for N_value in [3, 6, 12, 24, 48, 96, 192, 384, 768, 1536, 3072,3600]\n", + " area_value = area_function(r_value, N_value)\n", + " println(\"Numerical area for r = \", r_value, \" and N = \", N_value, \" is: \", area_value)\n", + "end \n", + "# Final test with N = 3600\n", + "N_value = 6400\n", + "area_value = area_function(r_value, N_value)\n", + "println(\"Numerical area for r = \", r_value, \" and N = \", N_value, \" is: \", area_value)\n", + "println(\"This should be close to πr^2: \", Float64(π)*r_value^2)\n", + "println(\"Difference from πr^2: \", abs(area_value - Float64(π)*r_value^2))" ] } ], From 593fc0a7eb935a7543069d7fd1890234ba86f12a Mon Sep 17 00:00:00 2001 From: Aron T Date: Sat, 22 Nov 2025 22:52:13 +0200 Subject: [PATCH 8/9] Restructure and expand copilot instructions - Reorganize into clearer sections (Overview, Core Architecture, Critical Patterns) - Add explicit code examples for computational/plotting separation pattern - Document both Symbolics.jl numeric evaluation methods (substitute+value and build_function) - Expand documentation patterns section with comprehensive style guidelines - Add mathematical concept documentation structure guidelines - Include MathWorld linking conventions and visual element guidance - Streamline CI/CD pipeline descriptions - Improve overall clarity and actionability --- .github/copilot-instructions.md | 299 +++++++++++++++++++------------- 1 file changed, 178 insertions(+), 121 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 3ea1810..75331bc 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,180 +1,206 @@ # Copilot Instructions for Math_Foundations -## Project Architecture +## Project Overview -This is a **Julia scientific computing project** using DrWatson for reproducibility, focused on mathematical foundations with visualization capabilities. The codebase follows a **modular mathematical library pattern** with comprehensive testing and documentation. +**Julia scientific computing project** using DrWatson for reproducibility. Implements mathematical foundations (algebra, geometry, trigonometry) with visualization, comprehensive testing, and cross-repository documentation deployment. -### Core Components +### Core Architecture -- **`src/Math_Foundations.jl`**: Main module with smart environment detection for CI/interactive plotting -- **`src/basic_maths.jl`**: Mathematical functions (roots, polynomials, hyperbolas, financial calculations) -- **`test/`**: Comprehensive test suite with CI-compatible plotting tests (54 total tests) -- **`docs/`**: Documenter.jl setup with mathematical sections (Algebra, Geometry, etc.) and cross-repository deployment to math_tech_study +- **`src/Math_Foundations.jl`**: Main module with CI-aware plotting (auto-detects headless environments) +- **`src/basic_maths.jl`**: Mathematical library (roots, polynomials, hyperbolas, financial calculations) +- **`test/`**: 54 tests with separated computational/plotting logic for CI compatibility +- **`docs/`**: Documenter.jl deploying to `https://study.fourm.info/math_foundations/` (cross-repo to `math_tech_study`) +- **`notebooks/`**: Jupyter notebooks for exploration (not tested in CI) ## Critical Development Patterns -### Module Structure +### Module Structure & Exports + +All code uses `@reexport` pattern and exports both computational + plotting functions: + ```julia -# Main module uses @reexport for clean interface +# src/Math_Foundations.jl using Reexport @reexport using Symbolics, Nemo, Plots, Latexify, LaTeXStrings, Dates, AMRVW, Polynomials -# Comprehensive exports for all functions -export nth_root -export plot_parabola_roots_amrvw, plot_parabola_roots_polynomial, plot_parabola_roots_quadratic -# ... + +# Export computational functions (no plotting) +export calculate_parabola_roots_quadratic, calculate_parabola_roots_polynomial, calculate_parabola_roots_amrvw + +# Export integrated plotting functions (computation + visualization) +export plot_parabola_roots_quadratic, plot_hyperbola, plot_hyperbola_axes_direct + +# Always export new functions in main module ``` -### Environment-Aware Module Loading + +### Automatic CI/Interactive Detection + +Module auto-configures at load time - no manual intervention needed: + ```julia -# The module automatically detects CI vs interactive environments +# src/Math_Foundations.jl - Runs on module load if haskey(ENV, "CI") || get(ENV, "GKSwstype", "") == "100" ENV["GKSwstype"] = "100" # Headless plotting gr(show=false) +else + gr() # Interactive plotting end ``` -## Math_Foundations CI Testing Approach +## Testing Strategy (CI-Compatible) -The superior CI testing strategy consists of three components: +### Three-Layer Testing Approach -### 1. Module-Level Headless Detection -Configure plotting environment in the main module (`Math_Foundations.jl`) at load time: +**1. Module-Level Detection** - Automatic (in `Math_Foundations.jl`): ```julia -# Automatic CI detection and headless configuration if haskey(ENV, "CI") || get(ENV, "GKSwstype", "") == "100" - ENV["GKSwstype"] = "100" # Force headless mode - gr(show=false) # Disable plot display + ENV["GKSwstype"] = "100" + gr(show=false) end ``` -### 2. Manual GKS Configuration in Tests -Set `ENV["GKSwstype"] = "100"` in test files before loading the module: +**2. Test-Level Configuration** - Manual (in `runtests.jl`): ```julia -# In runtests.jl - Configure headless mode before loading module -ENV["GKSwstype"] = "100" # Force headless plotting for CI +ENV["GKSwstype"] = "100" # Set BEFORE using Math_Foundations using DrWatson, Test @quickactivate "Math_Foundations" using Math_Foundations ``` -### 3. Separated Computational/Plotting Logic with Robust Testing -- **Pure computational functions** (`calculate_*`): Test mathematical logic directly, no try-catch -- **Plotting functions** (`plot_*`): Test with try-catch fallback for CI compatibility -- **Integration testing**: Verify both computation and visualization work together +**3. Separated Logic** - Design pattern for all new functions: + +- **Computational functions** (`calculate_*`): Pure math, no plotting, test directly +- **Plotting functions** (`plot_*`): Computation + visualization, test with try-catch +- **Pattern Example**: -### Test Setup (Uses @quickactivate) -```julia -# Tests use DrWatson @quickactivate pattern -using DrWatson, Test -@quickactivate "Math_Foundations" -# Load the Math_Foundations package -using Math_Foundations -``` -## Plotting Functions Pattern -All plotting functions auto-save with timestamps to `plots/` directory: ```julia -savefig("plots/"* Dates.format(now(),"yyyymmdd-HHMMSS") * "functionname.png" +# src/basic_maths.jl +function calculate_parabola_roots_quadratic(a₂, a₁=0.0, a₀=0.0) + discriminant = a₁^2 - 4 * a₂ * a₀ + root1 = (-a₁ + sqrt(Complex(discriminant))) / (2 * a₂) + root2 = (-a₁ - sqrt(Complex(discriminant))) / (2 * a₂) + return [root1, root2] # Always returns ComplexF64 +end + +function plot_parabola_roots_quadratic(a₂, a₁=0.0, a₀=0.0) + all_roots = calculate_parabola_roots_quadratic(a₂, a₁, a₀) # Math always succeeds + try + @variables x + f = a₂ * x^2 + a₁ * x + a₀ + plot_parabola(f, all_roots, a₂, a₁, a₀, "Quadratic") + catch e + !haskey(ENV, "CI") && @warn "Plotting failed: $e" + end + return [real(r) for r in all_roots if abs(imag(r)) < 1e-10] # Real roots only +end ``` -## Julia Coding Standards -### Mathematical Functions -1. Use standard Julia mathematical conventions -2. Handle negative numbers appropriately (see `nth_root`) -3. Return complex numbers for even roots of negative numbers -4. Include comprehensive edge case testing -5. Always export new functions in main module -6. Use Unicode symbols (a₂, a₁, a₀) in function parameters - -### Documentation & Comments -8. Include detailed comments explaining mathematical concepts -9. Use LaTeX math notation with Latexify.jl integration -10. Ensure all examples include explanatory text -11. Maintain the notebook-based structure with markdown explanations - -### Testing Patterns -12. Include unit tests for all functions -13. Use Julia's built-in testing framework -14. Use `@test` for assertions in unit tests -15. Use `@testset` to group related tests by function -16. Use `@test_throws` to test for expected errors -17. Use `@test_broken` to mark tests that are known to fail -18. Group tests with comprehensive edge cases (54+ tests) -19. **CI-Compatible Testing Pattern**: Separate computational logic from plotting, test math directly without try-catch, only use try-catch for visualization: +### Testing Pattern + ```julia -# Test computational logic directly (NO try-catch - mathematical errors should fail) -@testset "Pure Computational Tests" begin +# test/test_basic_maths.jl +@testset "Computational Tests" begin + # NO try-catch - math errors should fail roots = calculate_parabola_roots_quadratic(1.0, 0.0, -4.0) @test length(roots) == 2 @test typeof(roots) == Vector{ComplexF64} - # Test mathematical correctness without plotting dependencies end -# Test integration (plotting + computation) with CI-safe fallback @testset "Integration Tests" begin + # try-catch for CI-safe plotting try - # Test the plotting function (includes computation + visualization) result = plot_parabola_roots_quadratic(1.0, 0.0, -4.0) - @test typeof(result) == Vector{Float64} # Real roots only for backward compatibility - @test length(result) == 2 + @test typeof(result) == Vector{Float64} # Real roots catch e - # Graceful fallback for CI - test function exists and computational core works @test hasmethod(plot_parabola_roots_quadratic, (Float64, Float64, Float64)) - # Verify computational core still works via the separate computational function - computational_result = calculate_parabola_roots_quadratic(1.0, 0.0, -4.0) - @test typeof(computational_result) == Vector{ComplexF64} + @test typeof(calculate_parabola_roots_quadratic(1.0, 0.0, -4.0)) == Vector{ComplexF64} end end ``` -### Code Organization -19. Follow the pattern of existing code in basic_maths.jl -20. Use consistent naming conventions for variables and functions -21. Ensure all code is well-documented and follows Julia's style guide +### Plotting Conventions + +- All plots auto-save: `"plots/" * Dates.format(now(),"yyyymmdd-HHMMSS") * "functionname.png"` +- Ensure `plots/` directory exists before running tests +- Use LaTeX titles: `title!(L"Plot\ of\ %$a₂ * x^2 + %$a₁ * x + %$a₀\\")` -## Dependencies & Performance +## Coding Standards -**Heavy Dependencies** (main Project.toml): Nemo (~500MB), Makie, Symbolics, GLMakie -**Optimized Test Dependencies** (test/Project.toml): Only essential packages for CI speed +### Mathematical Functions -### Mathematical Libraries Used -- **Symbolics.jl**: For `@variables x` in hyperbola functions - - Pattern: Follow the @variables pattern seen in our notebooks - - Prefer simplify(expr, expand=true) for algebraic expressions -- **Polynomials.jl**: For polynomial root finding (`plot_parabola_roots_polynomial`) -- **AMRVW.jl**: Alternative root finding method -- **Nemo.jl**: Number theory (imported but verify usage before adding tests) - - Use polynomial_ring(ZZ, [vars]) for creating polynomial rings - - Prefer factor() over manual factorization +- Use Unicode symbols for coefficients: `a₂, a₁, a₀` (type `a\\_2` in Julia) +- Return `ComplexF64` for roots (even if imaginary part is zero) +- Handle negative numbers correctly (see `nth_root` - odd roots return negative reals, even roots return complex) +- Always export new functions in `src/Math_Foundations.jl` +- Follow pattern: `calculate_*` (pure math) + `plot_*` (integrated) + +### Testing Requirements + +- **@testset structure**: Group tests by function (54 total tests across all functions) +- **No try-catch for math**: Computational tests should fail on mathematical errors +- **try-catch for plots**: Only use for CI-safe visualization testing +- **Edge cases**: Test positive/negative, zero, special values +- Use `@test_throws` for expected errors, `@test_broken` for known failures + +### Documentation Standards + +- **Docstrings**: Required for all exported functions with signature and description +- **LaTeX math**: Use for equations in docs and plot titles +- **MathWorld links**: Add for new mathematical concepts (verify URL before adding) +- **Markdown docs**: Files in `docs/src/` organized by topic (Algebra, Geometry, Trigonometry) +- **Examples**: Include in docstrings showing typical usage + +## Dependencies & Libraries + +**Heavy Dependencies**: Nemo (~500MB), GLMakie, WGLMakie (main Project.toml) +**Optimized Tests**: Minimal dependencies in `test/Project.toml` for CI speed + +### Key Mathematical Libraries + +- **Symbolics.jl**: Symbolic variables (`@variables x`) for equation manipulation + - Create variables: `@variables x; f = a₂*x^2 + a₁*x + a₀` + - Simplify expressions: `simplify(expr, expand=true)` + - **Extract numeric values** (two methods): + 1. **substitute + value**: `substitute(expr, x => π/4; fold=Val(true))` then `Symbolics.value(result)` + 2. **build_function**: `f = build_function(expr, x, expression=Val{false})` creates callable Julia function + - Use `fold=Val(true)` with substitute to simplify after substitution + - Use `expression=Val{false}` with build_function to avoid eval requirement +- **Polynomials.jl**: Polynomial operations and root finding + - Create: `p = Polynomial([a₀, a₁, a₂])` + - Solve: `roots(p)` +- **AMRVW.jl**: Alternative root finding: `AMRVW.roots([a₀, a₁, a₂])` +- **Nemo.jl**: Number theory (verify usage patterns before adding new tests) +- **Plots.jl/GR**: Plotting with automatic CI headless mode ## Key Workflows -### Running Tests Locally +### Local Development + ```bash +# Run tests julia --project=. test/runtests.jl -``` -### Running Tests in CI Mode -```bash +# CI mode (headless plotting) CI=true julia --project=. test/runtests.jl -``` -### Building Documentation -```bash +# Build documentation julia --project=. docs/make.jl ``` -### Julia Compilation Considerations -- **Be Patient with First Runs**: Julia often needs to precompile packages and rebuild project cache on first run. when running a Julia command in the CLI for the first time, it may take a while to precompile the packages and build the project cache, so you won't see the results of running the command for a while. -- **Typical First Run**: May take 15-30 seconds for precompilation before tests actually start -- **Example Expected Output**: `Precompiling DrWatson... 3 dependencies successfully precompiled in 17 seconds` -- **Subsequent Runs**: Much faster once cache is built -- **Don't Cancel Early**: Allow time for compilation phase to complete -- **IMPORTANT**: This applies to ALL Julia commands including CI testing with `CI=true julia --project=. test/runtests.jl` +### Julia Compilation -### CI Considerations -- Plots directory must exist for plotting tests to pass -- Configure headless mode before plotting in tests -- 54 comprehensive tests covering all mathematical functions -- Test execution includes edge cases and error handling +**CRITICAL**: First runs take 15-30 seconds for precompilation - DO NOT cancel early! + +- **First Run**: `Precompiling DrWatson... 3 dependencies successfully precompiled in 17 seconds` +- **Subsequent Runs**: Near-instant once cache exists +- **Applies to**: ALL Julia commands including tests + +### CI/CD Pipeline + +- **Tests**: Run on all PRs (`.github/workflows/CI.yml`) +- **Docs Build**: Test on PR (no deploy) +- **Docs Deploy**: Auto-deploy to `https://study.fourm.info/math_foundations/` on merge to `main` +- **Cross-Repo**: Deploys to `FourMInfo/math_tech_study` subdirectory +- **Prerequisites**: `plots/` directory must exist for tests to pass ## Git Best Practices @@ -251,16 +277,47 @@ triangle_area_perim(a::Float64, b::Float64, c::Float64) -> Tuple{Float64, Float6 ``` ## Documentation Patterns -- Use LaTeX for all mathematical notation -- Use LaTeX syntax for mathematical symbols not Unicode e.g. "^\circ" instead of "°" -- Use Markdown for explanations -- After creating or editing a markdown document always review and fix all linting issues, unless the document is a configuration file of some kind -- Follow the pattern of existing function documentation in src directory -- When a new mathematical concept is introduced, add an external link to [MathWorld](https://mathworld.wolfram.com/) for that specific concept. - - Compare multiple potential URLs to choose the most appropriate one - - Avoid replacing working links with inferior alternatives - - Always use fetch_webpage function to check the link is valid and points to the correct concept. -- use underscore not askterisk for markdown emphasis + +### Structure for Mathematical Concept Documentation + +Documentation in `docs/src/` explains general math concepts (not code). Follow these patterns: + +**Document Organization:** +- Start with concept overview and [MathWorld](https://mathworld.wolfram.com/) link in opening paragraph +- Use hierarchical headings: `##` for major topics, `###` for subtopics +- Group related concepts (e.g., "By Side Length", "By Angle Measure") +- Include real-world applications section + +**Content Style:** +- **Definitions first**: Clear, precise mathematical definitions with MathWorld links +- **Build progressively**: Simple concepts → complex relationships → applications +- **Multiple representations**: Equations, tables, visual aids (SVG diagrams when helpful) +- **Context matters**: Explain _why_ concepts are important, not just _what_ they are + - Example: "Arc length is crucial for engineering, navigation, physics..." +- **Derivations**: Show mathematical reasoning step-by-step (see Hyperbola derivation) + +**Mathematical Notation:** +- Use LaTeX: `$$` for display equations, inline with `$...$` +- LaTeX syntax for symbols: `^\circ` not `°`, `\frac{}{}` for fractions +- Label variables clearly: "where: $r$ = radius, $θ$ = angle" +- Use aligned equations: `\begin{aligned}...\end{aligned}` for multi-step derivations + +**MathWorld Links:** +- Link every new mathematical term on first mention +- Format: `[Term](https://mathworld.wolfram.com/Term.html)` +- Verify URLs before adding (use fetch_webpage) +- Compare multiple URLs to choose most appropriate + +**Visual Elements:** +- SVG diagrams for geometric concepts (see Triangles, Polygons) +- Tables for reference data (degree/radian conversions, common values) +- Consistent styling in diagrams (colors, labels, annotations) + +**Markdown Conventions:** +- _Underscore_ for emphasis (not asterisk) +- **Bold** for important terms and section labels +- Fix all linting issues after editing (except config files) +- Code blocks with language tags: ````julia` for Julia examples ## Communication Patterns From cf8f40f85e4d42a4450cd8af8ce07818580b7f83 Mon Sep 17 00:00:00 2001 From: Aron T Date: Wed, 26 Nov 2025 15:25:55 +0200 Subject: [PATCH 9/9] Add pizza example and fix circle documentation - Add practical pizza example demonstrating circle through three points - Fix markdown linting issues in Circles documentation - Calculate pizza center and radius from three edge points - Verify circle equation with all three points --- docs/src/Geometry/04 Circles.md | 26 ++++------ notebooks/Basics.ipynb | 90 +++++++++++++++++++++++++++++++-- 2 files changed, 97 insertions(+), 19 deletions(-) diff --git a/docs/src/Geometry/04 Circles.md b/docs/src/Geometry/04 Circles.md index 4e6c567..6100466 100644 --- a/docs/src/Geometry/04 Circles.md +++ b/docs/src/Geometry/04 Circles.md @@ -18,9 +18,7 @@ ### Circumference -The circumference of a circle is the distance around it, given by: $$C = 2\pi r = \pi d$$ - -where: +The circumference of a circle is the distance around it, given by: $$C = 2\pi r = \pi d$$ where: - circumference: $C$ - radius: $r$ @@ -35,9 +33,7 @@ where: ### Area -The area enclosed by a circle is: $$A = \pi r^2$$ - -where: +The area enclosed by a circle is: $$A = \pi r^2$$ where: - area: $A$ - radius: $r$ @@ -99,11 +95,9 @@ A &= \sum \frac{1}{2} \times \text{base} \times \text{height} \\ ### Arc Length -- **Arc Length:** For an arc subtending angle $\theta$ (in radians) at the center: - $$s = r\theta$$ - - For angle in degrees: - $$s = \frac{\pi r \theta}{180}$$ +- **Arc Length:** The length of an arc subtended by a central angle $\theta$ in a circle of radius $r$ is given by: + - For angle $\theta$ (in radians): $$s = r\theta$$ + - For angle $\theta$ (in degrees): $$s = \frac{\pi r \theta}{180}$$ ### Sectors and Segments @@ -111,14 +105,14 @@ A &= \sum \frac{1}{2} \times \text{base} \times \text{height} \\ - Area of sector with central angle $\theta$ (in radians): $$A_{\text{sector}} = \frac{1}{2}r^2\theta$$ - - For angle in degrees: + - Area of sector with central angle $\theta$ (in degrees): $$A_{\text{sector}} = \frac{\pi r^2 \theta}{360}$$ -- **[Segment](https://mathworld.wolfram.com/CircularSegment.html):** The region bounded by a chord and the arc it subtends[subtending](https://mathworld.wolfram.com/Subtend.html) - - Area of segment: +- **[Segment](https://mathworld.wolfram.com/CircularSegment.html):** The region bounded by a chord and the arc it subtends + - Area of segment with central angle $\theta$ (in radians): $$A_{\text{segment}} = A_{\text{sector}} - A_{\text{triangle}} = \frac{1}{2}r^2(\theta - \sin\theta)$$ - - where $\theta$ is in radians + - Area of segment with central angle $\theta$ (in degrees): + $$A_{\text{segment}} = \frac{\pi r^2 \theta}{360} - \frac{1}{2}r^2\sin\left(\frac{\pi \theta}{180}\right)$$ ## Circle Equations diff --git a/notebooks/Basics.ipynb b/notebooks/Basics.ipynb index 1358d16..fc40eb1 100644 --- a/notebooks/Basics.ipynb +++ b/notebooks/Basics.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -2463,7 +2463,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -4001,6 +4001,90 @@ "println(\"This should be close to πr^2: \", Float64(π)*r_value^2)\n", "println(\"Difference from πr^2: \", abs(area_value - Float64(π)*r_value^2))" ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Thursday is, as always, big pizza day and you order a family pizza with a diameter of 80 cm \n", + "for you and your seven friends. How many cm^2 of pizza--assuming even distribution--does each of you get?\n", + "\n", + "Angle α at the center of the pizza slice for each of the 8 friends is 0.7853981633974484 radians\n", + "Radius r of the pizza is 40 cm\n", + "Area F of the pizza (circle) sector (slice) 1/2 * r^2 * α = 628.319 cm²\n", + "\n", + "Approximately how many cm of uncovered crust is available to each of you?\n", + "Circumference C of the pizza is 2 * π * r = 251.327 cm\n", + "Length of the uncovered crust per slice C_slice = C / 8 = 31.416 cm\n", + "\n", + "This week, your pizza chef makes you a very special offer: he sells you a pizza in the shape of a \n", + "circular ring with an outer diameter of 1 m and an inner diameter of 50 cm for the same price. You calculate \n", + "briefly how many cm^2 of pizza and how many cm of uncovered edge each of your friends would now get.\n", + "Outer radius rₒ of the pizza ring is 50 cm\n", + "Inner radius rᵢ of the pizza ring is 25 cm\n", + "Area F of the outer pizza slice 1/2 * rₒ^2 * α = 981.748 cm²\n", + "Area F of the inner pizza slice 1/2 * rᵢ^2 * α = 245.437 cm²\n", + "Actual area F of the pizza ring slice = F_outer_slice - F_inner_slice = 736.311 cm²\n", + "Outer circumference C_outer of the pizza ring is 2 * π * rₒ = 314.159 cm\n", + "Inner circumference C_inner of the pizza ring is 2 * π * rᵢ = 157.08 cm\n", + "Length of the outer uncovered crust per slice C_slice_outer = C_outer / 8 = 39.27 cm\n", + "Length of the inner uncovered crust per slice C_slice_inner = C_inner / 8 = 19.635 cm\n", + "Total uncovered crust per slice C_total = C_slice_inner + C_slice_outer = 58.905 cm\n", + "\n", + "Should you accept the pizza chef's offer?\n", + "Each of you gets more pizza area with the ring pizza: 107.992 cm² more per person. Accept offer!!\n" + ] + } + ], + "source": [ + "println(\"Thursday is, as always, big pizza day and you order a family pizza with a diameter of 80 cm \n", + "for you and your seven friends. How many cm^2 of pizza--assuming even distribution--does each of you get?\\n\")\n", + "α = 2π/8\n", + "println(\"Angle α at the center of the pizza slice for each of the 8 friends is \", round(α; digits=3r), \" radians\")\n", + "r = 40\n", + "println(\"Radius r of the pizza is \", r, \" cm\")\n", + "F_slice =1/2 * r^2 * α\n", + "println(\"Area F of the pizza (circle) sector (slice) 1/2 * r^2 * α = \", round(F_slice; digits=3), \" cm²\")\n", + "println(\"\\nApproximately how many cm of uncovered crust is available to each of you?\")\n", + "C = 2 * π * r\n", + "println(\"Circumference C of the pizza is 2 * π * r = \", round(C; digits=3), \" cm\")\n", + "C_slice = C / 8\n", + "println(\"Length of the uncovered crust per slice C_slice = C / 8 = \", round(C_slice; digits=3), \" cm\")\n", + "println(\"\\nThis week, your pizza chef makes you a very special offer: he sells you a pizza in the shape of a \n", + "circular ring with an outer diameter of 1 m and an inner diameter of 50 cm for the same price. You calculate \n", + "briefly how many cm^2 of pizza and how many cm of uncovered edge each of your friends would now get.\")\n", + "rₒ = 50\n", + "rᵢ = 25\n", + "println(\"Outer radius rₒ of the pizza ring is \", rₒ, \" cm\")\n", + "println(\"Inner radius rᵢ of the pizza ring is \", rᵢ, \" cm\")\n", + "F_outer_slice = 1/2 * rₒ^2 * α\n", + "println(\"Area F of the outer pizza slice 1/2 * rₒ^2 * α = \", round(F_outer_slice; digits=3), \" cm²\")\n", + "F_inner_slice = 1/2 * rᵢ^2 * α\n", + "println(\"Area F of the inner pizza slice 1/2 * rᵢ^2 * α = \", round(F_inner_slice; digits=3), \" cm²\")\n", + "F_ring_slice = F_outer_slice - F_inner_slice\n", + "println(\"Actual area F of the pizza ring slice = F_outer_slice - F_inner_slice = \", round(F_ring_slice; digits=3), \" cm²\")\n", + "C_outer = 2 * π * rₒ\n", + "C_slice_outer = C_outer / 8\n", + "println(\"Outer circumference C_outer of the pizza ring is 2 * π * rₒ = \", round(C_outer; digits=3), \" cm\")\n", + "C_inner = 2 * π * rᵢ\n", + "C_slice_inner = C_inner / 8\n", + "println(\"Inner circumference C_inner of the pizza ring is 2 * π * rᵢ = \", round(C_inner; digits=3), \" cm\")\n", + "println(\"Length of the outer uncovered crust per slice C_slice_outer = C_outer / 8 = \", round(C_slice_outer; digits=3), \" cm\")\n", + "println(\"Length of the inner uncovered crust per slice C_slice_inner = C_inner / 8 = \", round(C_slice_inner; digits=3), \" cm\")\n", + "C_total = C_slice_inner + C_slice_outer\n", + "println(\"Total uncovered crust per slice C_total = C_slice_inner + C_slice_outer = \", round(C_total; digits=3), \" cm\")\n", + "println(\"\\nShould you accept the pizza chef's offer?\")\n", + "if F_ring_slice > F_slice\n", + " println(\"Each of you gets more pizza area with the ring pizza: \", round(F_ring_slice - F_slice; digits=3), \" cm² more per person. Accept offer!!\")\n", + "else\n", + " println(\"Each of you gets less pizza area with the ring pizza: \", round(F_slice - F_ring_slice; digits=3), \" cm² less per person. Decline offer!!\") \n", + "end\n" + ] } ], "metadata": { @@ -4013,7 +4097,7 @@ "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", - "version": "1.12.1" + "version": "1.12.2" } }, "nbformat": 4,