Calculus
Jamie Flux
Contents
1 Real Numbers and Functions 14
Properties of the Real Numbers . . . . . . . . . . . . 14
Set Notation . . . . . . . . . . . . . . . . . . . . . . 14
Functions as Mappings Between Sets . . . . . . . . . 15
Python Code Snippet . . . . . . . . . . . . . . . . . 15
2 The Geometry of Graphs 20
The Cartesian Coordinate System . . . . . . . . . . 20
Graphing Techniques . . . . . . . . . . . . . . . . . . 20
Intercepts . . . . . . . . . . . . . . . . . . . . . . . . 21
Symmetry . . . . . . . . . . . . . . . . . . . . . . . . 21
Transformations of Functions . . . . . . . . . . . . . 22
Python Code Snippet . . . . . . . . . . . . . . . . . 22
3 Limits and Their Properties 27
The Concept of a Limit . . . . . . . . . . . . . . . . 27
1 Epsilon-Delta Definition . . . . . . . . . . . . 27
Limit Laws and Algebraic Properties . . . . . . . . . 28
1 Linearity and Constant Multiplication . . . . 28
2 Products, Quotients, and Powers . . . . . . . 28
Applications of the Concept of Approaching Values . 29
1 One-Sided Limits . . . . . . . . . . . . . . . . 29
2 Limits of Functions Approaching Infinity . . 29
Python Code Snippet . . . . . . . . . . . . . . . . . 30
4 Techniques for Evaluating Limits 33
Factoring and Simplification Techniques . . . . . . . 33
Rationalization Techniques . . . . . . . . . . . . . . 34
Handling Indeterminate Forms . . . . . . . . . . . . 34
Python Code Snippet . . . . . . . . . . . . . . . . . 35
1
5 Continuity of Functions 37
Continuity at a Point . . . . . . . . . . . . . . . . . . 37
Continuity on Intervals . . . . . . . . . . . . . . . . . 37
Intrinsic Properties and Behaviors of Continuous Func-
tions . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Classification and Analysis of Discontinuities . . . . 39
Python Code Snippet . . . . . . . . . . . . . . . . . 40
6 Intermediate Value Theorem and Applications 45
Statement and Formal Framework . . . . . . . . . . 45
Proof Utilizing Completeness of the Real Numbers . 45
Existence of Solutions via the Intermediate Value
Theorem . . . . . . . . . . . . . . . . . . . . . . . . . 46
Analysis of Function Behavior through the IVT . . . 47
Python Code Snippet . . . . . . . . . . . . . . . . . 47
7 The Derivative: Concept and Definition 50
Definition and Notational Conventions . . . . . . . . 50
Analytical Framework of the Difference Quotient . . 50
Geometric Interpretation and the Tangent Line . . . 51
Python Code Snippet . . . . . . . . . . . . . . . . . 51
8 Basic Differentiation Rules 54
The Sum and Difference Rules . . . . . . . . . . . . 54
The Product Rule . . . . . . . . . . . . . . . . . . . 55
The Quotient Rule . . . . . . . . . . . . . . . . . . . 55
Python Code Snippet . . . . . . . . . . . . . . . . . 56
9 Chain Rule for Differentiation 59
Preliminaries and Notational Conventions . . . . . . 59
Theoretical Development and Formal Derivation . . 59
Illustrative Examples . . . . . . . . . . . . . . . . . . 60
1 Example 1: Power of a Polynomial Function . 60
2 Example 2: Exponential of a Linear Function 61
3 Example 3: Trigonometric Composition . . . 61
4 Example 4: Logarithmic of a Rational Function 62
Python Code Snippet . . . . . . . . . . . . . . . . . 63
10 Implicit Differentiation and Related Rates 66
Implicit Differentiation . . . . . . . . . . . . . . . . . 66
1 Fundamental Principles . . . . . . . . . . . . 66
2 Illustrative Example in Implicit Differentiation 67
Related Rates . . . . . . . . . . . . . . . . . . . . . . 67
2
1 General Framework for Related Rates . . . . 68
2 Exemplary Application: Circular Motion . . 68
3 Extension to More Complex Relations . . . . 69
Python Code Snippet . . . . . . . . . . . . . . . . . 70
11 Differentiation of Trigonometric Functions 72
Derivatives of the Sine and Cosine Functions . . . . 72
Derivatives of Other Trigonometric Functions . . . . 73
Applications of Trigonometric Derivatives . . . . . . 74
Python Code Snippet . . . . . . . . . . . . . . . . . 75
12 Differentiation of Exponential and Logarithmic Func-
tions 78
Exponential Functions . . . . . . . . . . . . . . . . . 78
Logarithmic Functions . . . . . . . . . . . . . . . . . 79
Properties and Interrelations . . . . . . . . . . . . . 80
Python Code Snippet . . . . . . . . . . . . . . . . . 81
13 Differentiation of Inverse Functions 85
Preliminaries . . . . . . . . . . . . . . . . . . . . . . 85
The Derivative of an Inverse Function . . . . . . . . 85
Analytical Justification . . . . . . . . . . . . . . . . . 86
Interrelation of a Function and Its Inverse . . . . . . 87
Python Code Snippet . . . . . . . . . . . . . . . . . 87
14 Higher Order Derivatives and Applications 89
Definition and Notation . . . . . . . . . . . . . . . . 89
Second Derivative: Concavity and Acceleration . . . 90
Higher Order Derivatives . . . . . . . . . . . . . . . 90
Applications in Analysis and Applied Contexts . . . 91
Python Code Snippet . . . . . . . . . . . . . . . . . 91
15 Graphical Analysis Using Derivatives 95
The First Derivative Test and Critical Point Analysis 95
The Second Derivative Test and Concavity . . . . . 96
Enhanced Graph Sketching Techniques . . . . . . . . 96
Python Code Snippet . . . . . . . . . . . . . . . . . 97
16 Mean Value Theorem and Its Consequences 101
Statement of the Mean Value Theorem . . . . . . . . 101
Proof of the Mean Value Theorem . . . . . . . . . . 101
Implications for the Behavior of Functions and Rates
of Change . . . . . . . . . . . . . . . . . . . . . . . . 102
3
Python Code Snippet . . . . . . . . . . . . . . . . . 103
17 Increasing and Decreasing Functions 106
Preliminaries and Definitions . . . . . . . . . . . . . 106
Monotonicity via the Derivative . . . . . . . . . . . . 107
Critical Points and Their Analysis . . . . . . . . . . 107
Methodology for Identifying Intervals of Monotonicity108
Python Code Snippet . . . . . . . . . . . . . . . . . 108
18 Concavity, Inflection Points, and Curve Sketching 112
Concavity and Second Derivative Analysis . . . . . . 112
1 Definition and Characterization . . . . . . . . 112
2 Analytical Insights Through Taylor Expansion113
Inflection Points: Definitions and Criteria . . . . . . 113
Techniques for Curve Sketching Via Second Deriva-
tive Analysis . . . . . . . . . . . . . . . . . . . . . . 114
Python Code Snippet . . . . . . . . . . . . . . . . . 114
19 Optimization Problems 117
Critical Points and Necessary Conditions for Opti-
mality . . . . . . . . . . . . . . . . . . . . . . . . . . 117
Local Extrema and the Second Derivative Test . . . 117
Global Optimization and Endpoint Analysis . . . . . 118
Python Code Snippet . . . . . . . . . . . . . . . . . 118
20 Applications in Motion: Velocity and Acceleration 121
Mathematical Modeling of Motion . . . . . . . . . . 121
Velocity as the First Derivative of Position . . . . . . 121
Acceleration as the Derivative of Velocity . . . . . . 122
Modeling Real-World Motion . . . . . . . . . . . . . 122
Python Code Snippet . . . . . . . . . . . . . . . . . 123
21 L’Hopital’s Rule 127
Foundations of Indeterminate Forms . . . . . . . . . 127
Formal Statement and Theoretical Underpinnings . . 128
Applications in Evaluating Indeterminate Limits . . 128
Python Code Snippet . . . . . . . . . . . . . . . . . 129
22 Antiderivatives and Indefinite Integrals 132
Definition and Conceptual Framework . . . . . . . . 132
The Inverse Relationship with Differentiation . . . . 133
Algebraic Properties of Indefinite Integrals . . . . . . 133
The Constant of Integration and its Role . . . . . . . 133
4
Python Code Snippet . . . . . . . . . . . . . . . . . 134
23 Techniques of Integration: Substitution 137
Preliminaries and Theoretical Foundations . . . . . . 137
Formal Framework of the Substitution Process . . . 138
Analytic Structure and Methodological Implemen-
tation . . . . . . . . . . . . . . . . . . . . . . . . . . 139
Exemplification Within a Rigorous Framework . . . 140
Python Code Snippet . . . . . . . . . . . . . . . . . 141
24 Techniques of Integration: Integration by Parts 143
Theoretical Underpinnings . . . . . . . . . . . . . . . 143
Formal Derivation from the Product Rule . . . . . . 143
Methodological Implementation . . . . . . . . . . . . 144
Illustrative Examples of Application . . . . . . . . . 145
Python Code Snippet . . . . . . . . . . . . . . . . . 146
25 Techniques of Integration: Partial Fractions 148
Preliminaries and Motivation . . . . . . . . . . . . . 148
Algebraic Foundations: Factorization and Structure
of Decomposition . . . . . . . . . . . . . . . . . . . . 149
General Framework of Partial Fraction Decomposition149
Integration of Decomposed Components . . . . . . . 150
Illustrative Examples of Partial Fraction Integration 151
Python Code Snippet . . . . . . . . . . . . . . . . . 152
26 Techniques of Integration: Trigonometric Integrals 154
Preliminaries on Trigonometric Identities and Sub-
stitutions . . . . . . . . . . . . . . . . . . . . . . . . 154
Integrals of Powers of Sine and Cosine . . . . . . . . 155
1 Odd Powers and Substitution Methods . . . . 155
2 Even Powers and Transformation via Double-
Angle Formulas . . . . . . . . . . . . . . . . . 155
Reduction Formulas for Trigonometric Integrals . . . 156
1 Derivation of Reduction Formulas for Sine
and Cosine Powers . . . . . . . . . . . . . . . 156
2 Extensions to Higher Trigonometric Powers . 156
Integrals of Mixed Trigonometric Expressions . . . . 157
1 Products Involving Sine and Cosine . . . . . 157
2 Integrals Involving Tangent, Secant, and Aux-
iliary Functions . . . . . . . . . . . . . . . . . 157
Python Code Snippet . . . . . . . . . . . . . . . . . 158
5
27 Techniques of Integration: Trigonometric Substitu-
tion 161
Fundamental Principles . . . . . . √ . . . . . . . . . . 161
Substitution for Integrals Involving √a2 − x2 . . . . 161
Substitution for Integrals Involving √a2 + x2 . . . . 162
Substitution for Integrals Involving x2 − a2 . . . . 162
Python Code Snippet . . . . . . . . . . . . . . . . . 163
28 Techniques of Integration: Improper Integrals 166
Definition and Classification of Improper Integrals . 166
Evaluation of Integrals with Infinite Limits . . . . . 167
Evaluation of Integrals with Unbounded Integrands . 167
Analytical Techniques and Convergence Criteria . . 168
Detailed Methodologies in Handling Unbounded Be-
havior . . . . . . . . . . . . . . . . . . . . . . . . . . 169
Python Code Snippet . . . . . . . . . . . . . . . . . 170
29 The Fundamental Theorem of Calculus, Part I 173
Preliminaries and Formal Statement . . . . . . . . . 173
Proof of the Fundamental Theorem of Calculus, Part I174
Analysis of Differentiability and Its Consequences . . 174
Python Code Snippet . . . . . . . . . . . . . . . . . 175
30 The Fundamental Theorem of Calculus, Part II 177
Formal Statement and Interpretations . . . . . . . . 177
Proof and Justification . . . . . . . . . . . . . . . . . 178
On the Uniqueness of Antiderivatives and the Eval-
uation of Definite Integrals . . . . . . . . . . . . . . 178
Python Code Snippet . . . . . . . . . . . . . . . . . 179
31 Properties of Definite Integrals 182
Linearity of Definite Integrals . . . . . . . . . . . . . 182
Additivity and Interval Decomposition . . . . . . . . 182
Symmetry Properties of Definite Integrals . . . . . . 183
Python Code Snippet . . . . . . . . . . . . . . . . . 184
32 Area Under a Curve 187
Riemann Sums and the Limit Process . . . . . . . . 187
The Definite Integral as an Area Measurement . . . 188
Fundamental Theorem of Calculus and Computa-
tion of Areas . . . . . . . . . . . . . . . . . . . . . . 188
Python Code Snippet . . . . . . . . . . . . . . . . . 189
6
33 Volumes of Solids of Revolution: Disk and Washer
Methods 192
Disk Method . . . . . . . . . . . . . . . . . . . . . . 192
Washer Method . . . . . . . . . . . . . . . . . . . . . 193
Analytical Considerations . . . . . . . . . . . . . . . 193
Python Code Snippet . . . . . . . . . . . . . . . . . 194
34 Volumes by the Shell Method 198
Fundamental Concepts . . . . . . . . . . . . . . . . . 198
Derivation of the Integral Expression . . . . . . . . . 199
Integral Representation and Adaptability . . . . . . 199
Python Code Snippet . . . . . . . . . . . . . . . . . 200
35 Arc Length Calculations 203
Fundamental Concepts and Differential Elements . . 203
Arc Length for Graphs in Cartesian Coordinates . . 203
Arc Length for Parametrically Defined Curves . . . . 204
Arc Length in Polar Coordinates . . . . . . . . . . . 204
Python Code Snippet . . . . . . . . . . . . . . . . . 205
36 Surface Area of Solids of Revolution 208
Differential Element of Surface Area . . . . . . . . . 208
Surface Area for Curves Revolved about the x-Axis . 209
Surface Area for Curves Revolved about the y-Axis . 209
Generalization to Parametric Representations . . . . 210
Python Code Snippet . . . . . . . . . . . . . . . . . 210
37 Applications of Integration in Physics: Work and
Energy 214
Work in Mechanical Systems . . . . . . . . . . . . . 214
Work along Curvilinear Paths . . . . . . . . . . . . . 215
Energy Computations via Integration . . . . . . . . . 215
Integration in Multidimensional Energy Calculations 216
Python Code Snippet . . . . . . . . . . . . . . . . . 216
38 Separable Differential Equations 222
Definition and Formulation . . . . . . . . . . . . . . 222
Method of Separation and Integration . . . . . . . . 222
General Solutions and Integration Techniques . . . . 223
Illustrative Examples . . . . . . . . . . . . . . . . . . 224
Python Code Snippet . . . . . . . . . . . . . . . . . 225
7
39 First Order Linear Differential Equations 228
General Form and Preliminaries . . . . . . . . . . . . 228
Derivation and Application of the Integrating Factor 228
Solution via Decomposition into Homogeneous and
Particular Components . . . . . . . . . . . . . . . . . 229
Python Code Snippet . . . . . . . . . . . . . . . . . 230
40 Exact Differential Equations and Integrating Fac-
tors 233
Definition and Identification of Exact Differential
Equations . . . . . . . . . . . . . . . . . . . . . . . . 233
Determining the Potential Function . . . . . . . . . . 234
Integrating Factors and Their Role in Nonexact Equa-
tions . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
1 Integrating Factors Depending on a Single
Variable . . . . . . . . . . . . . . . . . . . . . 235
2 Derivation of Integrating Factors . . . . . . . 235
Application and Resolution of Nonexact Equations . 236
Python Code Snippet . . . . . . . . . . . . . . . . . 237
41 Slope Fields and Qualitative Analysis 239
Fundamental Concepts of Slope Fields . . . . . . . . 239
Graphical Construction of Slope Fields . . . . . . . . 239
Qualitative Interpretation of Slope Fields . . . . . . 240
Structural Insights from Slope Field Patterns . . . . 240
Python Code Snippet . . . . . . . . . . . . . . . . . 241
42 Sequences: Definition and Basic Properties 244
Definition of Sequences . . . . . . . . . . . . . . . . . 244
Notation and Terminology . . . . . . . . . . . . . . . 244
Basic Properties of Sequences . . . . . . . . . . . . . 245
1 Boundedness . . . . . . . . . . . . . . . . . . 245
2 Monotonicity . . . . . . . . . . . . . . . . . . 245
3 Typical Examples . . . . . . . . . . . . . . . 246
Discussion of Additional Structural Features . . . . . 246
Python Code Snippet . . . . . . . . . . . . . . . . . 247
43 Convergence of Sequences 250
Definition of Convergence . . . . . . . . . . . . . . . 250
The Cauchy Criterion . . . . . . . . . . . . . . . . . 250
Monotonic Sequences and the Monotone Convergence
Principle . . . . . . . . . . . . . . . . . . . . . . . . . 251
8
Limit Superior and Limit Inferior . . . . . . . . . . . 251
Subsequence Convergence . . . . . . . . . . . . . . . 252
Criteria for Divergence . . . . . . . . . . . . . . . . . 252
Python Code Snippet . . . . . . . . . . . . . . . . . 252
44 Introduction to Series and Convergence Tests 257
Infinite Series: Definitions and Notation . . . . . . . 257
Convergence and Divergence of Infinite Series . . . . 258
Absolute and Conditional Convergence . . . . . . . . 258
Comparison Tests . . . . . . . . . . . . . . . . . . . . 259
Ratio and Root Tests . . . . . . . . . . . . . . . . . 259
Alternating Series and Other Convergence Tests . . 260
Python Code Snippet . . . . . . . . . . . . . . . . . 261
45 The Comparison and Limit Comparison Tests 265
The Direct Comparison Test . . . . . . . . . . . . . . 265
The Limit Comparison Test . . . . . . . . . . . . . . 266
Python Code Snippet . . . . . . . . . . . . . . . . . 267
46 Alternating Series and the Ratio Test 271
Alternating Series . . . . . . . . . . . . . . . . . . . 271
The Ratio Test . . . . . . . . . . . . . . . . . . . . . 272
Python Code Snippet . . . . . . . . . . . . . . . . . 274
47 Root Test and Integral Test for Series Convergence277
The Root Test . . . . . . . . . . . . . . . . . . . . . 277
1 Definition and Fundamental Properties . . . 277
2 Theoretical Underpinnings . . . . . . . . . . . 277
The Integral Test . . . . . . . . . . . . . . . . . . . . 278
1 Conditions for Validity . . . . . . . . . . . . . 278
2 Analytical Framework and Error Estimation 279
Python Code Snippet . . . . . . . . . . . . . . . . . 279
48 Power Series Representation of Functions 283
Definition and Convergence Properties . . . . . . . . 283
1 Definition of a Power Series . . . . . . . . . . 283
2 Convergence and Analyticity . . . . . . . . . 284
Techniques for Constructing Power Series Represen-
tations . . . . . . . . . . . . . . . . . . . . . . . . . . 284
1 Taylor Series Expansion . . . . . . . . . . . . 284
2 Alternative Methods and Series Manipulation 284
Advantages of Series Representations . . . . . . . . . 285
9
1 Termwise Operations and Analytic Continu-
ation . . . . . . . . . . . . . . . . . . . . . . . 285
2 Approximation and Computational Efficacy . 285
Python Code Snippet . . . . . . . . . . . . . . . . . 286
49 Determining the Interval of Convergence for Power
Series 291
Preliminaries and Fundamental Definitions . . . . . 291
Techniques for Calculating the Radius of Convergence292
1 Application of the Root Test . . . . . . . . . 292
2 Utilization of the Ratio Test . . . . . . . . . . 292
Determination of the Interval of Convergence . . . . 293
Python Code Snippet . . . . . . . . . . . . . . . . . 293
50 Taylor and Maclaurin Series 297
Derivation of the Taylor Series . . . . . . . . . . . . 297
Maclaurin Series: The Special Case at Zero . . . . . 298
Error Analysis and the Remainder Term . . . . . . . 298
Applications to Local Function Approximations . . . 299
Python Code Snippet . . . . . . . . . . . . . . . . . 299
51 Applications of Taylor Series Approximations 303
Local Approximations via Taylor Series . . . . . . . 303
Error Estimation and Convergence Properties . . . . 304
Applications in Practical Problem Solving . . . . . . 304
Python Code Snippet . . . . . . . . . . . . . . . . . 305
52 Parametric Equations and Calculus 309
Parametric Representations of Curves . . . . . . . . 309
1 Definition and Notation . . . . . . . . . . . . 309
2 Canonical Examples . . . . . . . . . . . . . . 309
Differentiation of Parametric Curves . . . . . . . . . 310
1 Computation of the First Derivative . . . . . 310
2 Computation of the Second Derivative . . . . 310
Integration Techniques in Parametric Calculus . . . 311
1 Arc Length Calculation . . . . . . . . . . . . 311
2 Area Computations for Parametric Curves . . 311
Python Code Snippet . . . . . . . . . . . . . . . . . 312
53 Polar Coordinates and Graphing 315
The Polar Coordinate System . . . . . . . . . . . . . 315
Plotting Techniques for Polar Curves . . . . . . . . . 316
Comparison with Cartesian Representations . . . . . 316
10
Python Code Snippet . . . . . . . . . . . . . . . . . 317
54 Calculus in Polar Coordinates: Derivatives 321
Differentiation of Polar Functions . . . . . . . . . . . 321
Calculation of the Cartesian Slope . . . . . . . . . . 322
Interpretation of the Polar Derivative . . . . . . . . 322
Python Code Snippet . . . . . . . . . . . . . . . . . 323
55 Calculus in Polar Coordinates: Area and Arc Length326
Area in Polar Coordinates . . . . . . . . . . . . . . . 326
Arc Length in Polar Coordinates . . . . . . . . . . . 327
Python Code Snippet . . . . . . . . . . . . . . . . . 328
56 Vectors in the Plane: Introduction and Operations330
Definition and Notation . . . . . . . . . . . . . . . . 330
Operations on Vectors . . . . . . . . . . . . . . . . . 331
Magnitude and Direction . . . . . . . . . . . . . . . 331
Python Code Snippet . . . . . . . . . . . . . . . . . 332
57 Analytic Geometry in the Plane 335
Coordinate Representations and Vectors in R2 . . . 335
Lines in the Plane . . . . . . . . . . . . . . . . . . . 336
Circles and Their Algebraic Characterizations . . . . 336
Conic Sections: Classification and Algebraic Analysis 337
1 Parabolas . . . . . . . . . . . . . . . . . . . . 337
2 Ellipses and Hyperbolas . . . . . . . . . . . . 337
Python Code Snippet . . . . . . . . . . . . . . . . . 338
58 Functions of Several Variables: Introduction 342
Definition of Multivariable Functions . . . . . . . . . 342
Domains of Multivariable Functions . . . . . . . . . 343
Python Code Snippet . . . . . . . . . . . . . . . . . 344
59 Partial Derivatives and Their Computation 347
Definition and Notation . . . . . . . . . . . . . . . . 347
Computational Techniques . . . . . . . . . . . . . . . 347
1 Direct Computation via the Limit Definition 347
2 Utilization of Differentiation Rules . . . . . . 348
Higher Order Partial Derivatives . . . . . . . . . . . 348
1 Second and Mixed Partial Derivatives . . . . 348
2 Clairaut’s Theorem on Mixed Partial Deriva-
tives . . . . . . . . . . . . . . . . . . . . . . . 349
Geometric and Analytic Significance . . . . . . . . . 349
11
Python Code Snippet . . . . . . . . . . . . . . . . . 350
60 Tangent Planes and Linear Approximations 354
Tangent Planes to Surfaces . . . . . . . . . . . . . . 354
1 Derivation of the Tangent Plane Equation . . 355
Linear Approximations of Multivariable Functions . 355
1 The Differential and First Order Taylor Ex-
pansion . . . . . . . . . . . . . . . . . . . . . 356
2 Geometric Interpretation of Linear Approxi-
mations . . . . . . . . . . . . . . . . . . . . . 356
3 Application of Linear Approximations in Anal-
ysis . . . . . . . . . . . . . . . . . . . . . . . 356
Python Code Snippet . . . . . . . . . . . . . . . . . 357
61 The Chain Rule in Several Variables 360
Preliminaries . . . . . . . . . . . . . . . . . . . . . . 360
General Formulation of the Chain Rule . . . . . . . . 360
Proof of the Multivariable Chain Rule . . . . . . . . 361
Coordinate Formulation and Further Implications . . 362
Python Code Snippet . . . . . . . . . . . . . . . . . 363
62 Optimization of Functions of Several Variables 365
Critical Points and Necessary Conditions . . . . . . 365
Second-Order Analysis and the Hessian Matrix . . . 366
Python Code Snippet . . . . . . . . . . . . . . . . . 367
63 Lagrange Multipliers for Constrained Optimization369
Formulation of the Constrained Problem . . . . . . . 369
Derivation of the Lagrange Multiplier Conditions . . 370
Regularity Conditions and Constraint Qualifications 370
Interpretation of the Lagrange Multiplier Equations 371
Solving the System of Lagrange Multiplier Equations 371
Python Code Snippet . . . . . . . . . . . . . . . . . 372
64 Multiple Integrals: Double Integrals and Applica-
tions 375
Fundamental Concepts and Definitions . . . . . . . . 375
Iterated Integrals and Fubini’s Theorem . . . . . . . 376
Applications to Areas and Volumes . . . . . . . . . . 376
Additional Applications and Computations . . . . . 377
Python Code Snippet . . . . . . . . . . . . . . . . . 378
12
65 Multiple Integrals: Triple Integrals in Rectangular
Coordinates 380
Preliminaries and Notation . . . . . . . . . . . . . . 380
Definition of the Triple Integral . . . . . . . . . . . . 381
Iterated Integrals and the Fubini Theorem . . . . . . 381
Evaluation Techniques . . . . . . . . . . . . . . . . . 381
Applications to Volume and Geometric Measures . . 382
Python Code Snippet . . . . . . . . . . . . . . . . . 383
66 Change of Variables in Multiple Integrals 386
General Framework of Coordinate Transformations . 386
1 Polar Coordinates in Two Dimensions . . . . 387
2 Cylindrical Coordinates in Three Dimensions 387
3 Spherical Coordinates in Three Dimensions . 388
Python Code Snippet . . . . . . . . . . . . . . . . . 388
13
Chapter 1
Real Numbers and
Functions
Properties of the Real Numbers
The set of real numbers, denoted by R, is structured as a complete
ordered field. In this formulation, the field axioms ensure that
both addition and multiplication are well-defined operations on R,
with the existence of identity elements 0 and 1, respectively. Every
nonzero element in R possesses a unique multiplicative inverse, and
the operations obey the associative, commutative, and distributive
laws. Furthermore, the total order on R is compatible with these
algebraic operations; specifically, for any a, b, and c in R, the
relation a < b guarantees that a + c < b + c, and if 0 < a and
0 < b, then 0 < ab. A defining aspect of R is its completeness,
which is encapsulated by the least upper bound property: every
nonempty subset of R that is bounded above has a supremum in
R. In addition, the Archimedean property asserts that for any real
number r, there exists a natural number n satisfying n > r. These
interrelated properties form a robust foundation for quantitative
analysis and further studies in calculus and beyond.
Set Notation
The language of set theory provides an indispensable framework for
formulating and expressing mathematical ideas. Sets are typically
represented by listing elements within curly braces; for example,
14
the set of even integers is written as {2n | n ∈ Z}, where Z denotes
the set of all integers. The symbol ∈ indicates membership, and
the notation ⊆ is used to denote that one set is a subset of another.
Fundamental set operations include union and intersection, repre-
sented by ∪ and ∩, respectively, as well as set difference, denoted by
\. Moreover, set-builder notation permits the definition of a set by
a prescribed property; for instance, the collection {x ∈ R | x2 < 2}
characterizes all real numbers whose square is less than two. The
concept of the power set, typically symbolized by P(A) for a set
A, encompasses all subsets of A. This precise notation not only
enhances clarity but also supports the subsequent formulation of
functions and other mathematical constructs.
Functions as Mappings Between Sets
A function is formally defined as a mapping that assigns each el-
ement of a domain to a unique element of a codomain. This rela-
tionship is denoted by f : A → B, where A is the domain, B is the
codomain, and the association is expressed by a 7→ f (a) for each
a ∈ A. The detailed structure of a function is characterized by
several key properties. A function is said to be injective if, for all
a1 , a2 ∈ A, the equality f (a1 ) = f (a2 ) implies that a1 = a2 . It is
surjective if every b ∈ B is the image of at least one element in A;
that is, for every b ∈ B, there exists an a ∈ A such that f (a) = b.
When a function is both injective and surjective, it qualifies as bi-
jective, ensuring the existence of an inverse function f −1 : B → A
defined by the relation f −1 (b) = a if and only if f (a) = b. The
abstraction of functions as mappings serves as a pivotal concept in
mathematics, underpinning numerous analytical developments and
facilitating a rigorous understanding of continuous, differentiable,
and other transformational behaviors within various mathematical
contexts.
Python Code Snippet
# This Python script demonstrates several fundamental concepts
,→ discussed in the chapter:
# 1. Properties of the Real Numbers including order properties,
,→ field operations,
# the Archimedean property, and completeness (supremum for finite
,→ sets).
15
# 2. Set Notation and various set operations.
# 3. Functions as mappings between sets with checks for injectivity
,→ and surjectivity,
# along with the computation of an inverse function.
# -------------------------
# 1. Real Numbers and Their Properties
# -------------------------
def add(a, b):
"""
Return the sum of two real numbers.
Demonstrating the field property of addition.
"""
return a + b
def multiply(a, b):
"""
Return the product of two real numbers.
Demonstrating the field property of multiplication.
"""
return a * b
def order_property(a, b, c):
"""
Demonstrate the order preserving property of addition:
If a < b then a + c < b + c.
"""
if a < b and (a + c) < (b + c):
return True
return False
def positive_product(a, b):
"""
Check the multiplicative ordering property:
If 0 < a and 0 < b, then 0 < a * b.
"""
if a > 0 and b > 0 and (a * b) > 0:
return True
return False
def archimedean_property(r):
"""
For any real number r, finds the smallest natural number n
,→ satisfying n > r.
This illustrates the Archimedean property of the real numbers.
"""
n = 1
while n <= r:
n += 1
return n
def supremum(S):
16
"""
Given a non-empty list S of real numbers assumed to be bounded
,→ above,
return the supremum of S.
For finite sets with a maximum element, the supremum equals the
,→ maximum.
"""
return max(S)
# -------------------------
# 2. Set Notation and Operations
# -------------------------
def even_integers(n):
"""
Return a set of the first n even integers.
Example: for n=5, returns {2, 4, 6, 8, 10}.
"""
return {2 * i for i in range(1, n + 1)}
def set_operations_example():
"""
Demonstrate basic set operations: union, intersection, and set
,→ difference.
With example sets A and B.
"""
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}
union_set = A | B # Union of A and B
intersection_set = A & B # Intersection of A and B
difference_set = A - B # Elements in A but not in B
return union_set, intersection_set, difference_set
# -------------------------
# 3. Functions as Mappings Between Sets
# -------------------------
def f(x):
"""
Define a simple linear function f: → given by f(x) = 2x + 3.
This function is bijective (one-to-one and onto) over .
"""
return 2 * x + 3
def f_inverse(y):
"""
Compute the inverse function of f.
Since f(x) = 2x + 3, the inverse function is f1(y) = (y - 3) /
,→ 2.
"""
return (y - 3) / 2
def is_injective(func, domain):
17
"""
Check if the function 'func' is injective on a given finite
,→ 'domain'.
Returns True if every element of the domain maps to a unique
,→ value.
"""
seen = {}
for x in domain:
value = func(x)
if value in seen:
return False
seen[value] = x
return True
def is_surjective(func, domain, codomain):
"""
Check if the function 'func' is surjective from a given finite
,→ 'domain'
to a finite 'codomain'. Surjectivity is verified when the set of
,→ images
equals the codomain.
"""
images = {func(x) for x in domain}
return images == codomain
# -------------------------
# Main Execution: Demonstrations
# -------------------------
if __name__ == "__main__":
# Demonstrate order property: if a < b then a + c < b + c.
a, b, c = 3, 5, 2
print("Order Property: For a = {}, b = {}, c = {}:".format(a, b,
,→ c))
print(" Check ({} < {} and {}+{} < {}+{}): {}".format(a, b, a,
,→ c, b, c, order_property(a, b, c)))
# Demonstrate multiplicative positivity:
a, b = 4, 7
print("\nPositive Product: For a = {} and b = {}:".format(a, b))
print(" Check (0 < {} and 0 < {} and 0 < {}*{}): {}".format(a,
,→ b, a, b, positive_product(a, b)))
# Archimedean property demonstration:
r = 10.5
n = archimedean_property(r)
print("\nArchimedean Property: For r = {}, smallest natural n >
,→ r is: {}".format(r, n))
# Supremum demonstration for a finite list S.
S = [x / 10 for x in range(1, 50)] # S is bounded above (max =
,→ 4.9)
print("\nSupremum: For S = [x/10 for x in range(1, 50)]:")
18
print(" Supremum of S is: {}".format(supremum(S)))
# Set operations demonstration:
union_set, intersection_set, difference_set =
,→ set_operations_example()
print("\nSet Operations:")
print(" Union of A and B: {}".format(union_set))
print(" Intersection of A and B: {}".format(intersection_set))
print(" Difference of A \\ B: {}".format(difference_set))
# Demonstrate functions as mappings:
domain = set(range(-10, 11)) # Domain: integers from -10 to 10
codomain = {f(x) for x in domain} # Codomain: images under f
print("\nFunction f Mapping:")
print(" Domain [-10, 10] mapped by f(x) = 2x + 3 gives:")
print(" Sorted images: {}".format(sorted(codomain)))
# Check if f is injective on the finite domain.
print("\nInjectivity Check:")
print(" f is injective on [-10,10]: {}".format(is_injective(f,
,→ domain)))
# Check if f is surjective onto its image.
print("\nSurjectivity Check:")
print(" f is surjective on [-10,10] to its image:
,→ {}".format(is_surjective(f, domain, codomain)))
# Demonstrate and test the inverse function f1.
test_value = 17
x_val = f_inverse(test_value)
print("\nInverse Function Test:")
print(" For f(x)=2x+3, f1({}) = {}".format(test_value, x_val))
print(" Verification: f(f1({})) = {} (should equal
,→ {})".format(test_value, f(x_val), test_value))
19
Chapter 2
The Geometry of
Graphs
The Cartesian Coordinate System
The Cartesian coordinate system provides a rigorous framework
for representing geometric objects in a two-dimensional setting. In
this system, each point in the plane is identified with an ordered
pair (x, y) where x and y belong to the set of real numbers R. The
horizontal line, commonly designated as the x-axis, and the verti-
cal line, known as the y-axis, intersect at the origin (0, 0). These
axes establish a reference that permits the definition of distance,
direction, and orientation in the plane. The coordinate system fa-
cilitates the translation between algebraic equations and geometric
figures, a correspondence that is central to the study of analyti-
cal geometry. The distance between any two points (x1 , y1 ) and
(x2 , y2 ) is determined by the Euclidean metric,
d = (x2 − x1 )2 + (y2 − y1 )2 ,
p
which is fundamental to proving and understanding further geo-
metrical properties.
Graphing Techniques
Constructing a graph meticulously involves an interplay between
algebraic manipulation and geometric visualization. Given a func-
20
tion f : R → R, the graph is the set
{(x, f (x)) | x ∈ R}.
Graphing a function requires the evaluation of f (x) at carefully cho-
sen values of x so as to delineate the behavior of the function over
selected intervals. The density of the chosen points, the scale of the
coordinate axes, and the resolution of the plotted curve collectively
determine the fidelity of the graphical representation. Attention
to the curvature of the function, the rate of change indicated by
the slope in local regions, and the behavior near critical points all
contribute to a thorough geometric analysis. The techniques of
graphing not only elucidate the overall shape of the function but
also permit the identification of local and global properties that
may not be immediately apparent from the algebraic form alone.
Intercepts
Intercepts are the points at which the graph of a function meets the
coordinate axes, providing critical insights into the function’s be-
havior. The y-intercept corresponds to the point where the graph
intersects the y-axis, which is obtained by evaluating the function
at x = 0; mathematically this is given by (0, f (0)). Conversely, the
x-intercepts are the points where the function attains a value of
zero, i.e., the set of points {(x, 0) | f (x) = 0}. The determination
of intercepts often requires solving algebraic equations, and these
points serve as anchors for the graph. They offer a first approxi-
mation to the behavior of the function in the vicinity of the axes
and are essential in decomposing more complex curves into easily
comprehensible segments.
Symmetry
The concept of symmetry in the context of graphs refers to the
invariance of the graph under certain geometric transformations.
A function f : R → R is classified as even if it satisfies
f (−x) = f (x),
for all x ∈ R, which geometrically corresponds to symmetry about
the y-axis. Such symmetry implies that for every point (x, f (x))
21
on the graph, the point (−x, f (x)) is also present. In contrast, a
function is deemed odd if it satisfies
f (−x) = −f (x),
for all x ∈ R; this property is associated with rotational symmetry
about the origin. The presence of symmetry simplifies the analy-
sis of a function by reducing the necessary domain for study and
often permits the use of symmetry arguments in proving further
properties. The formal exploration of symmetry in graphs thereby
bridges the disciplines of abstract algebra and geometric intuition.
Transformations of Functions
Transformations of functions describe the systematic alterations
applied to a basic function to yield modified graphs. These trans-
formations can be broadly classified into translations, scalings, re-
flections, and rotations. A horizontal translation is effected by
replacing the argument x with x − h, where h ∈ R denotes the
magnitude and direction of the shift. A vertical translation oc-
curs by the addition of a constant term k, resulting in the function
f (x)+k. Scaling transformations modify the function by stretching
or compressing the graph; a horizontal scaling involves the substi-
tution of x with x/c, while a vertical scaling multiplies f (x) by a
constant factor a. Reflections are generated by negating either the
independent or dependent variable, yielding graphs that are mirror
images of the original with respect to one of the axes. The general
form of a transformed function may be expressed succinctly as
x − h
g(x) = a f + k,
c
where the parameters a, h, c, and k govern the nature of each
transformation. The algebraic representation of these transforma-
tions provides a powerful mechanism for predicting and explaining
the resultant geometric configurations, establishing a clear corre-
spondence between algebraic modifications and geometric interpre-
tations.
Python Code Snippet
import numpy as np
import [Link] as plt
22
from scipy import optimize
def euclidean_distance(point1, point2):
"""
Compute the Euclidean distance between two points.
Parameters:
point1 (tuple): (x1, y1)
point2 (tuple): (x2, y2)
Returns:
float: Euclidean distance computed as
sqrt((x2 - x1)^2 + (y2 - y1)^2)
"""
x1, y1 = point1
x2, y2 = point2
return [Link]((x2 - x1)**2 + (y2 - y1)**2)
def f(x):
"""
Example function f(x) = x^2 - 4.
Parameters:
x (float or ndarray): Input value(s).
Returns:
float or ndarray: f(x)
"""
return x**2 - 4
def graph_function(func, x_range=(-10, 10), num_points=400,
,→ title="Graph of the Function"):
"""
Plot the graph of a given function in the Cartesian coordinate
,→ system.
Parameters:
func (callable): The function to plot.
x_range (tuple): Range for x-axis as (min, max).
num_points (int): Number of points in the plot.
title (str): Title of the plot.
"""
x = [Link](x_range[0], x_range[1], num_points)
y = func(x)
[Link](figsize=(8, 6))
[Link](x, y, label=r'$f(x)$')
# Drawing the coordinate axes.
[Link](0, color='black', linewidth=0.5)
[Link](0, color='black', linewidth=0.5)
[Link](title)
[Link]("x")
[Link]("f(x)")
23
[Link]()
[Link](True)
[Link]()
def y_intercept(func):
"""
Compute the y-intercept of the function by evaluating f(0).
Parameters:
func (callable): Function for which intercept is computed.
Returns:
tuple: (0, f(0))
"""
return (0, func(0))
def find_x_intercepts(func, x_range=(-10, 10), num_points=1000):
"""
Find approximate x-intercepts of the function by detecting sign
,→ changes.
Parameters:
func (callable): Function f(x) for which x-intercepts are
,→ calculated.
x_range (tuple): Range to search for intercepts.
num_points (int): Number of points used for initial
,→ scanning.
Returns:
list: List of x-intercepts where f(x) = 0.
"""
x_values = [Link](x_range[0], x_range[1], num_points)
intercepts = []
for i in range(len(x_values) - 1):
if func(x_values[i]) * func(x_values[i+1]) < 0:
# Use Brent's method to find a root in the interval.
root = [Link](func, x_values[i], x_values[i+1])
[Link](root)
return intercepts
def is_even(func, test_points=100, x_range=(0, 10)):
"""
Check whether a function is even, i.e., f(x) = f(-x).
Parameters:
func (callable): Function to test.
test_points (int): Number of test points.
x_range (tuple): Range of x values where the test is
,→ performed.
Returns:
bool: True if the function is even, else False.
"""
24
x = [Link](x_range[0], x_range[1], test_points)
return [Link](func(x), func(-x))
def is_odd(func, test_points=100, x_range=(0, 10)):
"""
Check whether a function is odd, i.e., f(x) = -f(-x).
Parameters:
func (callable): Function to test.
test_points (int): Number of test points.
x_range (tuple): Range of x values where the test is
,→ performed.
Returns:
bool: True if the function is odd, else False.
"""
x = [Link](x_range[0], x_range[1], test_points)
return [Link](func(x), -func(-x))
def transformed_function(x, a=1, h=0, c=1, k=0, func=f):
"""
Generate a transformed version of the function using the
,→ transformation:
g(x) = a * f((x - h)/c) + k
Parameters:
x (float or ndarray): Independent variable.
a (float): Vertical scaling factor.
h (float): Horizontal translation.
c (float): Horizontal scaling factor.
k (float): Vertical translation.
func (callable): Original function f.
Returns:
float or ndarray: Transformed function value.
"""
return a * func((x - h) / c) + k
if __name__ == '__main__':
# Compute and display Euclidean distance between two points.
p1 = (1, 2)
p2 = (4, 6)
distance = euclidean_distance(p1, p2)
print("Euclidean Distance between", p1, "and", p2, "is
,→ {:.2f}".format(distance))
# Graph the example function f(x) = x^2 - 4.
print("Graphing the function f(x) = x^2 - 4")
graph_function(f, x_range=(-5, 5), title=r'Graph of
,→ $f(x)=x^2-4$')
# Calculate and display the intercepts.
25
print("Calculating intercepts for f(x) = x^2 - 4")
y_int = y_intercept(f)
x_ints = find_x_intercepts(f, x_range=(-5, 5))
print("Y-intercept:", y_int)
print("X-intercepts:", x_ints)
# Check and display whether the function is even or odd.
even_status = is_even(f)
odd_status = is_odd(f)
print("Is f(x) even? ", even_status)
print("Is f(x) odd? ", odd_status)
# Define parameters for a transformed function: g(x) = 2 *
,→ f((x-1)/2) + 3.
a, h, c, k = 2, 1, 2, 3
def g(x):
return transformed_function(x, a, h, c, k, func=f)
# Graph the transformed function.
print("Graphing the transformed function g(x) = 2 * f((x-1)/2) +
,→ 3")
graph_function(g, x_range=(-5, 10), title=r'Graph of
,→ $g(x)=2\,f\Bigl(\frac{x-1}{2}\Bigr)+3$')
26
Chapter 3
Limits and Their
Properties
The Concept of a Limit
The notion of a limit occupies a central position in mathematical
analysis, serving as the bridge between algebraic formulations and
the behavior of functions in the infinitesimal vicinity of a given
point. For a function f : R → R and a point a ∈ R, the expression
lim f (x) = L
x→a
is employed to indicate that as the variable x approaches the value
a, the function values f (x) approach the real number L. This con-
cept captures the idea of approaching without necessarily attaining,
and it may yield a finite limit L even in circumstances under which
f is not defined at a. The rigor of this formulation ensures that
properties and subsequent operations on limits can be consistently
and reliably derived.
1 Epsilon-Delta Definition
A rigorous formulation of the limit is provided by the epsilon-delta
definition. The function f (x) is said to have the limit L as x
approaches a, that is,
lim f (x) = L,
x→a
27
if and only if for every ϵ > 0 there exists a corresponding δ > 0
such that whenever
0 < |x − a| < δ,
the inequality
|f (x) − L| < ϵ
holds true. This definition encapsulates the idea that the values
of f (x) can be made arbitrarily close to L by restricting x to lie
within an appropriately small punctured neighborhood about a.
The quantifiers in the definition, namely, “for every ϵ > 0” and
“there exists a δ > 0,” establish a precise framework to capture the
intuitive notion of approaching a limit.
Limit Laws and Algebraic Properties
Once the existence of limits has been precisely defined, a collection
of algebraic properties, often referred to as the limit laws, facili-
tates the computation of limits in a systematic way. Under the
assumption that the relevant limits exist, these properties may be
stated as follows:
1 Linearity and Constant Multiplication
If f and g are functions such that limx→a f (x) = L and limx→a g(x) =
M , then the sum rule asserts that
lim f (x) + g(x) = L + M.
x→a
Furthermore, for any constant c ∈ R, the constant multiple law
guarantees that
lim c f (x) = c L.
x→a
2 Products, Quotients, and Powers
The product law allows the evaluation of limits of products of func-
tions:
lim f (x)g(x) = LM.
x→a
In the case of quotients, provided that M ̸= 0, one obtains
f (x) L
lim = .
x→a g(x) M
28
In addition, when n ∈ N, the power law implies that
n n
lim f (x) = L .
x→a
These laws simplify the evaluation of limits by reducing complex ex-
pressions to combinations of simpler limits that are already known
or easier to compute.
Applications of the Concept of Approach-
ing Values
The intrinsic value of limits lies in their ability to describe the
behavior of functions arbitrarily close to a specified point. Even in
cases where f (a) is undefined or does not coincide with the limit,
the surrounding behavior of the function is captured entirely by
the limit. This local behavior is of particular importance in the
study of continuity, differentiability, and integration.
1 One-Sided Limits
In many contexts it is advantageous to consider one-sided limits,
which explore the behavior of the function as the variable ap-
proaches a exclusively from values greater than or less than a.
These are denoted by
lim+ f (x)
x→a
and
lim f (x),
x→a−
respectively. A two-sided limit limx→a f (x) is said to exist if, and
only if, both one-sided limits exist and are equal. The distinc-
tion between left-hand and right-hand approaches is particularly
relevant in the analysis of functions with discontinuities or abrupt
changes in behavior.
2 Limits of Functions Approaching Infinity
In addition to limits at finite points, the behavior of a function as
the independent variable grows without bound is characterized by
limits at infinity. For instance, the notation
lim f (x) = L
x→∞
29
asserts that for every ϵ > 0 there exists a real number M such that
|f (x) − L| < ϵ for all x > M . This concept formalizes the idea that
a function may settle into an asymptotic behavior as its argument
increases indefinitely.
The techniques and properties discussed in this chapter pro-
vide the foundational framework necessary for subsequent manip-
ulations and analyses in the broader context of analysis. Each
law and definition is formulated to ensure compatibility with the
rigorous standards of modern mathematical discourse, enabling a
precise treatment of approaching values and the subtleties inherent
in their behavior.
Python Code Snippet
import sympy as sp
import numpy as np
# Define the symbol
x = [Link]('x')
# -----------------------------
# Example 1: Computing Limits Symbolically
# -----------------------------
# (a) Limit of sin(x)/x as x -> 0 using Sympy
f1 = [Link](x) / x
limit_f1 = [Link](f1, x, 0)
print("Limit of sin(x)/x as x -> 0:", limit_f1)
# (b) Limit of (x^2 - 1)/(x - 1) as x -> 1
f2 = (x**2 - 1) / (x - 1)
limit_f2 = [Link](f2, x, 1)
print("Limit of (x^2 - 1)/(x-1) as x -> 1:", limit_f2)
# -----------------------------
# Example 2: One-Sided Limits
# -----------------------------
# Limit of 1/x as x -> 0 from the right and left
f3 = 1 / x
limit_f3_right = [Link](f3, x, 0, dir='+')
limit_f3_left = [Link](f3, x, 0, dir='-')
print("Limit of 1/x as x -> 0^+:", limit_f3_right)
print("Limit of 1/x as x -> 0^-:", limit_f3_left)
# -----------------------------
# Example 3: Limit at Infinity
# -----------------------------
30
# Limit of 3 - 5/x as x -> infinity
f4 = 3 - 5/x
limit_f4 = [Link](f4, x, [Link])
print("Limit of 3 - 5/x as x -> infinity:", limit_f4)
# -----------------------------
# Example 4: Verification of Limit Laws
# -----------------------------
# Let f(x) = x + 2 and g(x) = 2*x**2.
# According to the sum law:
# lim (f(x) + g(x)) = lim f(x) + lim g(x) as x -> 3.
f = x + 2
g = 2 * x**2
limit_sum = [Link](f + g, x, 3)
print("Limit of (x+2) + 2*x^2 as x -> 3:", limit_sum)
# -----------------------------
# Example 5: Epsilon-Delta Verification (Numerical Approximation)
# -----------------------------
def check_epsilon_delta(f_func, a, L, epsilon, delta,
,→ num_points=1000):
"""
Check if for all x in (a-delta, a+delta) (excluding a),
the inequality |f(x) - L| < epsilon holds.
Parameters:
f_func : A Python function representing f(x).
a : The point at which limit is taken.
L : The proposed limit value.
epsilon : The tolerance in the range of f(x) values.
delta : The candidate delta value.
num_points : Number of sample points to test in the interval.
Returns:
True if the condition holds for all sampled points; otherwise,
,→ False.
"""
# Generate num_points uniformly in the interval (a-delta,
,→ a+delta)
xs = [Link](a - delta, a + delta, num_points)
# Exclude the point x = a to avoid potential singularities
xs = xs[[Link](xs - a) > 1e-12]
# Check if |f(x) - L| < epsilon for all x in the sample
differences = [Link](f_func(xs) - L)
return [Link](differences < epsilon)
def find_delta(f_func, a, L, epsilon, initial_delta=1.0, factor=0.9,
,→ num_points=1000):
"""
31
Iteratively search for a delta such that for all x with 0 <
,→ |x-a| < delta,
the inequality |f(x) - L| < epsilon holds.
Parameters:
f_func : The Python function representing f(x).
a : The point at which the limit is taken.
L : The limit value.
epsilon : The given tolerance for the epsilon-delta
,→ definition.
initial_delta: The starting candidate value for delta.
factor : Multiplicative factor to decrease delta if
,→ condition fails.
num_points : Number of points sampled in each iteration.
Returns:
A delta value satisfying the condition, or None if not found.
"""
delta = initial_delta
while delta > 1e-12: # Lower bound to avoid infinite loop
if check_epsilon_delta(f_func, a, L, epsilon, delta,
,→ num_points):
return delta
delta *= factor # Reduce delta if condition is not met
return None
# Define a sample function, for example f(x) = x^2.
# We know that lim (x^2) as x -> 2 is 4.
f_lambda = lambda x: x**2
a_value = 2.0
L_value = 4.0
epsilon_value = 0.1
delta_found = find_delta(f_lambda, a_value, L_value, epsilon_value)
if delta_found is not None:
print(f"For f(x)=x^2 at a={a_value} with limit L={L_value} and
,→ epsilon={epsilon_value},")
print(f"a delta = {delta_found:.5f} satisfies the epsilon-delta
,→ condition.")
else:
print("Could not find a suitable delta for the epsilon-delta
,→ condition.")
# End of Python code snippet demonstrating key equations and
,→ algorithms from the chapter.
32
Chapter 4
Techniques for
Evaluating Limits
Factoring and Simplification Techniques
In many cases the direct substitution of a value into a function
produces an expression of the form 0/0, which is classified as an
indeterminate form. A classical method for resolving such indeter-
minacies involves the algebraic technique of factoring. Consider,
for example, a rational expression such as
x2 − c2
,
x−c
where the numerator factors as (x − c)(x + c) by application of
the difference of squares. The cancellation of the common factor
(x − c), justified by the fact that the limit concerns values of x in a
punctured neighborhood of c, yields an equivalent expression that
is amenable to direct evaluation. Such algebraic manipulations not
only simplify the expression but also reveal an inherent structure
in the function, enabling the subsequent application of limit laws.
It is crucial to appreciate that the process of cancellation is per-
formed under the understanding that no alteration to the intrinsic
behavior of the function occurs in the limit process. The algebraic
simplification thus obtained preserves the essential characteristics
of the function in the vicinity of the point of indeterminacy.
33
Rationalization Techniques
An alternative method particularly suited to the evaluation of lim-
its involving radical expressions is rationalization. This technique
employs the multiplication of the numerator and the denominator
by an appropriately chosen conjugate. In expressions such as
√ √
x+h− x
,
h
multiplication by the conjugate leads to the transformation
√ √ √ √
( x + h − x)( x + h + x) (x + h) − x
√ √ = √ √ ,
h ( x + h + x) h ( x + h + x)
which simplifies to
1
√ √ .
x+h+ x
This procedure eliminates the obfuscating presence of radicals in
the numerator, thereby reducing an indeterminate form to one in
which the limit may be calculated by direct substitution. The
careful execution of rationalization not only ensures the elimination
of problematic terms but also adheres strictly to the underlying
algebraic structure, supporting the rigorous determination of the
limit.
Handling Indeterminate Forms
In the setting of real analysis it is not uncommon to encounter lim-
its that, upon substitution, yield expressions such as 0/0 or ∞/∞.
These indeterminate forms necessitate a deeper analytical insight,
typically achieved by employing a combination of the aforemen-
tioned techniques. For a function whose numerator and denomi-
nator simultaneously tend to zero, factoring or rationalization may
expose common terms that can be cancelled, thereby resolving the
indeterminacy.
In further instances, the interplay of multiple indeterminate be-
haviours within a single expression calls for a sequential application
of algebraic transformations. For example, suppose an expression
requires both the extraction of a common factor and the elimina-
tion of a radical component before the limit can be evaluated. In
34
such instances the algebraic procedures must be applied in a logi-
cally consistent order such that each transformation reinforces the
validity of the subsequent one. The cancellation of terms is carried
out with the acute understanding that the variable under consid-
eration is constrained to a domain excluding the point at which it
attains an indeterminate value.
Moreover, the apparatus of limit evaluation extends beyond
these operational techniques to incorporate a meticulous analysis of
asymptotic behaviors. By identifying dominant terms and execut-
ing analytic expansions where necessary, one arrives at expressions
whose limits are readily determined through standard substitution.
The rigorous application of these methods reflects a commitment
to both the precision of mathematical reasoning and the elegance
of algebraic manipulation.
In summary, the techniques of factoring, rationalization, and
the systematic resolution of indeterminate forms serve as robust
tools in the evaluation of limits. These methods transform complex
expressions into simplified forms that reveal the true behavior of
functions in the infinitesimal neighborhood around critical points,
aligning the intuitive aspects of limit evaluation with the stringent
requirements of mathematical rigor.
Python Code Snippet
import sympy
from sympy import symbols, limit, sqrt, simplify, cos
# Define symbols for the variables
x, c, h = symbols('x c h')
# Example 1: Factoring and Simplification Techniques
# Evaluate the expression: (x^2 - c^2) / (x - c)
expr1 = (x**2 - c**2) / (x - c)
simpl_expr1 = simplify(expr1)
print("Simplified expression 1:", simpl_expr1)
# The limit as x approaches c resolves the 0/0 indeterminate form:
result1 = limit(expr1, x, c)
print("Limit of expression 1 as x approaches c:", result1)
# Example 2: Rationalization Techniques
# Evaluate the expression: (sqrt(x+h) - sqrt(x)) / h, which
,→ represents
# the derivative of sqrt(x) in the limit as h -> 0.
expr2 = (sqrt(x+h) - sqrt(x)) / h
simpl_expr2 = simplify(expr2)
35
print("Simplified expression 2 after rationalization:", simpl_expr2)
# Compute the limit as h approaches 0:
result2 = limit(expr2, h, 0)
print("Limit of expression 2 as h approaches 0:", result2)
# Example 3: Handling Indeterminate Forms via Direct Differentiation
# Evaluate the expression: ((x + h)**2 - x**2) / h, a standard
,→ difference quotient
# representing the derivative of x^2.
expr3 = ((x + h)**2 - x**2) / h
simpl_expr3 = simplify(expr3)
print("Simplified expression 3:", simpl_expr3)
result3 = limit(expr3, h, 0)
print("Limit of expression 3 as h approaches 0:", result3)
# Example 4: Application of L'Hopital's Rule
# Consider the expression: (1 - cos(h)) / h**2, which is 0/0 when h
,→ -> 0.
expr4 = (1 - cos(h)) / h**2
simpl_expr4 = simplify(expr4)
print("Simplified expression 4:", simpl_expr4)
result4 = limit(expr4, h, 0)
print("Limit of expression 4 as h approaches 0:", result4)
36
Chapter 5
Continuity of Functions
Continuity at a Point
Let f : D → R be a function defined on a subset D of the real
numbers. The function f is said to be continuous at a point c ∈ D
if, for every ϵ > 0, there exists a δ > 0 such that for all x ∈ D
satisfying
|x − c| < δ,
the inequality
|f (x) − f (c)| < ϵ
holds. This definition encapsulates the idea that arbitrarily small
perturbations in the argument x result in correspondingly small
variations in the value of the function. In formal terms, continuity
at the point c is expressed as
∀ϵ > 0, ∃δ > 0 such that ∀x ∈ D, |x−c| < δ =⇒ |f (x)−f (c)| < ϵ.
The criterion is designed to capture the local behavior of the func-
tion in the vicinity of the point c, ensuring that the function does
not exhibit any abrupt changes in value near that point. The de-
pendence of δ on both ϵ and the specific point c underscores the
inherently local nature of this definition.
Continuity on Intervals
A function f : I → R is said to be continuous on an interval I ⊆ R
if it is continuous at every point c ∈ I. That is, for each c ∈ I and
37
for every ϵ > 0, one can find a corresponding δ = δ(c, ϵ) > 0 such
that
|x − c| < δ and x ∈ I =⇒ |f (x) − f (c)| < ϵ.
This pointwise definition, when extended over an entire interval, en-
sures that the function maintains a uniform behavior with respect
to small local changes throughout the interval. In instances where
the interval is closed or half-open, particular attention must be
given to the behavior at the endpoints, where the δ-neighborhoods
are appropriately restricted to lie within the interval I.
Intrinsic Properties and Behaviors of Con-
tinuous Functions
Continuous functions inherently exhibit a number of properties
that are fundamental to real analysis. One of the most signifi-
cant of these is the Intermediate Value Property. If f is continuous
on a closed interval [a, b], then for any value y between f (a) and
f (b), there exists at least one point c ∈ [a, b] for which
f (c) = y.
Symbolically, if
f (a) ≤ y ≤ f (b) or f (b) ≤ y ≤ f (a),
then
∃c ∈ [a, b] such that f (c) = y.
This theorem follows from the fact that continuous functions map
connected sets to connected sets, and hence the image of an interval
under a continuous function remains an interval.
Another salient property is that of compositional continuity. If
f is continuous at a point c and g is continuous at f (c), then the
composite function g ◦ f is continuous at c, which is expressed as
lim g(f (x)) = g lim f (x) .
x→c x→c
Such properties ensure that the operation of function composition
preserves the continuity structure, thereby enabling the construc-
tion of complex continuous functions from simpler components.
38
Furthermore, when functions are defined on compact sets, an
enhanced form of continuity, known as uniform continuity, is au-
tomatically guaranteed. Specifically, if the function f : [a, b] → R
is continuous on the compact interval [a, b], then for every ϵ > 0,
there exists a δ > 0 that is independent of the choice of point in
the interval and for which
∀x, y ∈ [a, b], |x − y| < δ =⇒ |f (x) − f (y)| < ϵ.
This removal of dependence on the point of consideration distin-
guishes uniform continuity from pointwise continuity and provides
a stronger guarantee on the behavior of the function over the entire
interval.
Classification and Analysis of Discontinu-
ities
Although continuous functions are characterized by the absence of
abrupt changes in behavior, it is instructive to examine the nature
of points where continuity fails. For a function f : D → R, a point
c ∈ D is a point of discontinuity if the limit
lim f (x)
x→c
either does not exist or exists but does not equal f (c). Such dis-
continuities can be classified into several distinct types.
A removable discontinuity occurs when the limit
lim f (x)
x→c
exists, yet it is either not equal to f (c) or f (c) is not defined. In
these cases, the function can be redefined at c without affecting
its behavior in any other region of the domain, thereby restoring
continuity. In contrast, a jump discontinuity is characterized by
the existence of distinct one-sided limits, namely,
lim f (x) and lim f (x),
x→c− x→c+
with the inequality
lim f (x) ̸= lim+ f (x).
x→c− x→c
39
Finally, discontinuities that are not amenable to such redefinition or
that are associated with divergence of one-sided limits are termed
essential discontinuities. These classifications provide a refined un-
derstanding of the structural nuances in functions that fail to be
continuous at certain points and offer avenues for remedial or an-
alytical adjustments where possible.
Python Code Snippet
import numpy as np
import [Link] as plt
import math
def is_continuous_at(f, c, delta=1e-6, epsilon=1e-6,
,→ num_samples=100):
"""
Approximate check for continuity of f at the point c using the
,→ epsilon-delta definition.
Parameters:
f (callable): The function f: R -> R to test.
c (float): The point at which continuity is tested.
delta (float): The radius of the neighborhood around c.
epsilon (float): The tolerance for changes in f.
num_samples (int): Number of equally spaced points in (c -
,→ delta, c + delta) for sampling.
Returns:
bool: True if |f(x) - f(c)| < epsilon for all sampled x in
,→ (c - delta, c + delta), else False.
Note:
This is a numerical approximation since the rigorous
,→ epsilon-delta definition requires
quantification over all x in the neighborhood.
"""
try:
f_c = f(c)
except Exception as e:
print(f"f({c}) is not defined: {e}")
return False
# Create num_samples points in the interval (c-delta, c+delta)
x_samples = [Link](c - delta, c + delta, num_samples)
for x in x_samples:
try:
if abs(f(x) - f_c) >= epsilon:
return False
except Exception as e:
40
return False
return True
def bisection_method(f, a, b, tol=1e-6, max_iter=100):
"""
Uses the bisection method to find a root of the function f in
,→ the interval [a, b].
This method relies on the Intermediate Value Theorem, which
,→ guarantees that if f is continuous
on [a, b] and f(a)*f(b) < 0, then there exists at least one root
,→ in (a, b).
Parameters:
f (callable): The continuous function for which the root is
,→ to be found.
a, b (float): The endpoints of the interval [a, b].
tol (float): The tolerance for the width of the interval.
max_iter (int): Maximum number of iterations.
Returns:
float: An approximation of the root.
Raises:
ValueError: If f(a) and f(b) do not have opposite signs.
"""
if f(a) * f(b) >= 0:
raise ValueError("f(a) and f(b) must have opposite signs for
,→ the bisection method to work.")
for i in range(max_iter):
c = (a + b) / 2.0
if (b - a) / 2.0 < tol:
return c
if abs(f(c)) < tol:
return c
if f(a) * f(c) < 0:
b = c
else:
a = c
return c
def compose_functions(f, g):
"""
Returns the composite function g(f(x)).
Parameters:
f (callable): The inner function.
g (callable): The outer function.
Returns:
callable: A function h(x) such that h(x) = g(f(x)).
"""
return lambda x: g(f(x))
41
def uniform_continuity_check(f, interval, num_points=1000,
,→ epsilon=1e-3):
"""
Approximate check for uniform continuity of a function f on a
,→ closed interval.
Uniform continuity means that a single delta works for every x
,→ in the interval for a given epsilon.
Since exhaustive checking is impossible numerically, consecutive
,→ sample points are used.
Parameters:
f (callable): The function f: R -> R.
interval (tuple): A tuple (a, b) representing the interval
,→ [a, b].
num_points (int): The number of sample points.
epsilon (float): The tolerance for change in f.
Returns:
bool: True if the maximum difference between function values
,→ for close sample points
is less than epsilon, suggesting uniform continuity.
"""
a, b = interval
x_vals = [Link](a, b, num_points)
f_vals = [Link]([f(x) for x in x_vals])
# Use differences of neighboring points as an approximation
diff_f = [Link]([Link](f_vals))
if [Link](diff_f) < epsilon:
return True
return False
# Example functions:
def continuous_function(x):
"""
A simple continuous function f(x) = x^2.
"""
return x ** 2
def discontinuous_function(x):
"""
A function with a potential jump discontinuity:
f(x) = { -x if x < 0, x if x >= 0 }.
"""
if x < 0:
return -x
else:
return x
def f_ivt(x):
"""
42
A continuous function on [-2, 2] designed for the Intermediate
,→ Value Theorem.
Example: f(x) = x^3 - x - 2, which has a real root.
"""
return x ** 3 - x - 2
if __name__ == "__main__":
# Check continuity at several points
check_points = [1.0, 0.0, -1.0]
print("Continuity Check for continuous_function (f(x)=x^2):")
for pt in check_points:
result = is_continuous_at(continuous_function, pt)
print(f" f is continuous at {pt}: {result}")
print("\nContinuity Check for discontinuous_function at critical
,→ point 0:")
result = is_continuous_at(discontinuous_function, 0)
print(f" discontinuous_function is continuous at 0: {result}")
# Demonstrate the bisection method using f_ivt on the interval
,→ [1, 2]
try:
root = bisection_method(f_ivt, 1, 2)
print("\nBisection Method:")
print(f" Approximate root of f_ivt in [1, 2]: {root}")
except ValueError as e:
print(e)
# Show composite function example: h(x) = sin(x^2)
h = compose_functions(continuous_function, [Link])
x_val = 2.0
print("\nComposite Function (g o f) where g(x)=sin(x) and
,→ f(x)=x^2:")
print(f" h({x_val}) = sin(({x_val})^2) = {h(x_val)}")
# Check for uniform continuity of continuous_function on [0, 1]
u_cont = uniform_continuity_check(continuous_function, (0, 1))
print("\nUniform Continuity Check for f(x)=x^2 on [0, 1]:")
print(f" f is uniformly continuous on [0, 1]: {u_cont}")
# Plot the continuous function with an annotated point to
,→ illustrate continuity
x_plot = [Link](-2, 2, 400)
y_plot = continuous_function(x_plot)
[Link](figsize=(8, 4))
[Link](x_plot, y_plot, label="f(x) = x^2")
[Link]([1], [continuous_function(1)], color="red",
,→ zorder=5, label="Point (1, f(1))")
[Link]("Plot of f(x) = x^2")
[Link]("x")
[Link]("f(x)")
[Link]()
[Link](True)
43
[Link]()
44
Chapter 6
Intermediate Value
Theorem and
Applications
Statement and Formal Framework
Let f : [a, b] → R be a function that is continuous on the closed
interval [a, b]. The Intermediate Value Theorem (IVT) asserts that
if L is any real number satisfying
f (a) ≤ L ≤ f (b) or f (b) ≤ L ≤ f (a),
then there exists at least one point c ∈ [a, b] such that
f (c) = L.
This statement encapsulates the essence of continuity, namely that
the image of a continuous function on a closed interval is itself an
interval. In effect, the theorem guarantees that no values between
f (a) and f (b) are "skipped" as one moves from one endpoint to the
other.
Proof Utilizing Completeness of the Real
Numbers
The IVT is fundamentally rooted in the completeness property of
the real numbers. Consider, without loss of generality, the case
45
where f (a) < L < f (b). Define the set
S = {x ∈ [a, b] | f (x) ≤ L}.
Since a ∈ S and S is bounded above by b, the least upper bound
c = sup S exists by the completeness axiom. Continuity of f at c
implies that
lim f (x) = f (c).
x→c
By the construction of S, values of f (x) for x approaching c from
the left satisfy f (x) ≤ L, while values for x approaching c from
the right are such that f (x) ≥ L. An application of the limit
laws, combined with the properties of the supremum, yields the
equality f (c) = L. This argument rigorously demonstrates the
existence of a point c in the interval at which the function attains
the intermediate value L.
Existence of Solutions via the Intermedi-
ate Value Theorem
One of the most prominent applications of the IVT is in establishing
the existence of roots of equations. Consider an equation of the
form
f (x) = 0,
where f is continuous on [a, b]. If it is verified that
f (a) < 0 and f (b) > 0 or f (a) > 0 and f (b) < 0,
then it follows immediately that f (a) and f (b) straddle 0. By the
IVT, there exists a point c ∈ [a, b] for which
f (c) = 0.
This result is not merely of theoretical interest; it is instrumental in
numerical methods such as the bisection method, where repeated
application of the IVT refines the interval within which a solu-
tion must lie. The theorem thus provides a foundational tool to
guarantee the existence of solutions under appropriate continuity
conditions.
46
Analysis of Function Behavior through the
IVT
Beyond its utility in root-finding, the Intermediate Value Theorem
offers significant insight into the overall behavior of a function.
When a function is continuous over an interval, its image cannot
consist of disjoint subsets of R; the range is necessarily an interval.
This feature is pivotal in the qualitative study of functions and
aids in identifying intervals where the function may be monotonic
or exhibit changes in trend.
To illustrate, suppose that f is continuous on [a, b] and that
f (a) and f (b) are known. Then for any L that falls between these
two values, the theorem guarantees the existence of a correspond-
ing c such that f (c) = L. Such an insight not only confirms that
solutions to equations exist but also furnishes constraints which
are leveraged when constructing more refined models or when per-
forming sensitivity analyses.
Moreover, the IVT provides a rigorous explanation for phenom-
ena observed in practical applications where physical quantities
cannot jump discontinuously without violating underlying conser-
vation or continuity principles. Whether investigating phase tran-
sitions in thermodynamics or ensuring stability in control systems,
the assurance that intermediate values are attained is indispens-
able.
The breadth and depth of the Intermediate Value Theorem ren-
der it a cornerstone of real analysis. Its reliance on continuity and
the completeness of the real numbers solidifies the logical frame-
work upon which many further theoretical and applied investiga-
tions are built.
Python Code Snippet
import math
def f(x):
"""
Defines the continuous function f(x) = x^3 - x - 2.
This function is used to illustrate the Intermediate Value
,→ Theorem (IVT).
It satisfies:
f(1) = 1^3 - 1 - 2 = -2,
47
f(2) = 2^3 - 2 - 2 = 4,
thereby ensuring that there is at least one value c in [1,2] for
,→ which f(c) = 0.
"""
return x**3 - x - 2
def bisection_method(func, a, b, tol=1e-6, max_iter=100):
"""
Uses the bisection method to numerically find a root of the
,→ equation func(x) = 0,
thereby demonstrating the application of the Intermediate Value
,→ Theorem.
Parameters:
func : The continuous function for which we seek a root.
a, b : The endpoints of the interval [a, b] where func(a)
,→ and func(b) have opposite signs.
tol : The tolerance criterion for convergence (the
,→ interval length is reduced until half the interval is
,→ lower than tol).
max_iter : Maximum number of iterations allowed.
Returns:
The approximate root c such that func(c) is nearly zero.
Raises:
ValueError: If func(a) and func(b) do not have opposite signs.
"""
# Ensure that a root exists within [a, b] by checking that
,→ func(a) and func(b) have opposite signs.
if func(a) * func(b) >= 0:
raise ValueError("Function must have opposite signs at the
,→ endpoints a and b.")
iter_count = 0
c = a # initial midpoint (will be updated)
# Continue iterating until the desired tolerance or maximum
,→ iterations is reached.
while (b - a) / 2.0 > tol and iter_count < max_iter:
c = (a + b) / 2.0 # Calculate the midpoint of the interval
fc = func(c)
print(f"Iteration {iter_count}: a = {a:.6f}, b = {b:.6f}, c
,→ = {c:.6f}, f(c) = {fc:.6f}")
# If the function value at the midpoint is sufficiently
,→ close to zero, return c as the root.
if abs(fc) < tol:
break
# Determine the subinterval that contains the root based on
,→ the Intermediate Value Theorem.
48
if func(a) * fc < 0:
b = c
else:
a = c
iter_count += 1
return c
def main():
"""
The main function demonstrates the application of the
,→ Intermediate Value Theorem
by using the bisection method to find a root of the equation
,→ f(x)=0.
For the function f(x) = x^3 - x - 2,
f(1) = -2 and f(2) = 4.
This guarantees, by the IVT, the existence of a point c in [1,
,→ 2] where f(c)=0.
"""
a = 1.0
b = 2.0
try:
root = bisection_method(f, a, b)
print(f"\nApproximate root found: x = {root:.7f} where f(x)
,→ = {f(root):.7f}")
except ValueError as e:
print("Error:", e)
if __name__ == "__main__":
main()
49
Chapter 7
The Derivative:
Concept and Definition
Definition and Notational Conventions
Let f : I → R be a function defined on an interval I ⊂ R. The
derivative of f at a point x ∈ I, when it exists, is defined by
f (x + h) − f (x)
f ′ (x) = lim ,
h→0 h
provided the limit exists. This limit is known as the difference
quotient in the infinitesimal limit and embodies the notion of the
instantaneous rate of change of the function at the point x. Alter-
native notations such as dxdf
(x) or dx
d
f (x) are also employed inter-
changeably to denote the derivative. The definition is not merely
symbolic but serves as a rigorous formulation that encapsulates the
local linear approximation of the function f .
Analytical Framework of the Difference
Quotient
The expression
f (x + h) − f (x)
h
represents the average rate of change of f over the interval from x to
x + h. As h approaches zero, this average rate of change converges
50
to a unique value, provided the limit exists, which is then defined
as the derivative f ′ (x). The rigor of this limiting process can be
established within an ϵ-δ framework. Specifically, for any given
ϵ > 0, there exists a corresponding δ > 0 such that
f (x + h) − f (x)
− f ′ (x) < ϵ,
h
whenever 0 < |h| < δ. This precise formulation ensures that the
derivative is a robust measure of the local behavior of f , capturing
the exact manner in which an infinitesimal increment in the input
produces a change in the function value. The analysis of such limits
is instrumental in connecting the discrete notion of average change
with the continuous behavior observed at an infinitesimal scale.
Geometric Interpretation and the Tan-
gent Line
Geometrically, the derivative at the point x corresponds to the
slope of the tangent line to the graph of f at the point (x, f (x)).
Consider the secant line determined by two distinct points (x, f (x))
and (x + h, f (x + h)); the slope of this secant line is given by
f (x+h)−f (x)
h . As h tends to zero, the secant line converges to the
tangent line, and its slope approaches f ′ (x). In this sense, the
tangent line provides the best linear approximation of the function
near the point x, and its equation may be expressed as
y = f (x) + f ′ (x)(t − x),
where t denotes a variable in the domain of f . This geometric view-
point reinforces the interpretation of the derivative as a measure of
instantaneous change and offers a visual insight into the behavior
of functions around a given point. The convergence of secant slopes
to the tangent slope is a fundamental concept that links the alge-
braic limit definition to its geometric counterpart, thereby unifying
the analytical and visual perspectives of differential calculus.
Python Code Snippet
import numpy as np
import [Link] as plt
51
import sympy as sp
# Define the sample function f(x)
def f(x):
return x**3 - 2*x + 1
# Derivative approximation using the limit definition (forward
,→ difference)
def derivative_limit(f, x, h=1e-7):
return (f(x + h) - f(x)) / h
# Derivative approximation using the central difference for improved
,→ accuracy
def derivative_central(f, x, h=1e-7):
return (f(x + h) - f(x - h)) / (2 * h)
# Epsilon-Delta simulator: Find a delta such that
# |(f(x+h) - f(x))/h - f'(x)| < epsilon for small h
def find_delta(f, x, f_prime, epsilon):
# Generate a range of h values logarithmically spaced between
,→ 1e-8 and 1e-1
h_values = [Link](-8, -1, 100)
for h in h_values:
approx = derivative_limit(f, x, h)
diff = abs(approx - f_prime)
if diff < epsilon:
return h, diff
return None, None
# Use sympy for symbolic differentiation to verify our numerical
,→ methods
x_sym = [Link]('x')
f_sym = x_sym**3 - 2*x_sym + 1 # Symbolic representation of f(x)
f_sym_diff = [Link](f_sym, x_sym) # Symbolic derivative f'(x)
f_sym_diff_func = [Link](x_sym, f_sym_diff, 'numpy')
# Choose a point to evaluate the derivative and the tangent line
x0 = 2.0
# Compute derivative approximations at x0 using both methods
approx_forward = derivative_limit(f, x0)
approx_central = derivative_central(f, x0)
symbolic_deriv = f_sym_diff_func(x0)
print("Derivative at x =", x0)
print("Forward Difference Approximation:", approx_forward)
print("Central Difference Approximation:", approx_central)
print("Symbolic Derivative:", symbolic_deriv)
# Epsilon-delta simulation: Given an epsilon, find a corresponding
,→ delta
epsilon = 1e-5
delta, error = find_delta(f, x0, symbolic_deriv, epsilon)
52
if delta is not None:
print(f"\nFor epsilon = {epsilon}, a delta = {delta} was found
,→ with error = {error}")
else:
print(f"\nNo suitable delta found for epsilon = {epsilon}")
# Define the tangent line at x0: y = f(x0) + f'(x0) * (x - x0)
def tangent_line(x, x0, f_x0, derivative):
return f_x0 + derivative * (x - x0)
# Generate values for plotting the function and the tangent line
x_vals = [Link](x0 - 5, x0 + 5, 400)
y_vals = f(x_vals)
tangent_vals = tangent_line(x_vals, x0, f(x0), approx_central)
# Plot the function and its tangent line at x0
[Link](figsize=(8, 6))
[Link](x_vals, y_vals, label="$f(x) = x^3 - 2x + 1$")
[Link](x_vals, tangent_vals, 'r--', label=f"Tangent at x = {x0}")
[Link]([x0], [f(x0)], color='black', zorder=5)
[Link]("Graph of f(x) and its Tangent Line at x =
,→ {:.1f}".format(x0))
[Link]("x")
[Link]("f(x)")
[Link]()
[Link](True)
[Link]()
53
Chapter 8
Basic Differentiation
Rules
The Sum and Difference Rules
Let f and g be functions that are differentiable at a point x. By in-
voking the definition of the derivative, one may express the deriva-
tive of the sum f + g as
(f + g)(x + h) − (f + g)(x)
(f + g)′ (x) = lim .
h→0 h
A straightforward algebraic manipulation yields
f (x + h) − f (x) g(x + h) − g(x)
(f + g) (x) = lim
′
+ .
h→0 h h
Assuming that the individual limits exist, the linearity of limits
ensures that
(f + g)′ (x) = f ′ (x) + g ′ (x).
An entirely analogous argument establishes that the derivative of
the difference f − g is given by
(f − g)′ (x) = f ′ (x) − g ′ (x).
This pair of results succinctly encapsulates the additivity and sub-
tractivity properties inherent in differentiation.
54
The Product Rule
Consider now two functions f and g that are differentiable at a
point x. The derivative of the product f (x)g(x) is defined as
d f (x + h)g(x + h) − f (x)g(x)
[f (x)g(x)] = lim .
dx h→0 h
To elucidate the structure of this limit, it is beneficial to intro-
duce the intermediate term f (x + h)g(x) and thereby rewrite the
difference quotient as
f (x + h)g(x + h) − f (x + h)g(x) f (x + h)g(x) − f (x)g(x)
+ .
h h
Expressing the first term in factorized form, one obtains
g(x + h) − g(x)
f (x + h) ,
h
and similarly, the second term becomes
f (x + h) − f (x)
g(x) .
h
Taking the limit as h → 0, and invoking the continuity of f and g
at x, yields
g(x + h) − g(x)
lim f (x + h) = f (x)g ′ (x),
h→0 h
and
f (x + h) − f (x)
lim g(x) = g(x)f ′ (x).
h→0 h
Hence, the product rule is rigorously established as
d
[f (x)g(x)] = f ′ (x)g(x) + f (x)g ′ (x).
dx
The Quotient Rule
Assume that f and g are differentiable functions at x, and that
g(x) ̸= 0. The derivative of the quotient fg(x)
(x)
is defined by
f (x+h) f (x)
d f (x) −
g(x+h) g(x)
= lim .
dx g(x) h→0 h
55
An initial step involves combining the two terms into a single frac-
tion:
f (x + h)g(x) − f (x)g(x + h)
.
h g(x + h)g(x)
A judicious maneuver consists of adding and subtracting the com-
mon term f (x)g(x) in the numerator to facilitate factorization.
This renders the numerator equal to
[f (x + h) − f (x)] g(x) − f (x) [g(x + h) − g(x)] .
Consequently, the difference quotient can be written as
[f (x + h) − f (x)] g(x) f (x) [g(x + h) − g(x)]
− .
h g(x + h)g(x) h g(x + h)g(x)
Upon taking the limit as h → 0, the limit process entails replacing
g(x + h) by its value g(x) (courtesy of continuity), and one deduces
that
d f (x) f ′ (x)g(x) − f (x)g ′ (x)
= .
dx g(x) [g(x)]2
This derivation substantiates the quotient rule and completes the
set of fundamental differentiation techniques.
Python Code Snippet
# Import sympy for symbolic mathematics
import sympy as sp
# Define the symbol 'x'
x = [Link]('x')
# Define two sample functions f(x) and g(x)
# For demonstration purposes, let:
# f(x) = x**2
# g(x) = sin(x)
f_expr = x**2
g_expr = [Link](x)
# ----------------------------------------------------------
# Sum and Difference Rules
# ----------------------------------------------------------
# Sum: f(x) + g(x)
sum_expr = f_expr + g_expr
# Difference: f(x) - g(x)
diff_expr = f_expr - g_expr
56
# Compute derivatives using sympy's differentiation
d_sum_expr = [Link](sum_expr, x)
d_diff_expr = [Link](diff_expr, x)
print("Sum Rule:")
print("d/dx [f(x) + g(x)] =", d_sum_expr) # Expected output: 2*x +
,→ cos(x)
print("\nDifference Rule:")
print("d/dx [f(x) - g(x)] =", d_diff_expr) # Expected output: 2*x -
,→ cos(x)
# ----------------------------------------------------------
# Product Rule
# ----------------------------------------------------------
# Product: f(x)*g(x)
product_expr = f_expr * g_expr
# Compute the derivative directly
d_product_expr = [Link](product_expr, x)
# Manual application of the product rule:
# d/dx [f(x)*g(x)] = f'(x)*g(x) + f(x)*g'(x)
manual_product_expr = [Link](f_expr, x) * g_expr + f_expr *
,→ [Link](g_expr, x)
print("\nProduct Rule:")
print("d/dx [f(x)*g(x)] =", d_product_expr)
print("Manual computation (f'(x)*g(x) + f(x)*g'(x)) =",
,→ manual_product_expr)
# ----------------------------------------------------------
# Quotient Rule
# ----------------------------------------------------------
# Quotient: f(x)/g(x) with the assumption that g(x) != 0
quotient_expr = f_expr / g_expr
# Compute the derivative directly
d_quotient_expr = [Link](quotient_expr, x)
# Manual application of the quotient rule:
# d/dx [f(x)/g(x)] = (f'(x)*g(x) - f(x)*g'(x)) / [g(x)]^2
manual_quotient_expr = ([Link](f_expr, x) * g_expr - f_expr *
,→ [Link](g_expr, x)) / (g_expr**2)
print("\nQuotient Rule:")
print("d/dx [f(x)/g(x)] =", d_quotient_expr)
print("Manual computation ((f'(x)*g(x) - f(x)*g'(x))/(g(x)**2)) =",
,→ manual_quotient_expr)
# ----------------------------------------------------------
# Additional Demonstration: Evaluation at a Specific Point
# ----------------------------------------------------------
57
# Evaluate expressions at x = pi/4
value = [Link] / 4
print("\nEvaluation at x = pi/4:")
print("f(x) =", f_expr.subs(x, value))
print("g(x) =", g_expr.subs(x, value))
print("f(x) + g(x) =", sum_expr.subs(x, value))
print("d/dx [f(x) + g(x)] =", d_sum_expr.subs(x, value))
58
Chapter 9
Chain Rule for
Differentiation
Preliminaries and Notational Conventions
Let f and g be functions defined on appropriate subsets of the real
numbers such that the composite function
h(x) = f g(x)
is well defined. In this context, the function g is referred to as the
inner function and f as the outer function. It is assumed that both
f and g are differentiable at points in their respective domains and
that the range of g is contained in the domain of f . The central
objective is to determine the derivative
d
h′ (x) =
f g(x)
dx
in terms of the derivatives f ′ and g ′ .
Theoretical Development and Formal Deriva-
tion
The derivation of the chain rule proceeds via a careful examination
of the difference quotient for the composite function. Begin with
the definition of the derivative of h:
f g(x + h) − f g(x)
h (x) = lim
′
.
h→0 h
59
To facilitate the analysis, introduce the intermediate difference
∆g = g(x + h) − g(x).
Provided that g is differentiable at x, ∆g tends to zero as h → 0,
and one may rewrite the difference quotient as
f g(x + h) − f g(x) f g(x) + ∆g − f g(x) ∆g
= · .
h ∆g h
Assuming that the limit as h → 0 exists and that f is differentiable
at g(x), the first factor converges to the derivative f ′ g(x) :
f g(x) + ∆g − f g(x)
lim = f ′ g(x) .
∆g→0 ∆g
Simultaneously, the second factor converges to g ′ (x), by the defi-
nition of the derivative of g:
g(x + h) − g(x)
lim = g ′ (x).
h→0 h
Thus, the limit defining h′ (x) may be expressed as the product of
these two limits, yielding the chain rule:
d
f g(x) = f ′ g(x) · g ′ (x).
dx
Illustrative Examples
Consider the application of the chain rule to various composite
functions.
1 Example 1: Power of a Polynomial Function
Let 5
h(x) = 3x2 + 2 .
Here, the inner function is
u(x) = 3x2 + 2,
and the outer function is
f (u) = u5 .
60
Differentiation of the outer function with respect to u gives
f ′ (u) = 5u4 .
Simultaneously, the derivative of the inner function is
u′ (x) = 6x.
By the chain rule, it follows that
4 4
h′ (x) = f ′ u(x) · u′ (x) = 5 3x2 + 2 · 6x = 30x 3x2 + 2 .
2 Example 2: Exponential of a Linear Function
Examine the composite function
h(x) = e4x−1 .
In this case, define the inner function as
u(x) = 4x − 1,
and the outer function as
f (u) = eu .
Since the derivative of the outer function is
f ′ (u) = eu ,
and the derivative of the inner function is
u′ (x) = 4,
the chain rule implies that
h′ (x) = e4x−1 · 4 = 4e4x−1 .
3 Example 3: Trigonometric Composition
Consider the composite trigonometric function
h(x) = sin x2 .
Identify the inner function as
u(x) = x2 ,
61
and the outer function as
f (u) = sin u.
The derivative of the outer function with respect to u is
f ′ (u) = cos u,
while the derivative of the inner function is
u′ (x) = 2x.
Application of the chain rule yields
h′ (x) = cos x2 · 2x = 2x cos x2 .
4 Example 4: Logarithmic of a Rational Func-
tion
Finally, consider the function
1+x
h(x) = ln .
1−x
Here, the composite structure is inherent in the argument of the
logarithm. Define the inner function as
1+x
u(x) = ,
1−x
and the outer function as
f (u) = ln u.
The derivative of f with respect to u is
1
f ′ (u) = ,
u
and a separate calculation shows that
2
u′ (x) = .
(1 − x)2
Thus, by the chain rule, the derivative of h(x) is
1 2 1−x 2 2
h′ (x) = · = · = ,
1+x
1−x
(1 − x)2 1 + x (1 − x)2 (1 + x)(1 − x)
which simplifies further when expressed in terms of a difference of
squares.
Each example demonstrates the efficacy and versatility of the
chain rule in handling the derivatives of composite functions across
diverse functional forms.
62
Python Code Snippet
import sympy as sp
# Define the symbol for the variable
x = [Link]('x')
# Define a function to compute the derivative of a composite
,→ function using the chain rule.
def chain_rule_composite(f, g, x):
"""
Compute the derivative of a composite function h(x) = f(g(x))
using the chain rule. Returns h'(x) = f'(g(x)) * g'(x)
Parameters:
f : sympy expression in terms of u (outer function)
g : sympy expression in terms of x (inner function)
x : sympy symbol representing the variable
Returns:
derivative: The derivative of f(g(x)) with respect to x.
"""
# Define a new symbol for the inner variable
u = [Link]('u')
# Compute the derivative of the outer function with respect to
,→ u.
# Note: f is given in terms of u, so we differentiate with
,→ respect to u.
f_prime = [Link]([Link](u, u), u)
# Substitute g(x) into f_prime to obtain f'(g(x))
f_prime_at_g = f_prime.subs(u, g)
# Compute the derivative of the inner function g with respect to
,→ x.
g_prime = [Link](g, x)
# Return the product as per the chain rule.
return [Link](f_prime_at_g * g_prime)
# Example 1: Power of a Polynomial Function
# h(x) = (3x^2 + 2)^5
h1 = (3*x**2 + 2)**5
h1_prime = [Link](h1, x)
print("Example 1: h(x) = (3x^2 + 2)^5")
print("Derivative computed using [Link]: ", h1_prime)
# Using chain_rule_composite: f(u) = u^5, g(x) = 3x^2 + 2
u = [Link]('u')
f1 = u**5
g1 = 3*x**2 + 2
chain_rule_derivative1 = chain_rule_composite(f1, g1, x)
63
print("Derivative computed using chain_rule_composite: ",
,→ chain_rule_derivative1)
print()
# Example 2: Exponential of a Linear Function
# h(x) = exp(4x - 1)
h2 = [Link](4*x - 1)
h2_prime = [Link](h2, x)
print("Example 2: h(x) = exp(4x - 1)")
print("Derivative computed using [Link]: ", h2_prime)
# Using chain_rule_composite: f(u) = exp(u), g(x) = 4x - 1
f2 = [Link](u)
g2 = 4*x - 1
chain_rule_derivative2 = chain_rule_composite(f2, g2, x)
print("Derivative computed using chain_rule_composite: ",
,→ chain_rule_derivative2)
print()
# Example 3: Trigonometric Composition
# h(x) = sin(x^2)
h3 = [Link](x**2)
h3_prime = [Link](h3, x)
print("Example 3: h(x) = sin(x^2)")
print("Derivative computed using [Link]: ", h3_prime)
# Using chain_rule_composite: f(u) = sin(u), g(x) = x^2
f3 = [Link](u)
g3 = x**2
chain_rule_derivative3 = chain_rule_composite(f3, g3, x)
print("Derivative computed using chain_rule_composite: ",
,→ chain_rule_derivative3)
print()
# Example 4: Logarithmic of a Rational Function
# h(x) = ln((1+x)/(1-x))
h4 = [Link]((1+x)/(1-x))
h4_prime = [Link](h4, x)
print("Example 4: h(x) = ln((1+x)/(1-x))")
print("Derivative computed using [Link]: ", h4_prime)
# Using chain_rule_composite: f(u) = log(u), g(x) = (1+x)/(1-x)
f4 = [Link](u)
g4 = (1+x)/(1-x)
chain_rule_derivative4 = chain_rule_composite(f4, g4, x)
print("Derivative computed using chain_rule_composite: ",
,→ chain_rule_derivative4)
print()
# Example 5: Additional Composite Example
# h(x) = (sin(x))^3, where f(u) = u^3 and g(x) = sin(x)
h5 = [Link](x)**3
h5_prime = [Link](h5, x)
print("Example 5: h(x) = (sin(x))^3")
print("Derivative computed using [Link]: ", h5_prime)
# Using chain_rule_composite: f(u) = u^3, g(x) = sin(x)
64
f5 = u**3
g5 = [Link](x)
chain_rule_derivative5 = chain_rule_composite(f5, g5, x)
print("Derivative computed using chain_rule_composite: ",
,→ chain_rule_derivative5)
65
Chapter 10
Implicit Differentiation
and Related Rates
Implicit Differentiation
Consider a relation expressed by an equation
F (x, y) = 0,
where F : R2 → R is continuously differentiable. In many in-
stances, the variable y is defined only implicitly as a function of
x. Differentiation of such an equation with respect to x requires
application of the chain rule to account for the dependence of y on
x. Differentiating both sides of the identity with respect to x yields
∂F ∂F dy
(x, y) + (x, y) = 0.
∂x ∂y dx
Assuming that ∂F
∂y (x, y) ̸= 0, the derivative dy
dx is then given by
∂x (x, y)
∂F
dy
= − ∂F .
∂y (x, y)
dx
1 Fundamental Principles
When a relation is not solved explicitly for y, the differentiation
process necessitates treating y as an implicit function of x. Every
occurrence of y in an expression requires further differentiation via
66
the chain rule. For example, when differentiating a composite term
such as y n , the derivative with respect to x is computed as
d n dy
(y ) = n y n−1 .
dx dx
Similar care must be taken with functions involving more compli-
cated expressions in y. In every such instance, the implicit depen-
dence of y on x is manifested by the additional factor dx
dy
.
2 Illustrative Example in Implicit Differentia-
tion
An instructive case arises in the study of conic sections. Consider
the ellipse defined by
x2 y2
+ = 1,
a2 b2
with constants a, b > 0. Differentiation with respect to x proceeds
as follows:
d x2 d y2
+ = 0.
dx a2 dx b2
Since
x2 2x y2 2y dy
d d
= and = ,
dx a2 a2 dx b2 b2 dx
one obtains the identity
2x 2y dy
+ 2 = 0.
a2 b dx
Solving for dy
dx yields
dy b2 x
=− 2 ,
dx a y
which provides the slope of the tangent line at a point (x, y) on the
ellipse.
Related Rates
In numerous applications, the variables connected by an implicit
relation evolve with respect to an independent parameter, typically
time t. When the variables x and y are functions of t and satisfy
an equation
F (x, y) = 0,
67
differentiation with respect to t relates the rates of change of these
variables. Applying the chain rule to the relation yields
∂F dx ∂F dy
+ = 0.
∂x dt ∂y dt
dt and dt , encapsulating the
This expression links the derivatives dx dy
interdependence of their temporal variations.
1 General Framework for Related Rates
Let x = x(t) and y = y(t) be differentiable functions that satisfy
the relation F (x(t), y(t)) = 0. The process of obtaining an equation
for the rates, dx
dt and dt , begins with differentiating F with respect
dy
to t. The chain rule entails that every instance of the variable
x contributes a term ∂F ∂x dt , while every instance of y contributes
dx
∂y dt . Hence, the differentiation leads to the equation
∂F dy
∂F dx ∂F dy
(x, y) + (x, y) = 0.
∂x dt ∂y dt
Given knowledge of one differential rate, the above relation may be
solved for the other rate, provided that ∂F ∂y (x, y) ̸= 0 (or alterna-
tively, ∂x (x, y) ̸= 0 if solved in the opposite manner).
∂F
2 Exemplary Application: Circular Motion
A classical example in related rates is provided by the equation
governing a circle,
x2 + y 2 = R 2 ,
where R is constant, and both x and y are functions of time t.
Differentiation with respect to t yields
dx dy
2x + 2y = 0.
dt dt
Dividing through by 2 gives
dx dy
x +y = 0.
dt dt
Assuming that the rate dx dt is known, the rate of change
dy
dt is de-
termined by isolating it:
dy x dx
=− .
dt y dt
68
This relation is essential for understanding the instantaneous mo-
tion of a point traced along the circumference of a circle.
3 Extension to More Complex Relations
Implicit differentiation and its extension to related rates are not
confined to simple geometric figures. In more intricate settings,
the relation F (x, y) = 0 may involve transcendental functions or
higher-degree polynomials. In each case, differentiation with re-
spect to the independent variable (either x or t) is accomplished
by applying the chain rule to every term where the implicit de-
pendence is present. The resulting equation, when solved for the
desired derivative, encapsulates the instantaneous relationship be-
tween the rates of change of the dynamic variables.
An example of such complexity is encountered with an equation
that combines algebraic and transcendental elements, such as
exy + sin(y) = x2 .
Differentiation with respect to x yields
dy dy
exy y + x + cos(y) = 2x.
dx dx
Collecting the terms that contain dy
dx produces
dy
(exy x + cos(y)) = 2x − exy y.
dx
Thus, the derivative is given by
dy 2x − exy y
= xy ,
dx e x + cos(y)
provided that the denominator is nonzero. A similar procedure
applies when differentiating with respect to time in a related rates
context.
The methods detailed herein furnish a versatile framework for
addressing a broad spectrum of problems wherein the interdepen-
dence of variables is implicitly defined and their rates of change are
of principal interest.
69
Python Code Snippet
# Import required modules from sympy and initialize pretty printing
from sympy import symbols, Function, diff, solve, Eq, sin, cos, exp,
,→ pprint, simplify, init_printing
init_printing()
# Define symbols for variables and parameters
x, y, a, b, R, t = symbols('x y a b R t', real=True, positive=True)
v = symbols('v', real=True) # Represents dx/dt in related rates
,→ problems
#-----------------------------------------------------------
# 1. Implicit Differentiation
#
# For a relation F(x, y) = 0 where y is implicitly a function of x,
# the derivative dy/dx is given by:
#
# dy/dx = - (F/x) / (F/y)
#
# This function computes dy/dx for a given expression F = 0.
#-----------------------------------------------------------
def implicit_derivative(F):
# Compute the partial derivatives of F with respect to x and y
F_x = diff(F, x)
F_y = diff(F, y)
# Calculate dy/dx using the formula: -F_x/F_y
dy_dx = -F_x/F_y
return simplify(dy_dx)
# Example 1: Ellipse
# Equation: (x^2)/(a^2) + (y^2)/(b^2) = 1, which can be written as:
# F(x, y) = x^2/a^2 + y^2/b^2 - 1 = 0
F_ellipse = x**2/a**2 + y**2/b**2 - 1
dy_dx_ellipse = implicit_derivative(F_ellipse)
print("dy/dx for the ellipse (x^2)/(a^2) + (y^2)/(b^2) = 1:")
pprint(dy_dx_ellipse)
# Example 2: Mixed Transcendental and Algebraic Expression
# Equation: exp(x*y) + sin(y) = x^2, written as:
# F(x, y) = exp(x*y) + sin(y) - x**2 = 0
F_complex = exp(x*y) + sin(y) - x**2
dy_dx_complex = implicit_derivative(F_complex)
print("\ndy/dx for the equation exp(x*y) + sin(y) = x^2:")
pprint(dy_dx_complex)
#-----------------------------------------------------------
# 2. Related Rates
70
#
# When x and y are both functions of time t and satisfy F(x, y) = 0,
# differentiating with respect to t gives:
#
# (F/x)*(dx/dt) + (F/y)*(dy/dt) = 0.
#
# Solving for dy/dt yields:
#
# dy/dt = - (F/x) / (F/y) * (dx/dt).
#
# This function computes dy/dt given F(x, y) = 0 and a known dx/dt.
#-----------------------------------------------------------
def related_rate(F, dx_dt):
# Differentiate F with respect to x and y
F_x = diff(F, x)
F_y = diff(F, y)
# Solve for dy/dt using the relation: F_x*dx/dt + F_y*dy/dt = 0
dy_dt = -F_x * dx_dt / F_y
return simplify(dy_dt)
# Example of Related Rates: Circle
# Equation: x^2 + y^2 = R^2, written as F(x, y) = x^2 + y^2 - R^2 =
,→ 0
F_circle = x**2 + y**2 - R**2
# Assume that dx/dt (denoted as v) is known; then, dy/dt is given
,→ by:
dy_dt_circle = related_rate(F_circle, v)
print("\ndy/dt for the circle x^2 + y^2 = R^2 with dx/dt = v:")
pprint(dy_dt_circle)
#-----------------------------------------------------------
# The methods shown above can be extended to more complicated
,→ relations.
# For example, the implicit differentiation of exp(x*y) + sin(y) =
,→ x^2 and
# determining related rates using the chain rule are powerful tools
,→ in calculus.
#
# This Python code snippet demonstrates how symbolic computation can
,→ be
# applied to derive important equations and formulas from the
,→ chapter.
#-----------------------------------------------------------
71
Chapter 11
Differentiation of
Trigonometric
Functions
Derivatives of the Sine and Cosine Func-
tions
The differentiation of the sine and cosine functions constitutes a
foundational component of the analysis of periodic phenomena.
The derivative of the sine function is obtained by first consider-
ing the limit definition of the derivative:
d sin(x + h) − sin x
sin x = lim .
dx h→0 h
By invoking the sine addition formula,
sin(x + h) = sin x cos h + cos x sin h,
the difference quotient can be rewritten as
sin x(cos h − 1) + cos x sin h
.
h
Utilizing the well-established limits
sin h cos h − 1
lim = 1 and lim = 0,
h→0 h h→0 h
72
the derivative is computed as
d
sin x = cos x.
dx
A similar procedure applies to the cosine function. The deriva-
tive is defined by
d cos(x + h) − cos x
cos x = lim .
dx h→0 h
Application of the cosine addition formula,
cos(x + h) = cos x cos h − sin x sin h,
leads to the expression
cos x(cos h − 1) − sin x sin h
.
h
Taking the limit as h → 0 and using the standard limits mentioned
above yields
d
cos x = − sin x.
dx
These prototypical results lay the groundwork for the analysis of
more complex trigonometric functions.
Derivatives of Other Trigonometric Func-
tions
The differentiation of the remaining trigonometric functions is de-
rived either by employing the quotient rule or by manipulation
using the reciprocal relations with sine and cosine. For the tangent
function, defined by
sin x
tan x = ,
cos x
application of the quotient rule leads to
d cos x · cos x − sin x · (− sin x) cos2 x + sin2 x 1
tan x = = = .
dx cos x
2 cos2 x cos2 x
Thus, the derivative is succinctly expressed as
d
tan x = sec2 x.
dx
73
Similarly, the cotangent function, given by
cos x
cot x = ,
sin x
is differentiated using the quotient rule to obtain
d − sin x · sin x − cos x · cos x sin2 x + cos2 x
cot x = = − = − csc2 x.
dx sin2 x sin2 x
The derivatives of the secant and cosecant functions follow nat-
urally from their definitions as reciprocals. For the secant function,
1
sec x = ,
cos x
application of the differentiation rules for reciprocal functions re-
sults in
d
sec x = sec x tan x.
dx
Analogously, for the cosecant function,
1
csc x = ,
sin x
its derivative is computed as
d
csc x = − csc x cot x.
dx
Each of these derivative formulas underscores the interdependent
nature of the trigonometric functions.
Applications of Trigonometric Derivatives
The differentiated forms of trigonometric functions have a broad
spectrum of applications across various branches of mathematics
and physics. In the study of oscillatory behavior, the derivatives
of the sine and cosine functions are instrumental in formulating
differential equations that model harmonic motion. For example,
the second-order linear differential equation
d2 y
+y =0
dx2
possesses solutions expressible in terms of sine and cosine functions,
whose differentiability properties guarantee that the solution pro-
cess is both robust and elegant.
74
Derivatives of functions such as the tangent, secant, and cose-
cant regularly appear in problems involving the geometry of curves,
notably when analyzing the behavior of angles and slopes on the
unit circle, or in problems formulated in polar coordinates. The
derivative of the tangent function, sec2 x, arises naturally in the
context of rate-of-change problems where the slope of a curve is
central to the analysis. Likewise, the derivatives of sec x and csc x
facilitate the investigation of curvature and inflection points in pe-
riodic functions.
Beyond direct applications in differential equations, these deriva-
tive formulas play a significant role in the realm of Fourier analysis
and in the study of periodic signals. The capability to transi-
tion between the trigonometric representations of functions and
their differentiated forms is a powerful tool that enables the de-
composition of complex signals into their constituent frequencies.
Moreover, the foundational results concerning the differentiation of
trigonometric functions extend in a natural and coherent manner
to functions defined in the complex plane. Euler’s formula,
eix = cos x + i sin x,
provides an alternative framework wherein differentiation may be
approached via complex analytic techniques, thereby reinforcing
the classical real-variable results and extending their applicability
to a broader class of functions.
The robust interconnections among the trigonometric functions,
their derivative properties, and the resultant applications in both
theoretical and applied contexts illustrate the central importance
of these concepts in the broader fabric of mathematical analysis.
Python Code Snippet
# This Python script illustrates the key differentiation formulas
,→ and algorithms
# related to trigonometric functions as discussed in this chapter.
# It uses symbolic differentiation with the sympy library and
,→ numerical approximation
# to validate the derivative definitions based on limits.
import sympy as sp
import numpy as np
# Define the symbol for the variable
x = [Link]('x')
75
# Define trigonometric functions symbolically
sin_x = [Link](x)
cos_x = [Link](x)
tan_x = [Link](x)
cot_x = [Link](x)
sec_x = 1 / [Link](x) # sec(x) = 1/cos(x)
csc_x = 1 / [Link](x) # csc(x) = 1/sin(x)
# Symbolically differentiate the functions using [Link]
d_sin = [Link](sin_x, x) # d/dx sin(x) = cos(x)
d_cos = [Link](cos_x, x) # d/dx cos(x) = -sin(x)
d_tan = [Link](tan_x, x) # d/dx tan(x) = sec^2(x)
d_cot = [Link](cot_x, x) # d/dx cot(x) = -csc^2(x)
d_sec = [Link](sec_x, x) # d/dx sec(x) = sec(x) tan(x)
d_csc = [Link](csc_x, x) # d/dx csc(x) = -csc(x) cot(x)
# Display the symbolic derivatives with pretty printing
print("Symbolic Derivatives:")
print("d/dx sin(x) =", [Link](d_sin))
print("d/dx cos(x) =", [Link](d_cos))
print("d/dx tan(x) =", [Link](d_tan))
print("d/dx cot(x) =", [Link](d_cot))
print("d/dx sec(x) =", [Link](d_sec))
print("d/dx csc(x) =", [Link](d_csc))
# Define a function to approximate the derivative using the limit
,→ definition.
def numerical_derivative(func, x_val, h=1e-6):
"""
Approximate the derivative of function 'func' at the point
,→ 'x_val'
using the definition of the derivative as a limit.
"""
return (func(x_val + h) - func(x_val)) / h
# Create corresponding numpy functions for numerical evaluation
f_sin = [Link]
f_cos = [Link]
f_tan = [Link]
# Choose a test point. For example, x = pi/4.
x_val = [Link] / 4
# Compute numerical derivatives by the limit definition
num_d_sin = numerical_derivative(f_sin, x_val)
num_d_cos = numerical_derivative(f_cos, x_val)
num_d_tan = numerical_derivative(f_tan, x_val)
# Compare numerical derivative with known analytical values
print("\nNumerical Derivatives at x = pi/4:")
print("d/dx sin(x) {:.6f} Expected: cos(pi/4) =
,→ {:.6f}".format(num_d_sin, [Link](x_val)))
76
print("d/dx cos(x) {:.6f} Expected: -sin(pi/4) =
,→ {:.6f}".format(num_d_cos, -[Link](x_val)))
print("d/dx tan(x) {:.6f} Expected: sec^2(pi/4)=
,→ {:.6f}".format(num_d_tan, 1/[Link](x_val)**2))
# Additionally, solve and verify a classical differential equation:
# Consider y'' + y = 0, whose general solution is y = A*cos(x) +
,→ B*sin(x)
# The differentiation of sine and cosine functions plays a crucial
,→ role in verifying this.
# Define the arbitrary constants A and B
A, B = [Link]('A B')
# Define the general solution y
y = A * [Link](x) + B * [Link](x)
# Compute the first and second derivatives of y
y_prime = [Link](y, x)
y_double_prime = [Link](y, x, 2)
# Form the left-hand side of the differential equation: y'' + y
equation = [Link](y_double_prime + y)
print("\nVerification of the differential equation y'' + y = 0:")
print("y'' + y =", [Link](equation))
# The output should be 0, confirming that the general solution
,→ satisfies y'' + y = 0.
77
Chapter 12
Differentiation of
Exponential and
Logarithmic Functions
Exponential Functions
Exponential functions occupy a central role in mathematical anal-
ysis due to their distinctive property of being proportional to their
own rate of change. Consider the general exponential function de-
fined by
f (x) = ax ,
where a is a positive constant different from 1. The differentiation
of f is approached via the limit definition of the derivative:
ax+h − ax
f ′ (x) = lim .
h→0 h
Exploiting the well-known property ax+h = ax ah permits rewriting
the difference quotient as
ah − 1
f ′ (x) = ax lim .
h→0 h
The limit
ah − 1
lim = ln a,
h→0 h
78
emerges naturally from the definition of the natural logarithm.
Consequently, the derivative of the general exponential function
is given by
d x
a = ax ln a.
dx
A noteworthy special case arises when a = e, the base of the natural
logarithm. Since ln e = 1, the derivative simplifies to the elegant
form
d x
e = ex .
dx
This self-referential property of the natural exponential function
underlines its profound importance in both theoretical and applied
disciplines. Furthermore, when the exponent is a differentiable
function g(x), the chain rule dictates that
d g(x)
a = ag(x) ln a · g ′ (x),
dx
thus demonstrating how the interplay between the exponential form
and composite functions requires careful consideration of the inner
function’s derivative.
Logarithmic Functions
Logarithmic functions, inherently defined as the inverses of expo-
nential functions, display equally significant and distinct differen-
tiation properties. Let f (x) = ln x denote the natural logarithm,
where the domain is x > 0. By virtue of the defining relation-
ship ln(ex ) = x, implicit differentiation serves as an effective tool.
Starting from the equivalent equation
eln x = x,
one may differentiate both sides with respect to x. The differenti-
ation of the left-hand side, utilizing the chain rule, produces
d
eln x · ln x = 1.
dx
Since eln x = x, it follows that
d
x· ln x = 1,
dx
79
and hence the derivative of the natural logarithm is found to be
d 1
ln x = .
dx x
For logarithms with an arbitrary positive base a where a ̸= 1, the
change of base formula serves to extend the differentiation result:
ln x
loga x = .
ln a
Differentiation then yields
d 1 d 1
loga x = · ln x = .
dx ln a dx x ln a
This derivation highlights the pivotal role of the natural logarithm
in the theory of logarithmic differentiation, with the multiplicative
factor ln1a encoding the transformation between logarithmic scales.
Properties and Interrelations
The differentiation techniques for both exponential and logarithmic
functions are intimately connected through their inverse relation-
ship. The function ex serves as a fixed point for differentiation,
while ln x reciprocally reflects the rate of change inverse to that of
x itself. Their properties are encapsulated in the identities
d x d 1
e = ex and ln x = ,
dx dx x
which serve as cornerstones in the study of continuous growth,
decay processes, and the analysis of complex dynamical systems.
Moreover, the application of the chain rule further accentuates the
flexibility of these functions when composed with other differen-
tiable functions, thereby broadening the scope of their utility in
advanced mathematical models.
The verbosity of the derivations presented underscores the ne-
cessity for a rigorous limit-based approach in establishing differ-
entiation rules. The aforementioned techniques are not only fun-
damental to theoretical investigations but also provide a robust
framework for addressing practical problems where such functions
emerge naturally.
80
Python Code Snippet
import math
import numpy as np
from sympy import symbols, diff, exp, log, simplify
def numerical_derivative(func, x, h=1e-7):
"""
Compute the numerical derivative of the function 'func' at point
,→ x
using the difference quotient limit definition.
"""
return (func(x + h) - func(x)) / h
# -----------------------------
# Exponential Function Differential Calculations
# -----------------------------
def exp_func(x, a):
"""
Compute the exponential function a^x.
:param x: The exponent
:param a: The base (a > 0 and a != 1)
:return: a raised to the power x
"""
return a ** x
def derivative_exp_numerical(x, a, h=1e-7):
"""
Numerical derivative for the exponential function a^x.
Uses the limit definition: f'(x) = a^x * (limit as h->0 of (a^h
,→ - 1)/h)
"""
f = lambda x: exp_func(x, a)
return numerical_derivative(f, x, h)
def derivative_exp_analytic(x, a):
"""
Analytic derivative for a^x computed as a^x * ln(a).
"""
return exp_func(x, a) * [Link](a)
# -----------------------------
# Natural Exponential Function (Base e)
# -----------------------------
def derivative_e_exp_numerical(x, h=1e-7):
"""
Numerical derivative for the natural exponential function e^x.
"""
return derivative_exp_numerical(x, math.e, h)
def derivative_e_exp_analytic(x):
"""
81
Analytic derivative for e^x is simply e^x.
"""
return math.e ** x
# -----------------------------
# Logarithmic Function Differential Calculations
# -----------------------------
def ln_func(x):
"""
Compute the natural logarithm ln(x). Domain: x > 0.
"""
return [Link](x)
def derivative_ln_numerical(x, h=1e-7):
"""
Numerical derivative for ln(x) using the definition.
"""
return numerical_derivative(ln_func, x, h)
def derivative_ln_analytic(x):
"""
Analytic derivative of ln(x) is 1/x.
"""
return 1 / x
def log_base_a(x, a):
"""
Compute logarithm of x with base a using change of base:
log_a(x) = ln(x) / ln(a)
"""
return [Link](x) / [Link](a)
def derivative_log_base_a_analytic(x, a):
"""
Analytic derivative for log base a function: d/dx log_a(x)=1/(x
,→ ln(a)).
"""
return 1 / (x * [Link](a))
# -----------------------------
# Chain Rule Example: Differentiation of a^(g(x))
# -----------------------------
def g(x):
"""
Inner function for chain rule example: g(x) = 2x + 3.
"""
return 2 * x + 3
def dg_dx(x):
"""
Derivative of the inner function g(x)=2x+3. Its derivative is
,→ constant 2.
"""
82
return 2
def chain_rule_numerical(x, a, h=1e-7):
"""
Numerical derivative for the composite function f(x)=a^(g(x)).
"""
f = lambda x: a ** (g(x))
return numerical_derivative(f, x, h)
def chain_rule_analytic(x, a):
"""
Analytic derivative computed using the chain rule:
d/dx a^(g(x)) = a^(g(x)) * ln(a) * g'(x)
"""
return a ** (g(x)) * [Link](a) * dg_dx(x)
# -----------------------------
# Main function to demonstrate and compare derivatives
# -----------------------------
def main():
# Define sample x values and a base for exponential functions
x_values = [0.5, 1, 1.5, 2]
a = 2.5 # arbitrary base for demonstration (a > 0 and a != 1)
print("Exponential Function: f(x)=a^x, with a =", a)
for x in x_values:
num_deriv = derivative_exp_numerical(x, a)
ana_deriv = derivative_exp_analytic(x, a)
print(f"x = {x:4.2f} -> Numerical Derivative =
,→ {num_deriv:12.8f}, "
f"Analytic Derivative = {ana_deriv:12.8f}")
print("\nNatural Exponential Function: f(x)=e^x")
for x in x_values:
num_deriv = derivative_e_exp_numerical(x)
ana_deriv = derivative_e_exp_analytic(x)
print(f"x = {x:4.2f} -> Numerical Derivative =
,→ {num_deriv:12.8f}, "
f"Analytic Derivative = {ana_deriv:12.8f}")
print("\nLogarithmic Function: f(x)=ln(x)")
for x in x_values:
num_deriv = derivative_ln_numerical(x)
ana_deriv = derivative_ln_analytic(x)
print(f"x = {x:4.2f} -> Numerical Derivative =
,→ {num_deriv:12.8f}, "
f"Analytic Derivative = {ana_deriv:12.8f}")
print("\nLogarithmic Function with arbitrary base:
,→ f(x)=log_a(x)")
for x in x_values:
ana_deriv = derivative_log_base_a_analytic(x, a)
83
print(f"x = {x:4.2f} -> Analytic Derivative log_{a}(x) =
,→ {ana_deriv:12.8f}")
print("\nChain Rule Example: f(x)=a^(g(x)) with g(x)=2x+3")
for x in x_values:
num_deriv = chain_rule_numerical(x, a)
ana_deriv = chain_rule_analytic(x, a)
print(f"x = {x:4.2f} -> Numerical Composite Derivative =
,→ {num_deriv:12.8f}, "
f"Analytic Composite Derivative = {ana_deriv:12.8f}")
# -----------------------------
# Symbolic Differentiation using sympy for verification
# -----------------------------
# Define symbolic variables and expressions
x_sym, a_sym = symbols('x a', positive=True)
# Symbolic differentiation of a^x
expr_exp = a_sym ** x_sym
sym_deriv_exp = diff(expr_exp, x_sym)
print("\nSymbolic differentiation (Exponential Function):")
print("d/dx a^x =", simplify(sym_deriv_exp))
# Symbolic differentiation of ln(x)
expr_ln = log(x_sym)
sym_deriv_ln = diff(expr_ln, x_sym)
print("Symbolic differentiation (Natural Logarithm):")
print("d/dx ln(x) =", simplify(sym_deriv_ln))
if __name__ == "__main__":
main()
84
Chapter 13
Differentiation of
Inverse Functions
Preliminaries
Let f : I → J be a continuously differentiable function defined
on an interval I ⊂ R with range J ⊂ R, and assume that f is
one-to-one. Under the additional hypothesis that f ′ (x) ̸= 0 for
all x ∈ I, the inverse function f −1 : J → I exists and is itself
differentiable. The analysis that follows considers the theoretical
framework for differentiating inverse functions while examining the
intrinsic relationship between a function and its inverse.
The Derivative of an Inverse Function
The fundamental identity linking a function with its inverse is given
by
f f −1 (y) = y,
which holds for all y ∈ J. Differentiation of this identity with
respect to y requires application of the chain rule. Differentiating
the left-hand side yields
d d −1
f f −1 (y) = f ′ f −1 (y) · f (y).
dy dy
85
Since the derivative of the right-hand side with respect to y is 1, it
follows that
d −1
f ′ f −1 (y) · f (y) = 1.
dy
Under the condition that f ′ f −1 (y) is nonzero, the preceding iden-
tity immediately implies
d −1 1
f (y) = ′ −1 .
dy f f (y)
This formula not only provides a direct method for computing the
derivative of the inverse function but also encapsulates the recip-
rocal nature of the rates of change associated with f and f −1 .
Analytical Justification
Consider a point x0 ∈ I and let y0 = f (x0 ). The invertibility
and continuous differentiability of f , together with the condition
f ′ (x0 ) ̸= 0, guarantee that a local inverse exists in a neighborhood
of y0 . Denote this inverse function locally by g, where
g(y) = f −1 (y).
By the defining property of inverse functions,
f g(y) = y.
Differentiating both sides with respect to y yields
f ′ g(y) g ′ (y) = 1.
This relation reaffirms that
1
g ′ (y) = ,
f ′ g(y)
thereby clarifying that the local linear approximation of g is gov-
erned by the reciprocal of the local linear approximation of f . The
derivation illustrates that the condition f ′ (x0 ) ̸= 0 is essential, as
it ensures the existence and differentiability of the inverse function
in the vicinity of x0 .
86
Interrelation of a Function and Its Inverse
The symmetric connection between a function and its inverse is
embodied in the relation
′
f ′ f −1 (y) · f −1 (y) = 1.
Geometrically, if the graph of f has a tangent at the point (x, f (x))
with slope f ′ (x), then the graph of f −1 , which is the reflection of
the graph of f about the line y = x, has a tangent at the point
f (x), x with slope given by
′ 1
f −1 (f (x)) = .
f ′ (x)
This reciprocal relationship between the slopes of the tangents
serves as a precise characterization of how the sensitivity to change
is inverted in the passage from a function to its inverse. In the con-
text of linear approximations, a rapid variation in the function f
leads to a correspondingly diminished variation in its inverse f −1 ,
and vice versa.
The analytical expression for the derivative of an inverse func-
tion provides a robust tool for examining various properties of in-
verse mappings. It underscores the inherent balance between a
function and its inverse, a balance that is central to understanding
transformation properties in mathematical analysis.
Python Code Snippet
import sympy as sp
# Define symbols
x, y = [Link]('x y', real=True)
# Choose a one-to-one, continuously differentiable function.
# Here we use f(x) = x**3 as an example, whose inverse is f^{-1}(y)
,→ = y**(1/3).
f = x**3
# Compute the derivative f'(x)
f_prime = [Link](f, x)
# To find the inverse function, solve f(x) = y for x.
# For f(x) = x**3, we solve x**3 - y = 0.
inverse_solutions = [Link](f - y, x)
87
# Select the appropriate (real) branch for the inverse.
f_inv = inverse_solutions[0]
# Compute the derivative of the inverse function directly by
,→ differentiating f_inv with respect to y.
f_inv_prime = [Link](f_inv, y)
# Alternatively, compute the derivative using the reciprocal
,→ formula:
# (f^{-1})'(y) = 1 / f'(f^{-1}(y))
reciprocal_formula = 1 / f_prime.subs(x, f_inv)
# Simplify the expressions for clarity
f_inv = [Link](f_inv)
f_inv_prime = [Link](f_inv_prime)
reciprocal_formula = [Link](reciprocal_formula)
# Output the function, its inverse, and the derivative details.
print("Function f(x):")
sp.pretty_print(f)
print("\nInverse function f^{-1}(y):")
sp.pretty_print(f_inv)
print("\nDerivative f'(x):")
sp.pretty_print(f_prime)
print("\nDerivative of inverse function computed directly,
,→ (f^{-1})'(y):")
sp.pretty_print(f_inv_prime)
print("\nDerivative of inverse function using reciprocal formula, 1
,→ / f'(f^{-1}(y)):")
sp.pretty_print(reciprocal_formula)
# Verify that both methods give the same result.
assert [Link](f_inv_prime - reciprocal_formula) == 0, "The
,→ derivatives do not match!"
# Test evaluation at a specific value of y, for example y0 = 8.
y0 = 8
f_inv_value = f_inv.subs(y, y0)
f_inv_derivative_value = f_inv_prime.subs(y, y0)
reciprocal_value = reciprocal_formula.subs(y, y0)
print("\nEvaluation at y =", y0)
print("f^{-1}({}) = {}".format(y0, f_inv_value))
print("(f^{-1})'({}) = {}".format(y0, f_inv_derivative_value))
print("1 / f'(f^{-1}({})) = {}".format(y0, reciprocal_value))
88
Chapter 14
Higher Order
Derivatives and
Applications
Definition and Notation
Let f : I → R be a function defined on an open interval I ⊂ R that
is differentiable at every point of I. The first derivative, denoted
by f ′ (x) or dx
d
f (x), encapsulates the instantaneous rate of change
of f at the point x. If the function f ′ is itself differentiable on I,
then the second derivative of f , denoted by f ′′ (x) or f (2) (x), is
defined by
d ′
f ′′ (x) = f (x) .
dx
More generally, if f is differentiable n times, the nth derivative of
f , denoted by f (n) (x), is defined recursively as
d (n−1)
f (n) (x) = f (x) ,
dx
with the convention that f (0) (x) = f (x). This notation and recur-
sive definition provide the framework necessary for analyzing the
behavior of functions at progressively finer scales.
89
Second Derivative: Concavity and Accel-
eration
The second derivative of a function holds special significance in the
analysis of its geometric and physical properties. In a purely geo-
metric setting, the sign of the second derivative at a point x ∈ I
determines the nature of the curvature of the graph of f . Specifi-
cally, if
f ′′ (x) > 0,
the graph of f is locally concave upward, indicating that the tan-
gent line at that point lies below the graph, which is typically
associated with a local minimum. Conversely, if
f ′′ (x) < 0,
the graph is locally concave downward, implying that the tangent
line at the point lies above the graph, a circumstance often linked
with a local maximum.
In physical contexts, when s(t) represents the position of a par-
ticle as a function of time t, the first derivative s′ (t) corresponds
to the velocity, and the second derivative s′′ (t) represents the ac-
celeration. The acceleration quantifies how velocity changes with
respect to time, and its sign and magnitude offer crucial insights
into the dynamics of motion. The rigorous interpretation of the
second derivative, therefore, not only characterizes the curvature
of a function’s graph but also serves as a fundamental descriptor
of acceleration in models of physical phenomena.
Higher Order Derivatives
Extending the concept of differentiation to orders beyond the sec-
ond derivative yields higher order derivatives, which provide an in-
creasingly nuanced local description of a function. For instance, the
third derivative, denoted by f (3) (x), measures the rate of change
of the acceleration (often interpreted as the "jerk" in kinematics),
while the fourth derivative, f (4) (x), further refines this description.
In the case of functions that are infinitely differentiable on I, the
Taylor series expansion around a point x0 ∈ I takes the form
∞
X f (n) (x0 )
f (x) = (x − x0 )n ,
n=0
n!
90
where each coefficient f (n) (x0 ) represents the influential role of the
nth derivative in approximating the function in a neighborhood of
x0 . The expansion vividly illustrates how higher order derivatives
contribute to a systematic and detailed understanding of the local
behavior of functions, lending themselves to significant applications
in both theoretical and applied analysis.
Applications in Analysis and Applied Con-
texts
Higher order derivatives appear naturally in various domains of
both pure and applied mathematics. In the study of optimization,
the second derivative test is a classical method for classifying criti-
cal points by examining the sign of f ′′ (x). However, in cases where
f ′ (x0 ) = 0 and f ′′ (x0 ) = 0, the investigation may extend to the
first nonzero derivative of order n > 2. The parity of n and the sign
of f (n) (x0 ) provide essential criteria for determining the nature of
the stationary point at x0 .
In physical applications, the successive derivatives of a function
describing motion capture increasingly detailed aspects of dynamic
behavior. For a position function s(t), while s′ (t) represents veloc-
ity and s′′ (t) represents acceleration, the third derivative s(3) (t),
and higher derivatives, depict more subtle phenomena such as the
rate of change of acceleration. This hierarchy of derivatives is in-
strumental in the modeling of complex physical systems, where the
precise quantification of motion and change is imperative.
Moreover, in the realm of differential geometry, the second
derivative is a critical component in the determination of curva-
ture and the analysis of inflection points on curves. Higher order
derivatives further contribute to understanding the intricate local
structure of functions and surfaces, often in the context of the Hes-
sian matrix in multivariable analysis. Such applications underscore
the deep interplay between the abstract theory of differentiation
and its practical manifestations in a variety of scientific disciplines.
Python Code Snippet
import sympy as sp
import numpy as np
import [Link] as plt
91
# Define the symbol and example function f(x) = exp(x) * sin(x)
x = [Link]('x')
f = [Link](x) * [Link](x)
# Compute first, second, and third derivatives symbolically
first_derivative = [Link](f, x)
second_derivative = [Link](f, x, 2)
third_derivative = [Link](f, x, 3)
print("f(x) =", [Link](f))
print("f'(x) =", [Link](first_derivative))
print("f''(x) =", [Link](second_derivative))
print("f'''(x) =", [Link](third_derivative))
# Function to compute the nth derivative symbolically of a given
,→ function
def nth_derivative(func, var, n):
"""
Recursively compute the nth derivative of func with respect to
,→ var.
"""
return [Link](func, var, n)
# Function to compute the Taylor series expansion of func around a
,→ point x0 up to order n
def taylor_series(func, var, x0, n):
"""
Returns the Taylor series expansion of 'func' around a point x0
,→ up to the nth order.
"""
series = 0
for i in range(n + 1):
derivative_i = nth_derivative(func, var, i)
term = (derivative_i.subs(var, x0) / [Link](i)) * (var
,→ - x0)**i
series += term
return [Link](series)
# Compute Taylor series expansion of the function f around x0 = 0 up
,→ to order 6.
x0 = 0
order = 6
taylor_approx = taylor_series(f, x, x0, order)
print("\nTaylor Series expansion of f(x) around x0 =", x0, "up to
,→ order", order, ":\n", taylor_approx)
# Convert symbolic expressions to numerical functions for further
,→ evaluation
f_numeric = [Link](x, f, 'numpy')
f_prime_numeric = [Link](x, first_derivative, 'numpy')
f_second_numeric = [Link](x, second_derivative, 'numpy')
92
# Evaluate the function and its derivatives at a specific point,
,→ e.g., x = 1.0
point = 1.0
print("\nEvaluation at x =", point)
print("f(1) =", f_numeric(point))
print("f'(1) =", f_prime_numeric(point))
print("f''(1) =", f_second_numeric(point))
# Define a function for performing the second derivative concavity
,→ test
def concavity_test(func_second, pt):
"""
Checks the concavity at a point 'pt' using the second
,→ derivative.
"""
value = func_second(pt)
if value > 0:
return "Concave Upward (local minimum candidate)"
elif value < 0:
return "Concave Downward (local maximum candidate)"
else:
return "Test inconclusive: possible inflection point"
print("\nConcavity test at x =", point, ":",
,→ concavity_test(f_second_numeric, point))
# Finite Difference Methods for numerical derivative approximations
def finite_diff_derivative(func, pt, h=1e-5):
"""
Approximates the first derivative of 'func' at point 'pt' using
,→ the centered finite difference method.
"""
return (func(pt + h) - func(pt - h)) / (2 * h)
finite_first = finite_diff_derivative(f_numeric, point)
finite_second = (f_numeric(point + 1e-5) - 2 * f_numeric(point) +
,→ f_numeric(point - 1e-5)) / (1e-5**2)
print("\nFinite Difference Approximation at x =", point)
print("Approximated f'(1) =", finite_first)
print("Approximated f''(1) =", finite_second)
# Visualization: Plot the original function and its Taylor series
,→ approximation
x_vals = [Link](-2, 2, 400)
f_vals = f_numeric(x_vals)
# Convert the Taylor series symbolic expression to a numerical
,→ function
taylor_func = [Link](x, taylor_approx, 'numpy')
taylor_vals = taylor_func(x_vals)
[Link](figsize=(8, 6))
[Link](x_vals, f_vals, label='f(x) = exp(x)*sin(x)', color='blue')
93
[Link](x_vals, taylor_vals, label='Taylor Approximation (order
,→ {})'.format(order), linestyle='--', color='red')
[Link]('x')
[Link]('y')
[Link]('Function and its Taylor Series Approximation')
[Link]()
[Link](True)
[Link]()
94
Chapter 15
Graphical Analysis
Using Derivatives
The First Derivative Test and Critical Point
Analysis
Let f : I → R be a function defined on an interval I ⊂ R that is
differentiable on its interior. Critical points occur at those values
x0 ∈ I for which f ′ (x0 ) = 0 or where f ′ fails to exist. The first
derivative, f ′ (x), encapsulates the instantaneous rate of change of
f and plays an essential role in determining the monotonic behavior
of the function. In regions where f ′ (x) maintains a constant sign,
the function either increases or decreases monotonically. A change
in the sign of f ′ (x) about a critical point provides insight into the
local extremal nature of f .
More precisely, assume that there exists an ε > 0 such that the
intervals (x0 −ε, x0 ) and (x0 , x0 +ε) lie within I. If f ′ is continuous
at x0 and satisfies
f ′ (x) > 0 for x ∈ (x0 −ε, x0 ) and f ′ (x) < 0 for x ∈ (x0 , x0 +ε),
then the function attains a local maximum at x0 . Conversely, if
f ′ (x) < 0 for x ∈ (x0 −ε, x0 ) and f ′ (x) > 0 for x ∈ (x0 , x0 +ε),
a local minimum is inferred at that critical point. The rigorous
verification of these properties depends on the application of the
first derivative test, which systematically analyzes sign variations
95
of f ′ (x) in the vicinity of a critical point. Such analyses yield robust
information regarding the structure of the graph of f , furnishing
pivotal data that serve as a foundation for subsequent graphical
reconstructions.
The Second Derivative Test and Concav-
ity
The investigation of the second derivative, denoted by f ′′ (x), intro-
duces the notion of concavity and furnishes an alternative mecha-
nism for classifying the behavior at critical points. Recall that the
second derivative is defined by
d ′
f ′′ (x) = f (x) ,
dx
and it describes the manner in which the rate of change of f is
itself changing. The sign of f ′′ (x) offers a clear criterion for the
concavity of the function. Specifically, if f ′′ (x) > 0 on an interval,
then f is said to be concave upward there, implying that the graph
of f bends upward and that any tangent line lies below the graph.
In contrast, if f ′′ (x) < 0, the function is concave downward, and
the graph bends downward with tangent lines positioned above the
curve.
In the context of a critical point x0 where f ′ (x0 ) = 0, examina-
tion of f ′′ (x0 ) yields further classification. If f ′′ (x0 ) > 0, then the
increase in the slope indicates a local minimum at x0 ; if f ′′ (x0 ) < 0,
a local maximum is suggested. It is important to note that when
f ′′ (x0 ) = 0, the test becomes inconclusive, necessitating higher or-
der derivative analyses or alternative methods in these cases. The
interplay between f ′ and f ′′ extends beyond the mere classification
of isolated points; it also permits a detailed understanding of the
overall curvature of f , thus enriching the portrait of the function’s
behavior across its domain.
Enhanced Graph Sketching Techniques
The synthesis of conclusions drawn from both the first and second
derivative tests provides extensive insight into the graphical struc-
ture of a function. By compiling information regarding intervals of
monotonicity and regions of concavity, an accurate outline of the
96
function’s graph may be constructed. The identification of critical
points, combined with the use of sign charts for f ′ (x) and f ′′ (x),
allows for the precise determination of local extrema and inflection
points.
Let f be continuously differentiable, and let the critical points
and inflection points be determined through the equations f ′ (x) =
0 and the equality f ′′ (x) = 0 (with appropriate sign changes),
respectively. The determination of intervals where f ′ (x) is pos-
itive or negative not only reveals regions of increasing and de-
creasing behavior but also establishes the baselines upon which
local maxima or minima occur. Simultaneously, the regions where
f ′′ (x) retains a consistent sign corroborate the shape of these seg-
ments—confirming whether the graph exhibits a concave upward
or concave downward formation.
The detailed analysis derived from these derivative tests leads
to a comprehensive map that guides the manual sketching of the
graph. In practice, once the critical points have been determined,
further refinement through the evaluation of f at these points and
the determination of asymptotic behavior (where applicable) con-
tribute to the high fidelity of the sketch. The resulting diagram
illustrates not only the local extrema and inflection points but also
the underlying curvature and overall global behavior of the func-
tion.
This methodology underscores the intrinsic value of derivative-
based techniques in graphing, ensuring that the qualitative and
quantitative features of a function are meticulously rendered. The
approach, rooted in rigorous mathematical analysis, ultimately fa-
cilitates a more profound comprehension of functional behavior, a
comprehension that is essential for the deeper study of real anal-
ysis and its diverse applications in both theoretical and applied
contexts.
Python Code Snippet
# Comprehensive Python Code Snippet for Graphical Analysis Using
,→ Derivatives
# This code demonstrates the implementation of the First and Second
,→ Derivative Tests,
# along with enhanced graph sketching techniques. It computes
,→ derivatives,
# finds critical points, analyzes sign changes, and visualizes the
,→ function.
97
import sympy as sp
import numpy as np
import [Link] as plt
def main():
# Declare the symbol and define the function f(x)
x = [Link]('x')
# Example function: f(x) = x^3 - 3*x^2 + 2
f = x**3 - 3*x**2 + 2
# Compute the first derivative: f'(x) = df/dx
f_prime = [Link](f, x)
# Compute the second derivative: f''(x) = d^2f/dx^2
f_double = [Link](f_prime, x)
print("Function: f(x) =", f)
print("First Derivative f'(x) =", [Link](f_prime))
print("Second Derivative f''(x) =", [Link](f_double))
# Solve for critical points where f'(x)=0 (or f' is undefined)
crit_points = [Link](f_prime, x, domain=[Link])
crit_points_list = list(crit_points)
crit_points_list.sort() # Ensure consistent ordering of
,→ critical points
print("\nCritical Points (from f'(x) = 0):", crit_points_list)
# Set a small epsilon for numerical evaluation around the
,→ critical points
epsilon = 1e-5
# Analyze each critical point with First and Second Derivative
,→ Tests
for cp in crit_points_list:
cp_val = float(cp)
f_val = [Link](x, cp)
f_prime_val = f_prime.subs(x, cp)
f_double_val = f_double.subs(x, cp)
print("\nEvaluating at critical point: x =", cp_val)
print("f(x) =", f_val)
print("f'(x) =", f_prime_val)
print("f''(x) =", f_double_val)
# First Derivative Test: Examine sign of f'(x) on either
,→ side of cp
left_val = f_prime.subs(x, cp - epsilon)
right_val = f_prime.subs(x, cp + epsilon)
print("f'(x) just left of cp (x = {}): {}".format(cp_val -
,→ epsilon, left_val))
print("f'(x) just right of cp (x = {}): {}".format(cp_val +
,→ epsilon, right_val))
if left_val > 0 and right_val < 0:
98
print("First Derivative Test: Local Maximum at x =",
,→ cp_val)
elif left_val < 0 and right_val > 0:
print("First Derivative Test: Local Minimum at x =",
,→ cp_val)
else:
print("First Derivative Test: Inconclusive at x =",
,→ cp_val)
# Second Derivative Test: Use f''(x) for further
,→ classification
if f_double_val > 0:
print("Second Derivative Test: Indicates Local Minimum
,→ at x =", cp_val)
elif f_double_val < 0:
print("Second Derivative Test: Indicates Local Maximum
,→ at x =", cp_val)
else:
print("Second Derivative Test: Inconclusive at x =",
,→ cp_val)
# Enhanced Graph Sketching: Plot f(x) and f'(x) along with
,→ critical points
f_numeric = [Link](x, f, 'numpy')
f_prime_numeric = [Link](x, f_prime, 'numpy')
# Define the domain for plotting using the critical points as
,→ reference
x_min = float(min(crit_points_list)) - 2
x_max = float(max(crit_points_list)) + 2
x_vals = [Link](x_min, x_max, 400)
y_vals = f_numeric(x_vals)
y_prime_vals = f_prime_numeric(x_vals)
[Link](figsize=(10, 6))
[Link](x_vals, y_vals, label='$f(x)$', color='blue')
[Link](x_vals, y_prime_vals, label="$f'(x)$", color='red',
,→ linestyle='--')
[Link](0, color='black', linewidth=0.5)
# Mark the critical points on the graph
crit_x = [float(cp) for cp in crit_points_list]
crit_y = [float([Link](x, cp)) for cp in crit_points_list]
[Link](crit_x, crit_y, color='green', zorder=5,
,→ label='Critical Points')
[Link]("Graphical Analysis: f(x) and its First Derivative
,→ f'(x)")
[Link]("x")
[Link]("y")
[Link]()
[Link](True)
[Link]()
99
if __name__ == "__main__":
main()
100
Chapter 16
Mean Value Theorem
and Its Consequences
Statement of the Mean Value Theorem
Let f : [a, b] → R be a function which is continuous on the closed
interval [a, b] and differentiable on the open interval (a, b). Under
these hypotheses, the Mean Value Theorem asserts that there exists
at least one point c ∈ (a, b) such that
f (b) − f (a)
f ′ (c) = .
b−a
This equation signifies that the instantaneous rate of change at
the point c equals the average rate of change of f over the inter-
val [a, b]. The continuity of f on [a, b] ensures that the function
does not exhibit any discontinuities between the endpoints, while
differentiability on (a, b) guarantees the existence of a well-defined
tangent at every interior point. These conditions are not merely
technical; they play an essential role in the subsequent analysis and
proof.
Proof of the Mean Value Theorem
Define an auxiliary function g : [a, b] → R by
f (b) − f (a)
g(x) = f (x) − (x − a).
b−a
101
The function g is continuous on [a, b] and differentiable on (a, b)
since it is constructed from functions having these properties. A
straightforward calculation yields
f (b) − f (a)
g(a) = f (a) − (a − a) = f (a),
b−a
and
f (b) − f (a)
g(b) = f (b) − (b − a) = f (b) − f (b) − f (a) = f (a).
b−a
Thus, g(a) = g(b). By invoking Rolle’s Theorem, there exists a
point c ∈ (a, b) where the derivative g ′ (c) vanishes. Computing the
derivative, one obtains
f (b) − f (a)
g ′ (x) = f ′ (x) − .
b−a
At the point c, the equality g ′ (c) = 0 implies that
f (b) − f (a)
f ′ (c) = ,
b−a
which completes the proof of the Mean Value Theorem.
Implications for the Behavior of Functions
and Rates of Change
The Mean Value Theorem serves as a fundamental bridge between
the local behavior of a function and its global behavior on an in-
terval. The equality
f (b) − f (a)
f ′ (c) =
b−a
establishes that at some point in (a, b) the instantaneous rate of
change is representative of the overall average change across the
entire interval. This result yields several significant consequences.
Firstly, if the derivative f ′ maintains a constant sign on (a, b),
then the function f exhibits monotonic behavior on [a, b]. In par-
ticular, if f ′ (x) ≥ 0 for all x ∈ (a, b), then the function is nonde-
creasing on the interval; if f ′ (x) > 0 on (a, b), then f is strictly in-
creasing. A similar conclusion holds if f ′ is nonpositive or strictly
102
negative. Moreover, the special case where f ′ (x) = 0 for every
x ∈ (a, b) immediately implies, via repeated applications of the
Mean Value Theorem, that f is constant on [a, b].
Secondly, the theorem provides a mechanism for estimating the
range of a function based on bounds for its derivative. Suppose that
in a certain interval the derivative of f is known to be bounded in
magnitude by a constant M , that is, |f ′ (x)| ≤ M for all x ∈ (a, b).
Then, for any x, y ∈ [a, b], the Mean Value Theorem ensures that
|f (y) − f (x)| = |f ′ (ξ)||y − x| ≤ M |y − x|
for some ξ between x and y. Such inequalities are instrumental in
the analysis of error estimates and in the study of uniform conti-
nuity.
Finally, the relationship established by the Mean Value Theo-
rem underscores the deep connection between an analytic descrip-
tion of a function and its geometric representation. The existence
of a point c where the tangent line to the curve of f parallels the
secant line through (a, f (a)) and (b, f (b)) not only demonstrates
a unifying property of differentiable functions but also provides a
powerful tool for further investigations in real analysis. The theo-
rem is central to proofs of various fundamental results, such as the
validity of Taylor’s Theorem with remainder, and it has profound
implications for the study of convergence, stability, and approxi-
mation in both theoretical and applied contexts.
Python Code Snippet
import numpy as np
import [Link] as plt
from [Link] import newton
import sympy as sp
# Define the function f both numerically and symbolically.
# For demonstration, we use f(x) = x^2, which is continuous and
,→ differentiable everywhere.
def f_numeric(x):
return x**2 # Example function; you may change it to any
,→ differentiable function
# Symbolic definition for analytical operations
x = [Link]('x')
f_sym = x**2
# Define the interval [a, b]
103
a = 1.0
b = 4.0
# Compute f(a) and f(b)
fa = f_numeric(a)
fb = f_numeric(b)
# Calculate the average rate of change (slope of the secant line)
,→ using the Mean Value Theorem formula:
# f'(c) = (f(b) - f(a)) / (b - a)
average_slope = (fb - fa) / (b - a)
print("Average rate of change (secant slope):", average_slope)
# Symbolically compute the derivative f'(x)
f_prime_sym = [Link](f_sym, x)
print("Symbolic derivative f'(x):", f_prime_sym)
# Solve for c in (a,b) so that f'(c) equals the average slope.
# That is, find c such that: f'(c) = (f(b)-f(a))/(b-a)
c_solutions = [Link]([Link](f_prime_sym, average_slope), x)
# Filter solutions that lie in the open interval (a,b)
c_symbolic = [sol for sol in c_solutions if sol > a and sol < b]
print("Symbolic solution for c in (a, b):", c_symbolic)
# Choose the first valid solution as our c value (if any)
if c_symbolic:
c_value_sym = float(c_symbolic[0])
else:
c_value_sym = None
print("Chosen symbolic c value:", c_value_sym)
# Define a numerical derivative using the central difference method
def numerical_derivative(func, x_val, h=1e-5):
return (func(x_val + h) - func(x_val - h)) / (2 * h)
# Define the function h(x) = f'(x) - average_slope,
# where f'(x) is approximated numerically.
def h_func(x_val):
return numerical_derivative(f_numeric, x_val) - average_slope
# Use Newton's method to numerically solve h(x) = 0 for c, with an
,→ initial guess at the midpoint.
initial_guess = (a + b) / 2.0
c_numerical = newton(h_func, initial_guess)
print("Numerical solution for c using Newton's method:",
,→ c_numerical)
print("f'(c) computed numerically =",
,→ numerical_derivative(f_numeric, c_numerical))
print("Average slope =", average_slope)
# Visualization
# Generate x values for plotting that cover a bit beyond the
,→ interval [a,b]
104
x_vals = [Link](a - 1, b + 1, 400)
f_vals = f_numeric(x_vals)
# Define the secant line connecting (a, f(a)) and (b, f(b))
secant_line = fa + average_slope * (x_vals - a)
[Link](figsize=(8, 6))
[Link](x_vals, f_vals, label='f(x) = x^2', color='blue')
[Link](x_vals, secant_line, label='Secant line from (a, f(a)) to
,→ (b, f(b))',
color='green', linestyle='--')
[Link]([a, b], [fa, fb], color='red', zorder=5,
label='Endpoints (a, f(a)) and (b, f(b))')
# Plot the tangent line at the computed c value (if available)
if c_value_sym is not None:
tangent_line = f_numeric(c_value_sym) +
,→ numerical_derivative(f_numeric, c_value_sym) * (x_vals -
,→ c_value_sym)
[Link](x_vals, tangent_line, label='Tangent at c',
,→ color='magenta', linestyle=':')
[Link]([c_value_sym], [f_numeric(c_value_sym)],
,→ color='black', zorder=5,
label="c where f'(c) = secant slope")
[Link]('Illustration of the Mean Value Theorem')
[Link]('x')
[Link]('f(x)')
[Link]()
[Link](True)
[Link]()
105
Chapter 17
Increasing and
Decreasing Functions
Preliminaries and Definitions
Let f : I → R be a function defined on an interval I ⊆ R. The
function f is said to be increasing on I if for every x, y ∈ I with
x < y it holds that
f (x) ≤ f (y).
In the case that the inequality is strict, that is, f (x) < f (y) for all
x, y ∈ I with x < y, the function is described as strictly increasing.
Analogously, the function f is decreasing on I if for all x, y ∈ I
with x < y one has
f (x) ≥ f (y),
and it is termed strictly decreasing when f (x) > f (y) under the
same condition. A function which is neither exclusively increasing
nor decreasing may exhibit segments of each behavior, and these
segments are determined via the sign of its derivative, when such
exists.
Critical in the study of monotonicity is the derivative of f .
When f is differentiable on an open subset of I, the sign of the
derivative f ′ (x) provides an effective criterion for determining in-
tervals of monotonic behavior. In particular, if f ′ (x) is positive
for all x in a subinterval of I, then f is strictly increasing on that
subinterval; if f ′ (x) is negative, then f is strictly decreasing. When
f ′ (x) vanishes or fails to exist, the corresponding points are desig-
nated as critical points.
106
Monotonicity via the Derivative
For a function f that is differentiable on an interval I, the Mean
Value Theorem guarantees that the derivative serves as a local
indicator of change. More precisely, if f ′ (x) > 0 for all x in an
open subinterval J ⊂ I, then for any two points x1 , x2 ∈ J with
x1 < x2 it follows that
f (x2 ) − f (x1 ) = f ′ (ξ)(x2 − x1 ) > 0,
for some ξ ∈ (x1 , x2 ). This result is a direct consequence of the
Mean Value Theorem and underscores the fact that a consistently
positive derivative implies strictly increasing behavior of the func-
tion on J. Similarly, if f ′ (x) < 0 for all x ∈ J, then f is strictly
decreasing on that subinterval.
The situation where f ′ (x) = 0 identically on an interval merits
particular attention. Under this circumstance, the function f is
constant on that interval by virtue of the Mean Value Theorem.
Thus, the uniform sign of the derivative plays a decisive role in
establishing the monotonicity of f .
Critical Points and Their Analysis
A point c ∈ I is defined to be a critical point of f if either f ′ (c) =
0 or f ′ (c) is undefined. Critical points are of significant interest
because they are the candidates around which the function may
experience a change in monotonic behavior. The First Derivative
Test provides a powerful tool in analyzing such behavior. Suppose
that c is an interior point of I and that f is differentiable on each
of the subintervals I1 = (a, c) and I2 = (c, b), where a, c, b ∈ I
with a < c < b. If the derivative f ′ (x) transitions from positive on
I1 to negative on I2 , then c is a point at which f attains a local
maximum. Conversely, if f ′ (x) changes from negative to positive
across c, then a local minimum is present at c. When the sign
of f ′ (x) remains unchanged on either side of c, such a point may
correspond to a plateau or to an inflection in the sense of having a
higher order of contact with the horizontal.
The analysis of critical points involves a careful verification of
the behavior of f in the vicinity of these points. In many instances,
the determination of monotonicity is facilitated by partitioning the
domain into subintervals separated by the critical values. Subse-
quent examination of the sign of f ′ on each subinterval affords a
107
complete characterization of the intervals where f is increasing,
decreasing, or constant. In this manner, the derivative provides a
precise instrument for identifying quantitative changes in the rate
of variation of f .
Methodology for Identifying Intervals of
Monotonicity
Given a function f that is continuously differentiable on an interval
I, the standard methodology for discerning its intervals of increase
and decrease commences with the determination of the set
{x ∈ I | f ′ (x) = 0 or f ′ (x) is undefined}.
The elements of this set serve as the boundaries of the subintervals
over which the sign of the derivative is invariant. On each resulting
subinterval, a representative point is chosen to test the sign of
f ′ (x). A positive value indicates that f is strictly increasing on
that subinterval, while a negative value indicates that f is strictly
decreasing. This process not only localizes the monotonic behavior
of f but also illuminates the nature of each critical point in relation
to local extrema.
The above framework is intrinsically tied to the rigorous un-
derpinnings of real analysis. Each step in the methodology is sup-
ported by classical results, and it reinforces the connection be-
tween differential calculus and the qualitative behavior of func-
tions. Through a detailed examination of the derivative of f , the
structure of its graph is elucidated, and the overall behavior of the
function is rendered comprehensible within the rigorous confines of
mathematical analysis.
Python Code Snippet
import sympy as sp
import numpy as np
import [Link] as plt
# ----------------------------------------------------------
# This script demonstrates key concepts from the chapter on
,→ Increasing and
# Decreasing Functions. In particular, it:
# - Defines a function f(x) and computes its derivative f'(x).
108
# - Finds the critical points where f'(x)=0 in a given domain.
# - Analyzes monotonicity based on the sign of the derivative.
# - Uses the Mean Value Theorem idea: For any x1, x2 in an
,→ interval with
# f'(x) > 0 (or < 0), f(x2) - f(x1) = f'(\xi)(x2 - x1) > 0 (or <
,→ 0).
# - Plots the function and its derivative, marking the critical
,→ points.
#
# Important equations illustrated:
# f(x2) - f(x1) = f'(\xi) (x2-x1) for some xi in (x1, x2)
# If f' > 0 then f is strictly increasing and if f' < 0 then f is
,→ strictly decreasing.
# ----------------------------------------------------------
def find_critical_points(f, x, domain_interval=(-10, 10)):
"""
Computes the derivative f'(x) and finds the critical points
(where f'(x)=0) within the given domain interval.
"""
# Compute the derivative
fprime = [Link](f, x)
# Solve for f'(x) = 0 over the specified interval using Sympy's
,→ solveset.
interval = [Link](domain_interval[0], domain_interval[1])
crit_set = [Link](fprime, x, domain=interval)
# Convert the set to a sorted list of floats
critical_points = list(crit_set)
critical_points = sorted([sp.N(pt) for pt in critical_points])
return fprime, critical_points
def analyze_monotonicity(f, x, critical_points,
,→ domain_interval=(-10, 10)):
"""
Partitions the domain into subintervals defined by the critical
,→ points and
evaluates the sign of the derivative in each subinterval.
Returns a list of tuples: (left_endpoint, right_endpoint,
,→ behavior), where:
- behavior is "Increasing" if f'(x) > 0 on the subinterval,
"Decreasing" if f'(x) < 0, and "Constant/Undetermined"
,→ otherwise.
"""
intervals = []
a, b = domain_interval
# Create partition points: domain endpoints and the critical
,→ points within
partition = [a] + critical_points + [b]
109
# Get the derivative function
fprime = [Link](f, x)
# Test the sign of the derivative in each subinterval by
,→ choosing a test point (midpoint)
for i in range(len(partition) - 1):
left = partition[i]
right = partition[i + 1]
test_point = (left + right) / 2
# Evaluate derivative at the test point
sign_val = sp.N([Link](x, test_point))
if sign_val > 0:
behavior = "Increasing"
elif sign_val < 0:
behavior = "Decreasing"
else:
behavior = "Constant/Undetermined"
[Link]((left, right, behavior))
return intervals
def plot_function_and_derivative(f, x, domain_interval=(-10, 10),
,→ critical_points=[]):
"""
Plots the function f(x) and its derivative f'(x) on the
,→ specified domain.
Critical points are marked on the graph.
"""
# Convert sympy expressions to numerical functions using
,→ lambdify.
f_lambd = [Link](x, f, 'numpy')
fprime = [Link](f, x)
fprime_lambd = [Link](x, fprime, 'numpy')
a, b = domain_interval
x_vals = [Link](a, b, 400)
f_vals = f_lambd(x_vals)
fprime_vals = fprime_lambd(x_vals)
[Link](figsize=(10, 6))
[Link](x_vals, f_vals, label='f(x)', color='blue')
[Link](x_vals, fprime_vals, label="f'(x)", linestyle='--',
,→ color='orange')
# Mark the critical points on f(x)
for cp in critical_points:
cp_val = f_lambd(cp)
[Link](cp, cp_val, 'ro')
[Link](f"({cp:.2f}, {cp_val:.2f})", (cp, cp_val),
textcoords="offset points", xytext=(0,10),
,→ ha='center')
[Link]('x')
110
[Link]('y')
[Link]("Function f(x) and its Derivative f'(x)")
[Link]()
[Link](True)
[Link]()
if __name__ == "__main__":
# Define the symbolic variable and example function:
x = [Link]('x')
# Example function: f(x) = x^3 - 3*x + 1
f = x**3 - 3*x + 1
# Define the domain for analysis
domain_interval = (-5, 5)
# Compute the derivative and critical points in the domain
fprime, critical_points = find_critical_points(f, x,
,→ domain_interval)
print("Function f(x):", f)
print("Derivative f'(x):", [Link](fprime))
print("Critical points in the interval {}:
,→ {}".format(domain_interval, critical_points))
# Analyze monotonicity based on critical points and derivative
,→ signs
intervals = analyze_monotonicity(f, x, critical_points,
,→ domain_interval)
print("\nMonotonicity Interval Analysis:")
for inter in intervals:
left, right, behavior = inter
print("Interval [{:.2f}, {:.2f}]: {}".format(left, right,
,→ behavior))
# Plot the function and its derivative along with the critical
,→ points
plot_function_and_derivative(f, x, domain_interval,
,→ critical_points)
111
Chapter 18
Concavity, Inflection
Points, and Curve
Sketching
Concavity and Second Derivative Analy-
sis
1 Definition and Characterization
Let f : I → R be a function defined on an interval I ⊆ R. The
function is said to be concave upward on a subinterval J ⊆ I if, for
every x ∈ J, the second derivative satisfies
f ′′ (x) > 0.
This condition implies that the rate of change of the first derivative
f ′ (x) is positive, indicating that the slopes of the tangent lines to
the graph of f increase as x increases. Consequently, the graph of f
lies above its tangent lines, and any chord connecting two distinct
points of the graph is situated below the curve.
Conversely, the function is termed concave downward on J if
f ′′ (x) < 0 for all x ∈ J.
In this scenario, the first derivative is decreasing over J, so that the
graph of f lies below its tangent lines and any chord joining two
points on the graph lies above the curve. The magnitude and sign
112
of f ′′ (x) serve as precise indicators of the curvature and provide a
quantifiable measure of the bending of the graph.
2 Analytical Insights Through Taylor Expansion
A rigorous insight into the nature of concavity is afforded by the
second-order Taylor expansion of f about a point x0 ∈ I, which is
expressed as
1
f (x0 + h) = f (x0 ) + f ′ (x0 )h + f ′′ (x0 )h2 + o(h2 ),
2
where h denotes a small increment and o(h2 ) represents the higher-
order terms. In the vicinity of x0 , the quadratic term 21 f ′′ (x0 )h2
dominates the deviation from the linear approximation. The sign
of f ′′ (x0 ), therefore, determines whether the local approximation
curves upward or downward, which directly relates to the definition
of concavity. This expansion underscores the intrinsic relationship
between the second derivative and the curvature of f .
Inflection Points: Definitions and Crite-
ria
An inflection point is a point on the graph of f at which a transition
between concave upward and concave downward behavior occurs.
Formally, a point c ∈ I is an inflection point if there exists a neigh-
borhood (c − δ, c + δ), for some δ > 0, such that f ′′ (x) changes sign
as x passes through c. Although a necessary condition for such a
change is often that
f ′′ (c) = 0,
this equality alone does not guarantee the existence of an inflection
point; it is the actual change in the sign of f ′′ (x) on intervals to
the left and right of c that is decisive.
The determination of inflection points requires a careful demar-
cation of the domain into subintervals on which the sign of f ′′ (x)
is invariant. Points where f ′′ (x) either vanishes or fails to exist
must be scrutinized by testing the behavior of f ′′ (x) in arbitrarily
small intervals surrounding those points. The confirmation of a
sign change validates that c is a true inflection point of f , thereby
enriching the understanding of the function’s geometric properties.
113
Techniques for Curve Sketching Via Sec-
ond Derivative Analysis
The synthesis of information derived from both the first and second
derivatives is crucial in achieving an accurate sketch of the graph
of f . The procedure begins with the identification of critical points
and the partitioning of the domain, followed by the application
of second derivative analysis to ascertain the intervals where the
function is concave upward or concave downward. The precise
location of inflection points, as determined by the change in the
sign of f ′′ (x), further refines the portrait of the graph.
On each subinterval over which f ′′ (x) maintains a consistent
sign, the function exhibits a uniform curvature behavior. Regions
where f ′′ (x) is positive confirm that the graph is bending upward,
while regions where f ′′ (x) is negative denote a downward bend.
These curvature attributes are instrumental when combined with
information from the first derivative; for instance, the identification
of local extrema is greatly aided by noting whether these extrema
occur in regions of particular concavity.
The concerted analysis of the derivative data transforms the
process of curve sketching into one that is both methodical and
precise. The curvature indicated by f ′′ (x) provides an additional
layer of detail that clarifies the behavior of f , especially in the
vicinity of points where the first derivative vanishes or undergoes
rapid variation. By partitioning the domain based on the con-
stancy of the sign of f ′′ (x) and marking the inflection points, a
more complete and nuanced graph of f is obtained. This approach
facilitates a faithful replication of the function’s intrinsic geometry
and enhances the overall reliability of the sketch.
Python Code Snippet
import numpy as np
import sympy as sp
import [Link] as plt
# Define the symbolic variable and function
x = [Link]('x')
# Sample function: f(x) = x^3 - 3x^2 + 2
f_expr = x**3 - 3*x**2 + 2
# Compute the first and second derivatives symbolically
114
f_prime_expr = [Link](f_expr, x)
f_double_expr = [Link](f_expr, x, 2)
# Solve for inflection points where the second derivative equals
,→ zero
inflection_points = [Link](f_double_expr, x)
# Print the symbolic expressions and inflection point(s)
print("Function f(x):", f_expr)
print("First derivative f'(x):", f_prime_expr)
print("Second derivative f''(x):", f_double_expr)
print("Inflection Point(s):", inflection_points)
# Convert symbolic expressions to numerical functions for plotting
,→ and evaluation
f_num = [Link](x, f_expr, 'numpy')
f_prime_num = [Link](x, f_prime_expr, 'numpy')
f_double_num = [Link](x, f_double_expr, 'numpy')
def taylor_second_order(expr, a):
"""
Compute the second-order Taylor polynomial (quadratic
,→ approximation) of a given
symbolic expression 'expr' around the point x = a.
The formula used is:
T_2(x) = f(a) + f'(a)*(x - a) + 0.5 * f''(a)*(x - a)^2
"""
f_a = [Link](x, a)
f_prime_a = [Link](expr, x).subs(x, a)
f_double_a = [Link](expr, x, 2).subs(x, a)
T2 = f_a + f_prime_a * (x - a) + [Link](1, 2) * f_double_a
,→ * (x - a)**2
return [Link](T2)
# Choose a point for the Taylor expansion; here, a = 2 (a critical
,→ point where f'(2)=0 and f''(2)>0)
a = 2
T2_expr = taylor_second_order(f_expr, a)
print("\nSecond-Order Taylor Expansion around x = {}:".format(a))
print(T2_expr)
# Lambdify the Taylor expansion for numerical evaluation
T2_num = [Link](x, T2_expr, 'numpy')
# Define a domain for numerical evaluation and plotting
x_vals = [Link](-1, 4, 400)
y_vals = f_num(x_vals)
y_taylor = T2_num(x_vals)
y_double = f_double_num(x_vals)
# Plot the function f(x) and its second-order Taylor approximation
[Link](figsize=(10, 6))
115
[Link](x_vals, y_vals, label="f(x) = x^3 - 3x^2 + 2",
,→ color="blue")
[Link](x_vals, y_taylor, label="Taylor Approximation at x =
,→ {}".format(a),
color="red", linestyle="--")
# Mark the inflection point(s) on the graph
for pt in inflection_points:
pt_val = float(pt)
[Link](x=pt_val, color="green", linestyle=":",
label="Inflection Point at x =
,→ {:.2f}".format(pt_val))
[Link](pt_val, f_num(pt_val), "ko",
label="f({:.2f}) = {:.2f}".format(pt_val,
,→ f_num(pt_val)))
# Annotate concavity regions:
# For f(x) = x^3 - 3x^2 + 2, the second derivative is f''(x) = 6x -
,→ 6.
# Therefore, the function is concave downward (f''(x) < 0) when x <
,→ 1,
# and concave upward (f''(x) > 0) when x > 1.
[Link](-1, 1, color="orange", alpha=0.1, label="Concave Down
,→ (f''(x) < 0)")
[Link](1, 4, color="cyan", alpha=0.1, label="Concave Up (f''(x)
,→ > 0)")
[Link]("Curve Sketching: Concavity, Inflection Points, and Taylor
,→ Expansion")
[Link]("x")
[Link]("f(x)")
[Link](loc="best")
[Link](True)
[Link]()
if __name__ == "__main__":
pass
116
Chapter 19
Optimization Problems
Critical Points and Necessary Conditions
for Optimality
Let f : I → R be a function defined on an interval I ⊆ R with
appropriate smoothness conditions. The search for extrema com-
mences with the identification of candidate points, known as crit-
ical points. A point x0 ∈ I qualifies as a critical point if either
f ′ (x0 ) = 0 or f ′ fails to exist at x0 . In the context of differentiable
functions, the condition
f ′ (x0 ) = 0
serves as a necessary condition for x0 to be a local extremum. The
critical points, therefore, emerge as natural candidates for local
maxima or minima. The establishment of these candidates is fun-
damental to the derivative-based analysis of optimization problems.
Local Extrema and the Second Derivative
Test
After isolating the critical points, the next phase involves classi-
fying the nature of these points through the use of second-order
derivative techniques. Suppose f is twice differentiable in a neigh-
borhood of a critical point x0 where f ′ (x0 ) = 0. The second deriva-
tive test asserts that if
f ′′ (x0 ) > 0,
117
the function exhibits concave upward behavior in the vicinity of
x0 , and accordingly, x0 is a local minimum. Conversely, if
f ′′ (x0 ) < 0,
the function displays concave downward behavior, thereby desig-
nating x0 as a local maximum. In circumstances where f ′′ (x0 ) = 0,
the second derivative test becomes inconclusive, mandating an ex-
amination of higher-order derivatives or alternative criteria. The
local behavior of f near x0 is further illuminated by considering
the Taylor series expansion,
f ′′ (x0 ) f ′′′ (x0 )
f (x) = f (x0 ) + (x − x0 )2 + (x − x0 )3 + · · · ,
2 6
which encapsulates the curvature characteristics of the function
around the critical point.
Global Optimization and Endpoint Anal-
ysis
The identification of global extrema necessitates a comprehensive
investigation that extends beyond internal critical points. When f
is defined on a closed and bounded interval, say [a, b], the extreme
value theorem guarantees the existence of absolute maximum and
minimum values. Thus, in addition to examining the critical points
within (a, b), one must also evaluate the function at the endpoints
a and b. Formally, if
f : [a, b] → R
is continuous, then
max{f (x) : x ∈ S ∪ {a, b}} and min{f (x) : x ∈ S ∪ {a, b}},
where S = {x ∈ (a, b) : f (x) = 0}, yield the global maximum
′
and minimum, respectively. The rigorous evaluation of these can-
didate points, derived from derivative considerations together with
boundary analysis, is essential for the resolution of optimization
problems within a compact domain.
Python Code Snippet
# Import necessary libraries for symbolic computation, numerical
,→ evaluation, and plotting
import sympy as sp
118
import numpy as np
import [Link] as plt
# Define the symbolic variable
x = [Link]('x')
# Define the function f(x) for optimization.
# For demonstration, we choose f(x) = x^3 - 3*x^2 + 4.
f = x**3 - 3*x**2 + 4
# Compute the first derivative f'(x)
f_prime = [Link](f, x)
print("First derivative f'(x):", [Link](f_prime))
# Compute the critical points by setting f'(x) = 0
critical_points = [Link](f_prime, x)
print("Critical Points:", critical_points)
# Compute the second derivative f''(x)
f_double_prime = [Link](f_prime, x)
print("Second derivative f''(x):", [Link](f_double_prime))
# Evaluate the second derivative at each critical point to classify
,→ their nature
for cp in critical_points:
second_deriv_value = f_double_prime.subs(x, cp)
if second_deriv_value > 0:
nature = "Local Minimum"
elif second_deriv_value < 0:
nature = "Local Maximum"
else:
nature = "Inconclusive (use higher-order tests or
,→ alternative criteria)"
print(f"At x = {cp}: f''(x) = {second_deriv_value} => {nature}")
# Example of global optimization on a closed interval [a, b]
# Here we set a = 0 and b = 3 for demonstration purposes
a_val = 0
b_val = 3
# Filter critical points that lie within the interval [a, b]
critical_points_interval = [cp for cp in critical_points if cp >=
,→ a_val and cp <= b_val]
print(f"Critical Points within the interval [{a_val}, {b_val}]:",
,→ critical_points_interval)
# Create a list of candidates including the endpoints and critical
,→ points within the interval
candidates = critical_points_interval + [a_val, b_val]
# Evaluate f(x) at each candidate point
candidate_values = [(cp, sp.N([Link](x, cp))) for cp in candidates]
print("Candidate points and their f(x) values:")
119
for cp, val in candidate_values:
print(f" x = {cp}, f(x) = {val}")
# Determine the global minimum and maximum based on the candidate
,→ evaluations
global_min = min(candidate_values, key=lambda t: t[1])
global_max = max(candidate_values, key=lambda t: t[1])
print(f"Global Minimum at x = {global_min[0]}, f(x) =
,→ {global_min[1]}")
print(f"Global Maximum at x = {global_max[0]}, f(x) =
,→ {global_max[1]}")
# Optional: Plot the function, the critical points, and the
,→ endpoints for visual understanding
# Create a numerical function from the symbolic expression
f_numeric = [Link](x, f, 'numpy')
# Define a range of x values for plotting, slightly extending beyond
,→ the interval [a, b]
x_vals = [Link](a_val - 1, b_val + 1, 400)
y_vals = f_numeric(x_vals)
# Plot the function
[Link](figsize=(8, 6))
[Link](x_vals, y_vals, label="$f(x)$", color="blue")
[Link]("x")
[Link]("$f(x)$")
[Link]("Visualization of $f(x) = x^3 - 3x^2 + 4$ with Critical
,→ Points and Endpoints")
[Link](True)
# Mark candidate points on the plot
for cp, val in candidate_values:
[Link](cp, val, 'ro') # plot as red dots
[Link](f"({cp}, {[Link](val, 2)})", xy=(cp, val),
,→ xytext=(5, -15),
textcoords="offset points",
,→ arrowprops=dict(arrowstyle="->", color="red"))
[Link]()
[Link]()
120
Chapter 20
Applications in
Motion: Velocity and
Acceleration
Mathematical Modeling of Motion
Physical motion is modeled by associating a continuously differen-
tiable function s : I → R with the position of a particle or object
over an interval I ⊆ R, where the independent variable t represents
time. In this framework, the function s(t) encodes the spatial lo-
cation of the object at each instant. This formulation permits
the rigorous analysis of motion by invoking the powerful methods
of differential calculus. The function s(t) is generally assumed to
possess the necessary smoothness properties so that its derivatives
exist and can accurately capture changes in the object’s position.
Velocity as the First Derivative of Posi-
tion
The concept of velocity arises naturally from the study of the rate
at which position changes with respect to time. Formally, the in-
stantaneous velocity at time t is defined by the derivative
ds
v(t) = (t),
dt
121
which expresses the limit of the average rate of change of posi-
tion over an infinitesimally small time interval. The velocity func-
tion v(t) encapsulates both the magnitude and direction of motion.
When s(t) is differentiable over the interval I, the value v(t) pro-
vides a local linear approximation for the change in position, guar-
anteeing that over a sufficiently short interval the displacement ∆s
is approximately equal to v(t)∆t. This derivative-based approach
not only formalizes the notion of speed and direction but also lays
the foundation for further analysis of dynamic behavior.
Acceleration as the Derivative of Velocity
The analysis of motion is deepened by considering the rate at which
the velocity changes. The instantaneous acceleration is defined as
the derivative of the velocity function with respect to time:
dv d2 s
a(t) = (t) = 2 (t).
dt dt
This second-order derivative measures the curvature of the position
function, indicating how the velocity evolves over time. A positive
value of a(t) indicates that the velocity is increasing, while a nega-
tive value signifies a decrease in velocity. The acceleration function
a(t) is central in characterizing the dynamic response of a particle
under the influence of varying forces. Its computation allows for
the assessment of not only instantaneous rates of change but also
serves as a key element in the formulation of differential equations
modeling physical systems.
Modeling Real-World Motion
In practical applications, the functions s(t), v(t), and a(t) assume
significant roles in modeling scenarios ranging from the motion of
celestial bodies to vehicular traffic dynamics. For instance, in an-
alyzing the motion of an automobile, the position function s(t)
may be subject to empirical data, and its first and second deriva-
tives provide insight into the vehicle’s speed and rate of acceler-
ation, respectively. In such contexts, the derivative v(t) = ds dt (t)
is employed to determine the instantaneous velocity at any given
moment, which is crucial for safety assessments and performance
2
evaluations. Similarly, the acceleration a(t) = ddt2s (t) is instru-
mental in understanding the forces acting upon the vehicle, such
122
as friction and air resistance, through the application of Newton’s
second law.
Mathematical analysis in this setting is often accompanied by
the study of limit processes and continuity conditions, ensuring
that the transition from average to instantaneous measurements is
both rigorous and reflective of physical realities. The derivative-
based approach offers a unifying principle that links abstract math-
ematical constructs to tangible physical quantities. In numerous
problems, the interplay between velocity and acceleration is exam-
ined by employing techniques such as the Mean Value Theorem,
which provides guarantees on the existence of intermediate rates
of change, or by considering the behavior of these functions under
various constraints imposed by initial conditions or external forces.
The precise mathematical formulation afforded by differential
calculus thus serves to illuminate the intricate relationships be-
tween position, velocity, and acceleration. In this manner, deriva-
tives not only quantify aspects of motion but also facilitate predic-
tive modeling and the calibration of systems subjected to dynamic
stimuli.
Python Code Snippet
# Import necessary libraries
import numpy as np
import sympy as sp
import [Link] as plt
# ---------------------------
# Symbolic definitions
# ---------------------------
# Define the symbol for time
t = [Link]('t')
# Define a sample position function s(t)
# For example, consider s(t) = 3*t**3 - 5*t**2 + 2*t + 1
s = 3*t**3 - 5*t**2 + 2*t + 1
# Compute the first derivative to get velocity v(t) = ds/dt
v = [Link](s, t)
# Compute the second derivative to get acceleration a(t) = d^2s/dt^2
a = [Link](s, t, 2)
# Output the symbolic expressions
print("Symbolic Position s(t):", s)
print("Symbolic Velocity v(t):", v)
123
print("Symbolic Acceleration a(t):", a)
# Convert symbolic expressions into numerical functions using
,→ lambdify
s_func = [Link](t, s, 'numpy')
v_func = [Link](t, v, 'numpy')
a_func = [Link](t, a, 'numpy')
# ---------------------------
# Numerical evaluation and plotting
# ---------------------------
# Create an array of time values for plotting
t_vals = [Link](0, 2, 400) # time interval from 0 to 2 seconds
# Evaluate position, velocity, and acceleration at these time values
s_vals = s_func(t_vals)
v_vals = v_func(t_vals)
a_vals = a_func(t_vals)
# ---------------------------
# Numerical differentiation using finite differences
# ---------------------------
def numerical_derivative(f, x, h=1e-5):
"""
Compute the first derivative of function f at point x using the
,→ central difference method.
"""
return (f(x + h) - f(x - h)) / (2 * h)
def numerical_second_derivative(f, x, h=1e-5):
"""
Compute the second derivative of function f at point x using the
,→ central difference method.
"""
return (f(x + h) - 2 * f(x) + f(x - h)) / (h ** 2)
# Define a specific point to evaluate numerical derivatives (for
,→ example, t0 = 1.0)
t0 = 1.0
v_numeric = numerical_derivative(s_func, t0)
a_numeric = numerical_second_derivative(s_func, t0)
print("\nNumerical velocity at t = {:.2f}: {:.5f}".format(t0,
,→ v_numeric))
print("Numerical acceleration at t = {:.2f}: {:.5f}".format(t0,
,→ a_numeric))
# ---------------------------
# Plotting position, velocity, and acceleration
# ---------------------------
[Link](figsize=(10, 8))
# Plot Position
124
[Link](3, 1, 1)
[Link](t_vals, s_vals, 'b', label='Position s(t)')
[Link]('Position vs Time')
[Link]('Time (t)')
[Link]('Position s(t)')
[Link]()
[Link](True)
# Plot Velocity
[Link](3, 1, 2)
[Link](t_vals, v_vals, 'r', label='Velocity v(t)')
[Link]('Velocity vs Time')
[Link]('Time (t)')
[Link]('Velocity v(t)')
[Link]()
[Link](True)
# Plot Acceleration
[Link](3, 1, 3)
[Link](t_vals, a_vals, 'g', label='Acceleration a(t)')
[Link]('Acceleration vs Time')
[Link]('Time (t)')
[Link]('Acceleration a(t)')
[Link]()
[Link](True)
plt.tight_layout()
[Link]()
# ---------------------------
# Mean Value Theorem Demonstration
# ---------------------------
# For a continuous and differentiable function, the Mean Value
,→ Theorem (MVT) states:
# There exists a point c in (a, b) such that
# f'(c) = (f(b) - f(a)) / (b - a)
# Here, we apply this to our position function s(t).
# Choose an interval [a_time, b_time]
a_time = 0.5
b_time = 1.5
# Compute the average rate of change over the interval
avg_rate = (s_func(b_time) - s_func(a_time)) / (b_time - a_time)
print("\nAverage rate of change between t = {:.2f} and t = {:.2f}:
,→ {:.5f}".format(a_time, b_time, avg_rate))
# Use the numerical velocity function to search for c where v(c)
,→ avg_rate
c_candidates = [Link](a_time, b_time, 1000)
v_candidates = v_func(c_candidates)
# Find the candidate where the absolute difference is minimized
c_index = [Link]([Link](v_candidates - avg_rate))
125
c_value = c_candidates[c_index]
print("According to the Mean Value Theorem, a point c in ({:.2f},
,→ {:.2f}) is approximately: {:.5f}".format(a_time, b_time,
,→ c_value))
print("Velocity at c, v(c) = {:.5f}".format(v_func(c_value)))
126
Chapter 21
L’Hopital’s Rule
Foundations of Indeterminate Forms
Indeterminate forms emerge when evaluating limits of the quotient
of two functions where the individual limits of the numerator and
the denominator fail to yield a determinate result. In many in-
stances, if
lim f (x) = 0 and lim g(x) = 0,
x→c x→c
or
lim f (x) = ±∞ and lim g(x) = ±∞,
x→c x→c
then the expression
f (x)
lim
x→c g(x)
is classified as an indeterminate form of type 00 or ∞
∞ , respectively.
The ambiguity inherent to these forms arises from the competing
rates at which the functions approach their limits. A delicate,
rigorous analysis that leverages differential calculus is necessary
in order to resolve these uncertainties. In many cases, alternative
forms such as 0·∞, ∞−∞, or 1∞ may be manipulated algebraically
into one of the primary quotient forms, thereby permitting the
application of more systematic methods.
127
Formal Statement and Theoretical Un-
derpinnings
Suppose that f and g are functions defined on an open interval
I containing a point c, except possibly at c itself, and that both
functions are differentiable on I \ {c}. Provided that
lim f (x) = 0 and lim g(x) = 0,
x→c x→c
or
lim f (x) = ±∞ and lim g(x) = ±∞,
x→c x→c
and that g ′ (x) ̸= 0 for each x ∈ I \ {c}, then the rule may be stated
as follows: if the limit
f ′ (x)
L = lim
x→c g ′ (x)
exists or is equal to +∞ or −∞, then
f (x)
lim = L.
x→c g(x)
This conclusion is commonly established by invoking Cauchy’s Mean
Value Theorem, which provides the necessary technical bridge be-
tween the differentiability of the functions and the behavior of their
quotient. In addition, the theorem extends naturally to the case
where the independent variable tends to infinity, that is, when
x → ∞ or x → −∞. Under the corresponding conditions, the
replacement of the variable approaching a finite limit with an infi-
nite limit retains the validity of the result.
Applications in Evaluating Indeterminate
Limits
The procedure for utilizing L’Hopital’s Rule in the resolution of
limits involves examining functions whose naive substitution yields
the forms 00 or ∞∞
. After verifying the differentiability conditions
and the nonvanishing of the derivative of the denominator near
the point of interest, one computes the derivatives f ′ (x) and g ′ (x),
subsequently considering the limit
f ′ (x)
lim .
x→c g ′ (x)
128
In many cases, the newly formed limit is more accessible analyti-
cally than the original quotient. Occasionally, the process requires
repeated application of the rule when successive derivatives con-
tinue to result in an indeterminate form. Throughout such analy-
ses, careful attention must be paid to the underlying assumptions,
ensuring that the differentiability criteria remain satisfied and that
the derivatives do not vanish in a manner that impairs the appli-
cability of the rule.
Various challenging limits, especially those involving exponen-
tial, logarithmic, trigonometric, or polynomial functions, yield to
this technique. For instance, limits of the form
ex − 1
lim ,
x→0 x
or
ln x
lim ,
x→∞ x
prove to be amenable to the method after the initial substitution
results in the necessary indeterminate forms. In each instance,
precise computation of the derivatives elucidates the dominant be-
havior of the functions near the specified point, thereby revealing
the true limit.
The application of L’Hopital’s Rule not only furnishes an ef-
fective computational tool but also enriches the theoretical un-
derstanding of the interplay between function behavior and the
differential calculus. Rigorous justification of its use, along with
careful verification of all hypotheses, forms an essential component
of higher-level mathematical analysis.
Python Code Snippet
import sympy as sp
def is_indeterminate(f, g, x, limit_point):
"""
Check if the limit of f(x) and g(x) at the limit_point results
,→ in an indeterminate form,
specifically 0/0 or /.
"""
Lf = [Link](f, x, limit_point)
Lg = [Link](g, x, limit_point)
# Check for 0/0 indeterminate form
if Lf == 0 and Lg == 0:
129
return True
# Check for / indeterminate form
if (Lf in [[Link], -[Link]]) and (Lg in [[Link], -[Link]]):
return True
return False
def apply_lhopital(f, g, x, limit_point, max_iterations=5):
"""
Apply L'Hopital's Rule to compute the limit of the quotient
,→ f(x)/g(x) as x approaches limit_point.
Parameters:
f : numerator function (sympy expression)
g : denominator function (sympy expression)
x : independent variable (sympy symbol)
limit_point : point at which the limit is evaluated (can be a
,→ finite number or [Link]/-[Link])
max_iterations : maximum number of iterations to apply
,→ L'Hopital's Rule
Returns:
The limit of f(x)/g(x) after applying L'Hopital's Rule
,→ iteratively (if possible).
"""
# If the limit is not initially indeterminate, return the
,→ evaluated limit directly.
if not is_indeterminate(f, g, x, limit_point):
return [Link](f / g, x, limit_point)
iteration = 0
while iteration < max_iterations:
# Differentiate numerator and denominator
f = [Link](f, x)
g = [Link](g, x)
iteration += 1
# If the new form is no longer indeterminate, evaluate and
,→ return the limit.
if not is_indeterminate(f, g, x, limit_point):
return [Link](f / g, x, limit_point)
# After max_iterations, attempt a final evaluation even if still
,→ indeterminate.
return [Link](f / g, x, limit_point)
def main():
# Define the symbol for our calculations
x = [Link]('x')
print("Demonstration of L'Hopital's Rule using sympy\n")
# Example 1: Evaluate limit as x -> 0 of (exp(x) - 1) / x
f1 = [Link](x) - 1
130
g1 = x
limit1 = apply_lhopital(f1, g1, x, 0)
print("Limit as x -> 0 of (exp(x) - 1) / x =", limit1)
# Example 2: Evaluate limit as x -> of ln(x) / x
f2 = [Link](x)
g2 = x
# For limits at infinity, direct computation using [Link]
,→ works well.
limit2 = [Link](f2 / g2, x, [Link])
print("Limit as x -> of ln(x) / x =", limit2)
# Example 3: Evaluate limit as x -> 0 of (sin(x) - x) / x**3
f3 = [Link](x) - x
g3 = x**3
limit3 = apply_lhopital(f3, g3, x, 0)
print("Limit as x -> 0 of (sin(x) - x) / x**3 =", limit3)
# Example 4: Evaluate limit as x -> 0 of (1 - cos(x)) / x**2
f4 = 1 - [Link](x)
g4 = x**2
limit4 = apply_lhopital(f4, g4, x, 0)
print("Limit as x -> 0 of (1 - cos(x)) / x**2 =", limit4)
if __name__ == "__main__":
main()
131
Chapter 22
Antiderivatives and
Indefinite Integrals
Definition and Conceptual Framework
An antiderivative of a function f defined on an interval I ⊆ R is a
function F defined on I such that
F ′ (x) = f (x)
for every x ∈ I. In this context, the process of finding an antideriva-
tive is recognized as the inverse of differentiation. The notation for
the indefinite integral Z
f (x) dx
denotes the collection of all antiderivatives of f , that is,
{F (x) + C | C ∈ R}.
The inclusion of the arbitrary constant C reflects the observation
that the derivative of a constant function is zero, thereby obscuring
the unique determination of a single antiderivative by the differen-
tiation process.
132
The Inverse Relationship with Differenti-
ation
The operator of differentiation, defined by the limit process
F (x + h) − F (x)
F ′ (x) = lim ,
h→0 h
maps functions to their rates of change. In contrast, integration
acts to reconstruct a function from its derivative, establishing an
inverse relationship. If F is an antiderivative of f , then it follows
that Z
d
f (x) dx = f (x)
dx
on any interval where f is continuous. This relationship under-
scores the conceptual view that integration recovers the original
function up to an arbitrary constant, a nuance that is intrinsic to
the loss of information when passing from F to F ′ .
Algebraic Properties of Indefinite Inte-
grals
The structure of antiderivatives is governed by several fundamental
algebraic properties that are inherit to the operation of integration.
If f and g are functions for which antiderivatives exist and α, β
are arbitrary real numbers, then the linearity of the antiderivative
operator is expressed as
Z Z Z
[αf (x) + βg(x)] dx = α f (x) dx + β g(x) dx.
This linearity property is a direct consequence of the properties
of the derivative and serves as the basis for many techniques in
integration. The formulation naturally accommodates the addi-
tion of an arbitrary constant, thereby ensuring that the set of all
antiderivatives retains the structure of an affine space.
The Constant of Integration and its Role
The appearance of the constant of integration in the expression
Z
f (x) dx = F (x) + C
133
is a direct manifestation of the fact that differentiation annihilates
constant functions. For any constant C ∈ R,
d
[F (x) + C] = F ′ (x) = f (x).
dx
Thus, every function of the form F (x)+C qualifies as an antideriva-
tive of f . This aspect is of crucial importance in the broader con-
text of differential equations, where initial conditions are often em-
ployed to determine a unique antiderivative among the family of
solutions. The arbitrary constant encapsulates the inherent am-
biguity that results from the inverse operation of differentiation,
and its proper management is essential in both theoretical devel-
opments and practical computations within calculus.
Python Code Snippet
# Comprehensive Python Code Snippet for Antiderivatives and
,→ Indefinite Integrals
# This code demonstrates the key concepts discussed in the chapter:
# 1. Calculation of antiderivatives (indefinite integrals).
# 2. Verification that the derivative of an antiderivative recovers
,→ the original function.
# 3. The linearity property of integration.
# 4. Inclusion of the constant of integration (C).
import sympy as sp
# Define the symbols. 'x' is the variable and 'C' represents the
,→ constant of integration.
x, C = [Link]('x C')
# -------------------------------------------------------------
# Example 1: Antiderivative of a Polynomial Function
# f(x) = x^2
# According to the definition:
# F(x) such that F'(x) = f(x)
# The antiderivative is computed as:
# x^2 dx = x^3/3 + C
f = x**2
F = [Link](f, x)
F_with_constant = F + C
print("Antiderivative of f(x) = x^2 is:")
[Link](F_with_constant)
print("\nVerification (Differentiating F(x) should yield f(x)):")
[Link]([Link](F_with_constant, x))
# Expected output: Differentiating F(x) gives back x**2
134
# -------------------------------------------------------------
# Example 2: Linearity of Integration
# Demonstrate that integration is a linear operator:
# [ f(x) + g(x)] dx = f(x) dx + g(x) dx
# where and are arbitrary constants.
g = [Link](x) # Let g(x) = sin(x)
alpha, beta = [Link]('alpha beta')
integrated_linear_combination = [Link](alpha * f + beta * g,
,→ x)
# Alternatively, compute individual integrals and sum:
linear_combination_check = alpha * [Link](f, x) + beta *
,→ [Link](g, x)
print("\nAntiderivative of *x^2 + *sin(x) (direct integration):")
[Link](integrated_linear_combination + C) # Adding the constant
,→ of integration
print("\nLinearity Check: x^2 dx + sin(x) dx:")
[Link](linear_combination_check + C)
# The two printed expressions are equivalent (up to the arbitrary
,→ constant C)
# -------------------------------------------------------------
# Example 3: Antiderivative of an Exponential Function
# For f(x) = e^x, the antiderivative is:
# e^x dx = e^x + C
f_exp = [Link](x)
F_exp = [Link](f_exp, x) + C
print("\nAntiderivative of f(x) = e^x is:")
[Link](F_exp)
# Verification automatically follows since d/dx[e^x + C] = e^x
# -------------------------------------------------------------
# Helper Function: Compute the Antiderivative with Constant of
,→ Integration
def compute_antiderivative(function_expr, variable):
"""
Computes the antiderivative (indefinite integral) of a given
,→ function expression
with respect to a specified variable. The result includes an
,→ arbitrary constant C.
Parameters:
function_expr : sympy expression
The function to integrate.
variable : sympy symbol
The variable of integration.
Returns:
sympy expression representing the antiderivative + C.
135
"""
constant = [Link]('C')
antideriv = [Link](function_expr, variable)
return antideriv + constant
# Testing the helper function with f(x) = sin(x)
f_sin = [Link](x)
antideriv_sin = compute_antiderivative(f_sin, x)
print("\nAntiderivative of f(x) = sin(x) using the helper function
,→ is:")
[Link](antideriv_sin)
print("\nVerification (Differentiating the antiderivative of
,→ sin(x)):")
[Link]([Link](antideriv_sin, x))
# The derivative of the antiderivative should return sin(x)
if __name__ == '__main__':
# Main block to execute the examples as a demonstration.
print("\n--- End of Antiderivatives Demonstration Code ---")
136
Chapter 23
Techniques of
Integration:
Substitution
Preliminaries and Theoretical Foundations
The substitution method for integration originates as an inverse
application of the Chain Rule in differential calculus. Consider an
integrand that may be expressed in the composite form
f g(x) g ′ (x).
In such situations, the substitution method, frequently referred to
as u-substitution, systematically transforms the original integral
into an equivalent form that is often more tractable. The funda-
mental principle is that if a continuously differentiable function
g: I → R
is designated on an interval I, and if a function
f : g(I) → R
admits an antiderivative on the range of g, then there exists close
correspondence between the integral
Z
f g(x) g ′ (x) dx
137
and the simplified form obtained by the substitution
u = g(x),
which yields
du = g ′ (x) dx.
Thus, the integral is transformed into
Z
f (u) du.
This transformation is rigorously justified by the Inverse Function
Theorem and the continuous differentiability of g. The method
not only simplifies the computational task but also highlights the
inherent interplay between differentiation and integration.
Formal Framework of the Substitution Pro-
cess
Let g : I → R be a continuously differentiable function, and let f
be defined on the
interval g(I) in such a way that the composite
function f g(x) g ′ (x) is integrable on I. Under these conditions,
the substitution
u = g(x)
implies that
du = g ′ (x) dx.
Accordingly, the integral
Z
f g(x) g ′ (x) dx
can be rewritten as Z
f (u) du.
This process requires that the mapping x 7→ g(x) be both one-to-
one and onto its image in order to ensure that the substitution is
reversible and that the integration variable is properly transformed.
This technique is particularly effective when the integrand natu-
rally decomposes into a composite function alongside its deriva-
tive, thereby allowing a direct application of standard integration
methods to the variable u.
138
An additional facet of the substitution method arises in the
context of definite integrals. If
Z b
f g(x) g ′ (x) dx
a
is considered, then the limits of integration must be updated ac-
cording to the substitution as follows:
u(a) = g(a) and u(b) = g(b).
The integral then becomes
Z g(b)
f (u) du.
g(a)
This precise adjustment of the limits maintains the integrity of the
integral under the transformation and ensures that the evaluation
proceeds within the correct bounds in the u-domain.
Analytic Structure and Methodological Im-
plementation
The substitution method is built upon the recognition of patterns
within the integrand that suggest the existence of an inner function
whose derivative is also present, up to a multiplicative constant.
When such a pattern is detected, the substitution
u = g(x)
is implemented in order to express the differential element dx in
terms of du. This change leads to an integrand solely in terms of
u which is, in many circumstances, simpler to integrate.
The procedure may be outlined in a sequence of conceptual
steps. Initially, a function g(x) is identified for which the integrand
contains both g(x) (or a function thereof) and the derivative g ′ (x),
possibly scaled by constants. Once the substitution is declared, the
differential relation
du = g ′ (x) dx
is used to completely rewrite the integral in terms of u. The process
capitalizes on the Chain Rule, since differentiating a composite
function
F g(x)
139
yields
F ′ g(x) g ′ (x),
demonstrating the inverse relationship between differentiation and
integration. It is paramount that the substitution be chosen so as
to not omit any variable dependencies which might compromise the
validity of the transformation.
This systematic method simplifies the structure of the original
integral, thereby transforming potentially complex expressions into
ones that are susceptible to elementary integration techniques. In
many instances, once the variable change has been executed, the
new integral Z
f (u) du
can be integrated directly, and the resulting antiderivative can then
be mapped back into the original variable by inverting the substi-
tution.
Exemplification Within a Rigorous Frame-
work
A prototypical example of the substitution method is encountered
in the evaluation of an integral of the form
Z
cos x3 + 1 · 3x2 dx.
By setting
u = x3 + 1,
the differential is given by
du = 3x2 dx.
Consequently, the original integral transforms into
Z
cos(u) du,
which is immediately integrable due to the standard antiderivative
of the cosine function. The antiderivative in terms of u is
sin(u),
140
and upon reversing the substitution, the antiderivative obtained is
sin x3 + 1 .
This example encapsulates the efficacy of the systematic substi-
tution method in reducing complex integrals to forms whose an-
tiderivatives are available in closed form.
The substitution method, viewed through the lens of rigorous
analysis, is not merely a procedural trick but a manifestation of the
deep interplay between composite functions and their derivatives.
Its application extends beyond elementary integrals and plays a
crucial role in solving integrals that arise in advanced mathematical
analysis and applied mathematics.
Python Code Snippet
# Import necessary modules from sympy for symbolic computation
from sympy import symbols, diff, integrate, cos, sin, simplify,
,→ pprint
# Define the symbols
x, u = symbols('x u')
# Define the inner function for the substitution: u = g(x) = x^3 + 1
g = x**3 + 1
# Compute the derivative of g(x)
dg = diff(g, x) # dg/dx = 3*x**2
# Output the inner function and its derivative
print("g(x) =", g)
print("g'(x) =", dg)
# Define the outer function f(u) = cos(u)
f = cos(u)
# Construct the original integrand in terms of x: cos(g(x)) * g'(x)
integrand = cos(g) * dg
print("\nOriginal integrand (in terms of x):")
pprint(integrand)
# ---------------------------------------------------------
# Substitution Process:
# Step 1: Identify the substitution u = g(x) such that du = g'(x)
,→ dx.
# This transforms the integral cos(g(x)) * g'(x) dx into
,→ cos(u) du.
#
# Step 2: Compute the antiderivative in terms of u.
141
antideriv_u = integrate(f, u)
print("\nAntiderivative in terms of u:")
pprint(antideriv_u)
# Step 3: Substitute back u = g(x) to express the antiderivative in
,→ terms of x.
antideriv_x = antideriv_u.subs(u, g)
print("\nAntiderivative expressed back in terms of x:")
pprint(antideriv_x)
# Verification: Differentiate the obtained antiderivative with
,→ respect to x
# to ensure it matches the original integrand.
verified_integrand = simplify(diff(antideriv_x, x))
print("\nVerification: Derivative of the antiderivative (should
,→ equal the original integrand):")
pprint(verified_integrand)
# ---------------------------------------------------------
# Example: Evaluate a Definite Integral using Substitution
# Consider the definite integral:
# from x = a to x = b of cos(x^3 + 1) * 3*x**2 dx
a = 0 # Lower limit of integration
b = 1 # Upper limit of integration
# Adjust the limits for the substitution:
# For u = g(x) = x^3 + 1, the new limits become:
ua = [Link](x, a) # u(a) = a^3 + 1
ub = [Link](x, b) # u(b) = b^3 + 1
print("\nSubstituted limits for u:")
print("u(a) =", ua)
print("u(b) =", ub)
# Evaluate the definite integral in terms of u
definite_integral_u = integrate(f, (u, ua, ub))
print("\nDefinite integral evaluated using substitution in terms of
,→ u:")
pprint(definite_integral_u)
# Alternatively, evaluate the definite integral directly in terms of
,→ x
definite_integral_x = integrate(integrand, (x, a, b))
print("\nDefinite integral evaluated directly in terms of x:")
pprint(definite_integral_x)
# End of Python code snippet demonstrating the substitution method
,→ in integration.
142
Chapter 24
Techniques of
Integration:
Integration by Parts
Theoretical Underpinnings
Integration by parts is a fundamental technique in the evaluation
of integrals involving products of functions. Its theoretical basis is
rooted in the product rule for differentiation. For two sufficiently
smooth functions u(x) and v(x), the product rule is expressed as
d
u(x)v(x) = u′ (x)v(x) + u(x)v ′ (x).
dx
Integration of both sides with respect to x over an appropriate in-
terval yields a relationship that serves as the foundation for the
method. The process relies on the inverse interplay between dif-
ferentiation and integration, as encapsulated by the Fundamental
Theorem of Calculus.
Formal Derivation from the Product Rule
Assume that u(x) and v(x) are continuously differentiable functions
defined on an interval I. Integrating the derivative of the product
143
u(x)v(x) over I,
Z Z Z
d
u (x)v(x) dx + u(x)v (x) dx =
′ ′
u(x)v(x) dx,
dx
and applying the Fundamental Theorem of Calculus on the right-
hand side results in
Z Z
u(x)v(x) = u′ (x)v(x) dx + u(x)v ′ (x) dx.
Rearrangement of this equation yields the integration by parts for-
mula for indefinite integrals:
Z Z
u(x)v (x) dx = u(x)v(x) − v(x)u′ (x) dx.
′
In this context the notation may be simplified by introducing dif-
ferentials du = u′ (x) dx and dv = v ′ (x) dx, so that the formula can
be succinctly written as
Z Z
u dv = u v − v du.
Methodological Implementation
When presented with an integral that consists of a product of func-
tions, the method of integration by parts is employed by judiciously
selecting one factor as the function u and the remaining part, in-
cluding its differential, as dv. The selection is guided by the prin-
ciple that differentiating u should yield a simpler expression, while
the antiderivative of dv should be attainable by elementary means.
The procedure is as follows. First, set
u = u(x) and dv = v ′ (x) dx,
so that differentiation provides
du = u′ (x) dx,
and integration yields
Z
v= v ′ (x) dx.
144
Substituting these expressions into the integration by parts for-
mula, Z Z
u dv = u v − v du,
transforms the original integral into a typically simpler one. This
systematic alteration of the integral’s structure often permits the
evaluation of integrals that would be intractable by more direct
methods.
Illustrative Examples of Application
Consider the task of integrating a product of functions where one
factor is of a type whose derivative is less complex and the other
has a straightforward antiderivative. For instance, in evaluating an
integral of the form Z
x ex dx,
one may choose
u = x and dv = ex dx.
Then, differentiation yields
du = dx,
and integration provides
v = ex .
Substitution into the integration by parts formula leads to
Z Z
x e dx = x e − ex dx.
x x
The remaining integral, ex dx, is elementary, and its evaluation
R
produces Z
x ex dx = x ex − ex + C,
where C denotes an arbitrary constant of integration.
Integration by parts finds extensive application in the treat-
ment of integrals involving logarithmic, inverse trigonometric, and
algebraic functions multiplied by transcendental functions. The
method is especially effective when the integrand exhibits a struc-
ture that loosely mirrors the product of a function and the deriva-
tive of another, ensuring that the transformation simplifies the
integrative process. Every instance of application reinforces the
robustness and utility of the underlying theoretical principles.
145
Python Code Snippet
import sympy as sp
def integration_by_parts(u, dv, x):
"""
Perform integration by parts on an integrand.
Given functions u(x) and the differential dv (i.e., v'(x) dx),
,→ this function
computes the integral based on the formula:
u dv = u*v - v du
where:
du = d(u)/dx dx and
v = dv
Parameters:
u : sympy expression representing u(x)
dv : sympy expression representing v'(x) dx
x : sympy symbol (the variable of integration)
Returns:
result : The simplified antiderivative (ignoring the constant
,→ of integration)
"""
du = [Link](u, x)
v = [Link](dv, x)
result = u * v - [Link](v * du, x)
return [Link](result)
# Define the symbol for variable x
x = [Link]('x')
# -----------------------------------------------------------
# Demonstration 1: Evaluating x * exp(x) dx using integration by
,→ parts.
#
# The theoretical derivation is based on:
#
# 1. The Product Rule (for differentiation):
# d/dx [u(x)v(x)] = u'(x)v(x) + u(x)v'(x)
#
# 2. Integrating both sides yields:
# u(x)v(x) = u'(x)v(x) dx + u(x)v'(x) dx
#
# Rearranging, we obtain the Integration by Parts formula:
# u(x)v'(x) dx = u(x)v(x) - v(x)u'(x) dx
#
# In our example, choose:
# u = x => du = 1*dx
146
# dv = exp(x)dx => v = exp(x)
# -----------------------------------------------------------
u_expr = x
dv_expr = [Link](x)
# Compute the integral using the integration_by_parts function.
integral_result = integration_by_parts(u_expr, dv_expr, x)
print("Integration by parts result for x * exp(x) dx:")
[Link](integral_result)
# Verify by directly integrating using sympy's integrate function.
direct_result = [Link](x * [Link](x), x)
print("\nDirect integration result for x * exp(x) dx:")
[Link]([Link](direct_result))
# -----------------------------------------------------------
# Demonstration 2: Deriving the integration by parts formula from
,→ the product rule.
#
# Let u(x) and v(x) be arbitrary functions. The product rule states:
#
# d/dx [u(x) * v(x)] = u'(x) * v(x) + u(x) * v'(x)
#
# Integrating both sides gives:
#
# u(x) * v(x) = u'(x) * v(x) dx + u(x) * v'(x) dx
#
# Rearranging leads to:
#
# u(x) * v'(x) dx = u(x) * v(x) - v(x) * u'(x) dx
#
# This section uses symbolic functions to demonstrate the
,→ relationship.
# -----------------------------------------------------------
# Define u(x) and v(x) as arbitrary functions.
u = [Link]('u')(x)
v = [Link]('v')(x)
# Compute the derivative of the product u(x)*v(x)
product_derivative = [Link](u * v, x)
print("\nProduct rule: d/dx [u(x) * v(x)] equals:")
[Link]([Link](product_derivative))
# The printed relationship above exemplifies the theoretical basis
,→ for the
# integration by parts formula.
147
Chapter 25
Techniques of
Integration: Partial
Fractions
Preliminaries and Motivation
The integration of rational functions occupies a central position
in advanced calculus and mathematical analysis. In numerous in-
stances, integrals involving rational expressions are rendered tractable
by decomposing the given function into a sum of simpler fractions.
Let P (x) and Q(x) denote polynomials with real coefficients, and
consider the rational function
P (x)
.
Q(x)
After ensuring that deg P (x) < deg Q(x) through polynomial divi-
sion when necessary, the function is amenable to a decomposition
into simpler components. This decomposition exploits the fun-
damental theorem of algebra, by which every polynomial may be
factored into linear or irreducible quadratic factors over the field of
real numbers. The resulting partial fraction representation facili-
tates the evaluation of the antiderivative by reducing the integral
to a sum of elementary integrals.
148
Algebraic Foundations: Factorization and
Structure of Decomposition
Assume that the denominator Q(x) can be factored completely over
the real numbers. In general, one may write
m
Y n
Y
Q(x) = (x − αi )ki (x2 + βj x + γj )ℓj ,
i=1 j=1
where the factors (x − αi ) are distinct linear factors and (x2 +
βj x + γj ) are quadratic factors that are irreducible over R (that
is, their discriminants satisfy βj2 − 4γj < 0). Under the hypothesis
that deg P (x) < deg Q(x), the rational function admits a unique
decomposition into partial fractions of the form
m k n ℓj
P (x) X X i
Ai,r X X Bj,s x + Cj,s
= + ,
Q(x) i=1 r=1
(x − αi )r j=1 s=1 (x2 + βj x + γj )s
where the constants Ai,r , Bj,s , and Cj,s are determined by equating
coefficients after clearing denominators. The systematic determi-
nation of these constants relies on established techniques in algebra,
such as the method of undetermined coefficients.
General Framework of Partial Fraction
Decomposition
Let the rational function
P (x)
R(x) =
Q(x)
satisfy the degree condition deg P (x) < deg Q(x). The decomposi-
tion of R(x) into partial fractions is executed by expressing it as a
sum of simpler rational functions whose denominators are powers
of irreducible factors. More precisely, if
m
Y n
Y
Q(x) = (x − αi )ki (x2 + βj x + γj )ℓj ,
i=1 j=1
then one considers a representation of the form
m k n ℓj
P (x) X X i
Ai,r X X Bj,s x + Cj,s
= + .
Q(x) i=1 r=1
(x − αi ) r
j=1 s=1
(x2 + βj x + γj )s
149
Multiplication by Q(x) leads to an identity between polynomials,
and the resulting system of linear equations, obtained by equating
the coefficients of like powers of x, uniquely determines the un-
known constants. The decomposition, once achieved, permits the
integral
P (x)
Z
dx
Q(x)
to be expressed as a sum of integrals of simpler rational functions.
Integration of Decomposed Components
Following the decomposition, the evaluation of each term reduces
to standard integration techniques. Terms corresponding to linear
factors yield integrals of the form
Z
dx
,
x−α
which, upon integration, produce logarithmic expressions,
Z
dx
= ln |x − α| .
x−α
For repeated linear factors, the integrals of terms such as
Z
dx
, r > 1,
(x − α)r
are obtained by applying the power rule for integration, resulting
in expressions involving negative powers of (x − α).
The decomposition corresponding to irreducible quadratic fac-
tors introduces integrals of the form
Bx + C Bx + C
Z Z
dx or dx.
x2 + βx + γ (x2 + βx + γ)s
For these integrals it is advantageous to complete the square in the
quadratic denominator. If one writes
2
β2
β
x + βx + γ = x +
2
+ γ− ,
2 4
then standard substitutions and the use of known antiderivatives,
such as those involving the inverse tangent or logarithmic functions,
yield the required expressions. The integration process hence trans-
forms the original integral into a sum of simpler integrals whose
antiderivatives are given in closed form.
150
Illustrative Examples of Partial Fraction
Integration
Consider a rational function of the form
2x + 3
.
(x − 1)(x2 + x + 1)
Assume a decomposition of the form
2x + 3 A Bx + C
= + .
(x − 1)(x2 + x + 1) x − 1 x2 + x + 1
Multiplying by the common denominator (x − 1)(x2 + x + 1) yields
an identity of polynomials,
2x + 3 = A x2 + x + 1 + (Bx + C)(x − 1).
Expansion and subsequent collection of like powers of x lead to a
system of linear equations:
A + B = 0,
A − C = 2,
A − C = 3.
Solving this system for the constants A, B, and C determines the
coefficients uniquely. Once these constants have been identified,
the original integral splits into two parts,
Bx + C
Z Z
A
dx and dx,
x−1 x +x+1
2
each of which is amenable to elementary integration. The first
integral resolves to a logarithmic function,
Z
A
dx = A ln |x − 1| ,
x−1
while the second integral, after completing the square in the de-
nominator, is integrated using a substitution that leads to a com-
bination of logarithmic and inverse trigonometric functions.
In another instance, the technique applies to rational functions
where the denominator contains repeated irreducible quadratic fac-
tors. In such cases, the decomposition introduces a series of terms
of the form
Bs x + Cs
,
(x2 + βx + γ)s
151
with s ≥ 1, and the integrals are evaluated by iterative application
of the substitution method and standard integral formulas.
Through these methodologies, the decomposition of complex ra-
tional functions into partial fractions proves to be an indispensable
tool in the computation of antiderivatives, rendering the integra-
tion process more systematic and accessible.
Python Code Snippet
# Import necessary functions from sympy for symbolic computation
from sympy import symbols, apart, integrate, factor, simplify, div,
,→ pprint
# Define the symbolic variable
x = symbols('x')
# Define the example rational function:
# f(x) = (2x + 3) / [(x - 1)(x^2 + x + 1)]
f = (2*x + 3) / ((x - 1) * (x**2 + x + 1))
# Perform partial fraction decomposition using [Link]
decomp = apart(f, x)
print("Partial Fraction Decomposition of f(x):")
pprint(decomp)
print("\n")
# Compute the indefinite integral of f(x)
integral_f = integrate(f, x)
print("Indefinite Integral of f(x):")
pprint(integral_f)
print("\n")
# Demonstrate the integration of each decomposed term individually.
print("Integration of Decomposed Terms:")
# decomp.as_ordered_terms() yields the separate terms in the
,→ decomposition.
terms = decomp.as_ordered_terms()
for term in terms:
int_term = integrate(term, x)
print("Integral of:")
pprint(term)
print("is:")
pprint(int_term)
print("-" * 40)
# Factorization example: Consider the quadratic denominator.
# The quadratic expression x^2 + x + 1 is irreducible over the
,→ reals.
quadratic_expr = x**2 + x + 1
152
print("\nFactorization of the Quadratic Expression x^2 + x + 1:")
factored_quadratic = factor(quadratic_expr)
pprint(factored_quadratic)
print("\n")
# Define a function that handles the entire process of integration
,→ for a rational function
# using partial fraction decomposition with polynomial division if
,→ necessary.
def partial_fraction_integration(numerator, denominator, var):
"""
Given a numerator and denominator representing a rational
,→ function,
this function performs polynomial division if the degree of the
,→ numerator
is not less than the degree of the denominator. Then, it
,→ computes the partial
fraction decomposition of the proper fraction part and returns
,→ the integrated result.
"""
# Perform polynomial division to express the function as:
# quotient + remainder/denominator, ensuring deg(remainder) <
,→ deg(denominator)
quotient, remainder = div(numerator, denominator, domain='QQ')
integrated_result = 0
# Integrate the polynomial part if quotient is non-zero
if quotient != 0:
integrated_result += integrate(quotient, var)
# For the proper fraction, perform partial fraction
,→ decomposition and integrate
proper_fraction = remainder / denominator
integrated_result += integrate(apart(proper_fraction, var), var)
return simplify(integrated_result)
# Use the custom integration function on f(x), defined by its
,→ numerator and denominator
numerator = 2*x + 3
denominator = (x - 1) * (x**2 + x + 1)
custom_integral = partial_fraction_integration(numerator,
,→ denominator, x)
print("Integrated Result using custom partial_fraction_integration
,→ function:")
pprint(custom_integral)
153
Chapter 26
Techniques of
Integration:
Trigonometric Integrals
This chapter is devoted to the systematic treatment of integra-
tion methods for functions that involve powers of trigonometric
functions and mixed trigonometric expressions. The techniques
described herein rely on classical trigonometric identities, substi-
tution strategies, and the derivation of reduction formulas to trans-
form intricate integrals into sums of elementary forms.
Preliminaries on Trigonometric Identities
and Substitutions
Trigonometric functions possess a rich structure of algebraic identi-
ties that facilitate the integration process. The Pythagorean iden-
tity,
sin2 x + cos2 x = 1,
serves as a fundamental tool, while the double-angle formulas,
sin 2x = 2 sin x cos x, cos 2x = 2 cos2 x − 1,
and the half-angle formulas provide alternative representations of
higher powers of sine and cosine. Appropriate substitutions, such
154
as setting u = cos x or u = sin x, in conjunction with the differential
relations
du = − sin x dx or du = cos x dx,
respectively, enable the conversion of trigonometric integrals into
integrals of algebraic functions. These preliminary identities and
substitutions provide the groundwork for the subsequent, more spe-
cialized techniques.
Integrals of Powers of Sine and Cosine
A broad class of integrals encountered in practice is of the form
Z
sinm x cosn x dx,
where m and n are positive integers. The strategy for evaluating
such integrals depends sensitively on whether the exponents are
odd or even.
1 Odd Powers and Substitution Methods
When one of the exponents, say m, is odd, it is advantageous to
express
sinm x = sinm−1 x · sin x,
and to rewrite the even power sinm−1 x using the identity
sin2 x = 1 − cos2 x.
This representation allows the integrand to be recast in the form
of a polynomial in cos x multiplied by a single factor of sin x. With
the substitution u = cos x, so that du = − sin x dx, the original
integral is transformed into an algebraic integral in u, which is
more readily evaluated.
2 Even Powers and Transformation via Double-
Angle Formulas
In the instance where both m and n are even, direct substitution
does not yield an immediate simplification. Instead, the applica-
tion of power-reducing identities is necessary. For example, the
identities
1 − cos 2x 1 + cos 2x
sin2 x = , cos2 x = ,
2 2
155
allow powers of sine and cosine to be expressed in terms of func-
tions of 2x. This transformation converts the original integral into a
linear combination of integrals involving cos 2x and constant multi-
ples, each of which is amenable to standard integration procedures.
Reduction Formulas for Trigonometric In-
tegrals
Reduction formulas play a central role in handling integrals of
higher powers by providing recursive relations that reduce the ex-
ponent in a systematic manner.
1 Derivation of Reduction Formulas for Sine and
Cosine Powers
A prototypical example is given by the integral
Z
In = sinn x dx.
An application of integration by parts, choosing
u = sinn−1 x and dv = sin x dx,
leads to the reduction relation
sinn−1 x cos x n − 1
Z
In = − + sinn−2 x dx.
n n
A similar reduction formula can be derived for
Z
Jn = cosn x dx.
These recursive relations reduce the original problem to the evalu-
ation of integrals with lower exponents. Iterative application even-
tually expresses the integral in terms of elementary functions.
2 Extensions to Higher Trigonometric Powers
The scope of reduction formulas extends naturally to integrals of
the form Z
sinm x cosn x dx,
156
where algebraic manipulation via the Pythagorean identity reduces
the combined exponent sum. When both m and n are even, the
combination of a reduction procedure with double-angle substitu-
tions simplifies the integrals to sums of basic trigonometric inte-
grals. These methods are particularly effective in problems related
to Fourier series and oscillatory integrals.
Integrals of Mixed Trigonometric Expres-
sions
Integrals involving mixed trigonometric functions require a careful
examination of the interplay between different functional forms,
especially when the integrals incorporate functions such as tangent
and secant.
1 Products Involving Sine and Cosine
For integrals featuring products such as
Z
sinm x cosn x dx,
when one of the exponents is odd the extraction of a single factor
(either sin x or cos x) enables the use of a suitable substitution as
previously described. Alternatively, in cases where both exponents
are even, the application of power-reducing formulas transforms
the integral into a sum of terms involving multiple angles. The
resulting elementary integrals are then integrated term by term.
2 Integrals Involving Tangent, Secant, and Aux-
iliary Functions
A related category involves integrals of the form
Z
tanm x secn x dx.
The identities
d
tan2 x = sec2 x − 1 and tan x = sec2 x,
dx
provide the essential framework for these integrals. Frequently, iso-
lating a factor of sec2 x permits the substitution u = tan x, which
157
converts the original integral into a polynomial integral in u. In
more complex cases, the judicious combination of substitution and
integration by parts is required to manage the resulting expres-
sions. The methods employed in these scenarios reveal an under-
lying unity among the various techniques used for trigonometric
integration.
Python Code Snippet
import sympy as sp
# Initialize pretty printing for better display of expressions
sp.init_printing()
# Define the symbol for the variable x
x = [Link]('x', real=True)
# --------------------------------------------------------
# 1. Preliminaries on Trigonometric Identities
# --------------------------------------------------------
# Pythagorean Identity: sin^2(x) + cos^2(x) = 1
pythagorean = [Link](x)**2 + [Link](x)**2
print("Pythagorean Identity: sin^2(x) + cos^2(x) =",
,→ [Link](pythagorean))
# Double-Angle Formulas:
# sin(2x) = 2*sin(x)*cos(x)
double_angle_sin = [Link](2*x)
print("Double-Angle Formula for sine: sin(2x) =",
,→ [Link](double_angle_sin))
print("Verification: 2*sin(x)*cos(x) =",
,→ [Link](2*[Link](x)*[Link](x)))
# cos(2x) can be written as 2*cos^2(x) - 1 and also as 1 -
,→ 2*sin^2(x)
double_angle_cos = [Link](2*x)
expr1 = 2*[Link](x)**2 - 1
expr2 = 1 - 2*[Link](x)**2
print("Double-Angle Formula for cosine: cos(2x) =",
,→ [Link](double_angle_cos))
print("Verification: 2*cos^2(x)-1 =", [Link](expr1))
print("Verification: 1-2*sin^2(x) =", [Link](expr2))
# --------------------------------------------------------
# 2. Integrals of Powers of Sine and Cosine
# --------------------------------------------------------
# Consider the general integral: sin^m(x)*cos^n(x) dx
158
# Example (a): m = 3 (odd), n = 2 using substitution.
integral_odd = [Link]([Link](x)**3 * [Link](x)**2, x)
print("Integral of sin^3(x)*cos^2(x) dx =",
,→ [Link](integral_odd))
# Example (b): Both m and n even, e.g., sin^2(x)*cos^2(x) dx using
,→ power-reducing formulas.
integral_even = [Link]([Link](x)**2 * [Link](x)**2, x)
print("Integral of sin^2(x)*cos^2(x) dx =",
,→ [Link](integral_even))
# --------------------------------------------------------
# 3. Reduction Formulas for Trigonometric Integrals
# --------------------------------------------------------
# Reduction formula for I_n = sin^n(x) dx:
# I_n = -[sin^(n-1)(x)*cos(x)]/n + [(n-1)/n]*I_(n-2)
# Here we demonstrate the integration for specific values of n.
# For n = 3:
n = 3
I_n3 = [Link]([Link](x)**n, x)
print("Integral of sin^3(x) dx =", [Link](I_n3))
# For n = 4:
n = 4
I_n4 = [Link]([Link](x)**n, x)
print("Integral of sin^4(x) dx =", [Link](I_n4))
# --------------------------------------------------------
# 4. Integrals of Mixed Trigonometric Expressions
# --------------------------------------------------------
# Example: Integral involving tangent and secant:
# tan^3(x)*sec^4(x) dx
integral_tan_sec = [Link]([Link](x)**3 * [Link](x)**4, x)
print("Integral of tan^3(x)*sec^4(x) dx =",
,→ [Link](integral_tan_sec))
# --------------------------------------------------------
# 5. Demonstration of Substitution Method
# --------------------------------------------------------
# Manual substitution example for sin^3(x) dx when m is odd.
# Write sin^3(x) dx = sin^2(x)*sin(x) dx and use the identity
,→ sin^2(x) = 1 - cos^2(x).
# Substitute u = cos(x), then du = -sin(x) dx => sin(x) dx = -du.
# Define symbol u for substitution
u = [Link]('u', real=True)
# Expressing the integral with the substitution:
# sin^3(x) dx becomes - (1 - u**2) du
159
integral_sub = -[Link](1 - u**2, u)
# Replace u with cos(x) to obtain the answer in terms of x
integral_substituted = [Link](integral_sub.subs(u, [Link](x)))
print("Manual substitution: Integral of sin^3(x) dx =",
,→ integral_substituted)
160
Chapter 27
Techniques of
Integration:
Trigonometric
Substitution
Fundamental Principles
Trigonometric substitution is an analytical technique that trans-
forms integrals containing radical expressions or quadratic forms
into integrals expressed solely in terms of trigonometric functions.
This method exploits the classical identities
sin2 θ + cos2 θ = 1, 1 + tan2 θ = sec2 θ, sec2 θ − 1 = tan2 θ,
which allow for the elimination of square roots and the re-expression
of quadratic expressions in a more tractable form. The appropri-
ate choice of substitution aligns the structure of the integrand with
these identities, thereby reducing the integral to one involving stan-
dard trigonometric functions.
√
Substitution for Integrals Involving a2 − x 2
When an integral contains a radical of the form
p
a2 − x2 ,
161
the substitution
x = a sin θ
proves effective. Under this substitution, the differential transforms
as
dx = a cos θ dθ,
and the radical simplifies according to
p p
a2 − x2 = a2 − a2 sin2 θ = a cos θ.
This replacement not only removes the radical but also converts the
integrand into an expression in θ that typically involves powers of
sine and cosine. The resulting integrals become accessible through
standard trigonometric integration techniques.
√
Substitution for Integrals Involving a2 + x2
In the presence of a radical of the form
p
a2 + x2 ,
the substitution
x = a tan θ
is employed. The differential is computed as
dx = a sec2 θ dθ,
while the radical transforms in the following manner:
p p
a2 + x2 = a2 + a2 tan2 θ = a sec θ.
This substitution converts the original algebraic expression into one
involving the secant function, thereby facilitating the application
of trigonometric integrals that are standard in the literature.
√
Substitution for Integrals Involving x2 − a2
For integrals that include a radical of the form
p
x2 − a2 ,
the substitution
x = a sec θ
162
is particularly advantageous. In this case, the differential becomes
dx = a sec θ tan θ dθ,
and the radical simplifies as
p p p
x2 − a2 = a2 sec2 θ − a2 = a sec2 θ − 1 = a tan θ.
The substitution effectively replaces the square root by a linear
trigonometric function, thereby reducing the complexity of the inte-
grand. This transformation aligns the integral with familiar forms
whose antiderivatives are well established in advanced calculus.
Each of these substitutions is motivated by the inherent geo-
metric interpretations of the quadratic expressions and their cor-
responding radicals. The transformations applied yield integrals
that are not only more manageable but also provide insight into
the underlying structure of the original expressions.
Python Code Snippet
# This Python code demonstrates the key equations, formulas, and
,→ algorithms
# for trigonometric substitutions in the evaluation of integrals.
# It uses sympy for symbolic computation and verification of the
,→ substitutions.
from sympy import symbols, sin, cos, tan, sec, sqrt, diff, simplify,
,→ integrate, pprint
# Define the symbols used in the substitutions.
theta, a, x = symbols('theta a x', positive=True, real=True)
# Print Fundamental Trigonometric Identities:
print("Fundamental Trigonometric Identities:")
# Identity: sin^2(theta) + cos^2(theta) = 1
print("sin^2(theta) + cos^2(theta) =", simplify(sin(theta)**2 +
,→ cos(theta)**2))
# Identity: 1 + tan^2(theta) = sec^2(theta)
print("1 + tan^2(theta) =", simplify(1 + tan(theta)**2))
# Identity: sec^2(theta) - 1 = tan^2(theta)
print("sec^2(theta) - 1 =", simplify(sec(theta)**2 - 1))
print("\n")
# ----------------------------------------------------------
# Case 1: Substitution for Integrals Involving (a2 - x2)
# Using the substitution: x = a*sin(theta)
# Therefore, dx = a*cos(theta)dtheta, and the radical becomes:
163
# (a2 - x2) = (a2 - a2*sin2(theta)) = a*cos(theta)
print("Substitution for (a2 - x2):")
x_sub = a * sin(theta)
dx_sub = diff(x_sub, theta) # Derivative of a*sin(theta) ==>
,→ a*cos(theta)
radical1 = sqrt(a**2 - x_sub**2)
radical1_simpl = simplify(radical1)
print("x substitution: x =", x_sub)
print("Differential dx/dtheta =", dx_sub)
print("Simplified radical (a2 - x2) =", radical1_simpl)
# Example: Transform the integral (a2 - x2) dx into the theta
,→ domain.
integral_expr1 = sqrt(a**2 - x**2)
transformed_expr1 = integral_expr1.subs(x, x_sub) * dx_sub #
,→ Replace x and multiply by dx
transformed_expr1_simpl = simplify(transformed_expr1)
print("\nTransformed integral for (a2 - x2) dx =")
print(transformed_expr1_simpl)
print("\n")
# ----------------------------------------------------------
# Case 2: Substitution for Integrals Involving (a2 + x2)
# Using the substitution: x = a*tan(theta)
# Therefore, dx = a*sec2(theta)dtheta, and the radical becomes:
# (a2 + x2) = (a2 + a2*tan2(theta)) = a*sec(theta)
print("Substitution for (a2 + x2):")
x_sub2 = a * tan(theta)
dx_sub2 = diff(x_sub2, theta) # Derivative of a*tan(theta) ==>
,→ a*sec2(theta)
radical2 = sqrt(a**2 + x_sub2**2)
radical2_simpl = simplify(radical2)
print("x substitution: x =", x_sub2)
print("Differential dx/dtheta =", dx_sub2)
print("Simplified radical (a2 + x2) =", radical2_simpl)
# Example: Transform the integral (a2 + x2) dx into the theta
,→ domain.
integral_expr2 = sqrt(a**2 + x**2)
transformed_expr2 = integral_expr2.subs(x, x_sub2) * dx_sub2 #
,→ Replace x and multiply by dx
transformed_expr2_simpl = simplify(transformed_expr2)
print("\nTransformed integral for (a2 + x2) dx =")
print(transformed_expr2_simpl)
print("\n")
# ----------------------------------------------------------
# Case 3: Substitution for Integrals Involving (x2 - a2)
# Using the substitution: x = a*sec(theta)
# Therefore, dx = a*sec(theta)*tan(theta)dtheta, and the radical
,→ becomes:
# (x2 - a2) = (a2*sec2(theta) - a2) = a*tan(theta)
print("Substitution for (x2 - a2):")
164
x_sub3 = a * sec(theta)
dx_sub3 = diff(x_sub3, theta) # Derivative of a*sec(theta) ==>
,→ a*sec(theta)*tan(theta)
radical3 = sqrt(x_sub3**2 - a**2)
radical3_simpl = simplify(radical3)
print("x substitution: x =", x_sub3)
print("Differential dx/dtheta =", dx_sub3)
print("Simplified radical (x2 - a2) =", radical3_simpl)
# Example: Transform the integral (x2 - a2) dx into the theta
,→ domain.
integral_expr3 = sqrt(x**2 - a**2)
transformed_expr3 = integral_expr3.subs(x, x_sub3) * dx_sub3 #
,→ Replace x and multiply by dx
transformed_expr3_simpl = simplify(transformed_expr3)
print("\nTransformed integral for (x2 - a2) dx =")
print(transformed_expr3_simpl)
165
Chapter 28
Techniques of
Integration: Improper
Integrals
Definition and Classification of Improper
Integrals
An integral is termed improper when either one or both endpoints
of the interval of integration are infinite or when the integrand
exhibits a singular behavior, that is, it becomes unbounded at one
or more points within the interval. In precise terms, an integral of
the form Z ∞
f (x) dx
a
or Z b
f (x) dx,
−∞
is classified as improper due to the unbounded interval. Similarly,
if a function f is defined on a closed interval [a, b] but has a vertical
asymptote at a point c with a < c < b, the integral
Z b
f (x) dx,
a
166
is treated as the limit of two separate integrals,
Z b "Z #
c−ϵ Z b
f (x) dx = lim+ f (x) dx + f (x) dx ,
a ϵ→0 a c+ϵ
provided these limits exist. This chapter provides a rigorous ex-
amination of the techniques that transform these definitions into
practical methods for determining convergence and evaluating the
integrals explicitly.
Evaluation of Integrals with Infinite Lim-
its
In dealing with integrals over an unbounded domain, the funda-
mental strategy is to recast the improper integral as a limit of
definite integrals over finite intervals. To that end, consider an
integral with an infinite upper bound,
Z ∞
f (x) dx.
a
This expression is redefined by introducing a variable upper limit
b and then taking the limit as b → ∞,
Z ∞ Z b
f (x) dx = lim f (x) dx.
a b→∞ a
A crucial aspect of this method is to establish conditions under
which the limit exists and is finite. A similar re-definition holds for
an integral with an infinite lower limit. The convergence of these
integrals rests on the behavior of the function f (x) as x approaches
infinity, and a variety of tests—both heuristic and rigorous—may
be applied to assess this behavior.
Evaluation of Integrals with Unbounded
Integrands
When the integrand f (x) becomes unbounded within the limits of
integration, the integral is approached via a limiting process around
167
the singularity. Suppose f (x) is unbounded at an endpoint a. The
integral
Z b
f (x) dx,
a
is interpreted as
Z b
lim+ f (x) dx.
ϵ→a ϵ
Alternatively, if the singularity occurs at an interior point c of [a, b],
the integral is split at the point of discontinuity:
Z b Z c−ϵ Z b !
f (x) dx = lim+ f (x) dx + f (x) dx .
a ϵ→0 a c+ϵ
The existence of these limits provides a rigorous definition of the
convergence of the improper integral. Central to this analysis is
the precise examination of the asymptotic behavior of f (x) in the
vicinity of the singular point, and techniques frequently involve
comparisons with functions whose integrals are already known to
converge or diverge.
Analytical Techniques and Convergence
Criteria
The evaluation of improper integrals is underpinned by several piv-
otal techniques that facilitate the determination of convergence
as well as the explicit computation of the integrals. A common
approach is to employ the method of substitution to recast the
integrals into forms where standard antiderivatives are available.
In many instances, integration by parts may also be implemented
where the integrand can be expressed as a product of two functions,
one of which possesses an easily integrable derivative.
Convergence analysis is often accomplished via comparison tests.
If a nonnegative function f (x) is bounded above by another func-
tion g(x) for all sufficiently large x, and if the integral
Z ∞
g(x) dx
a
is known to converge, then the integral involving f (x) will also con-
verge. Such techniques depend on carefully estimating the domi-
nant behavior of the integrand as x → ∞ or as x approaches points
where f (x) is unbounded.
168
In addition, the limit comparison test provides a refined tool.
For functions f (x) and g(x) that are nonnegative on the relevant
domain, if
f (x)
lim = L,
x→∞ g(x)
with 0 < L < ∞, then both integrals
Z ∞ Z ∞
f (x) dx and g(x) dx,
a a
either converge or diverge simultaneously. Moreover, alternative
techniques such as the Dirichlet test and the Abel test offer further
analytical tools for handling oscillatory integrands or those with
more intricate asymptotic structures.
The theoretical foundation of improper integrals, encompass-
ing both the definition through limits and the techniques of com-
parison, substitution, and integration by parts, forms the basis
for much of the advanced analysis encountered in this field. Each
method addresses the inherent challenge of evaluating an infinite
process in finite terms, thereby transforming the notion of an “in-
finite extent” into a practical computational framework.
Detailed Methodologies in Handling Un-
bounded Behavior
A rigorous examination of improper integrals often necessitates the
dissection of the underlying function into its dominant components.
For instance, consider an integrand f (x) with asymptotic behavior
akin to x−p for large x. Then the convergence of the integral
Z ∞
x−p dx
a
is entirely determined by the value of p; convergence occurs if and
only if p > 1. This archetypal example underscores the importance
of isolating the rate of decay—or growth—of the integrand in order
to draw conclusions regarding convergence.
When singularities arise within finite intervals, the analytical fo-
cus centers on the local behavior near the point of unboundedness.
In such cases, expanding the integrand into a series representation
or invoking the technique of dominant balance may yield a compar-
ison with a function whose improper integral is well understood.
169
A careful treatment of the limit is then required; the integration
is typically performed over an interval that excludes an arbitrarily
small neighborhood around the singularity, and the limit is taken
as the size of this neighborhood shrinks to zero.
The methods discussed herein reflect a synthesis of classical
analysis and modern rigor. They facilitate not only the compu-
tation of definite values of convergent improper integrals but also
provide a framework for establishing divergence in cases where the
limiting processes fail to yield a finite result. The interplay be-
tween analytical techniques and convergence criteria constitutes a
central theme in the study of improper integrals and exemplifies
the broader challenges encountered in the integration of functions
with inherently infinite or unbounded characteristics.
Python Code Snippet
import numpy as np
from [Link] import quad
import math
def improper_integral_infinite_upper(f, a):
"""
Evaluate an improper integral with an infinite upper limit.
The integral is defined as:
[a,) f(x) dx = lim (b→) [a, b] f(x) dx
Parameters:
f : function
The integrand.
a : float
The lower limit of the integration.
Returns:
result : float
The evaluated integral.
error : float
The estimated absolute error.
"""
result, error = quad(f, a, [Link])
return result, error
def improper_integral_infinite_lower(f, b):
"""
Evaluate an improper integral with an infinite lower limit.
The integral is defined as:
[-, b] f(x) dx = lim (a→-) [a, b] f(x) dx
170
Parameters:
f : function
The integrand.
b : float
The upper limit of the integration.
Returns:
result : float
The evaluated integral.
error : float
The estimated absolute error.
"""
result, error = quad(f, -[Link], b)
return result, error
def improper_integral_singularity(f, a, c, b):
"""
Evaluate an improper integral with a singularity at an interior
,→ point c.
For a function f(x) that is unbounded at c (with a < c < b), the
,→ integral is defined as:
[a, b] f(x) dx = lim(→0){ [a, c-] f(x) dx + [c+, b] f(x) dx
,→ }
Parameters:
f : function
The integrand with a singularity at x = c.
a : float
The lower limit of the integration.
c : float
The point of singularity.
b : float
The upper limit of the integration.
Returns:
approx_value : float
The approximated value of the improper integral.
epsilon_results : list of floats
Approximations obtained for a sequence of decreasing .
"""
# Define a set of epsilon values approaching 0
epsilons = [1e-1, 1e-2, 1e-3, 1e-4, 1e-5]
epsilon_results = []
for eps in epsilons:
left, error_left = quad(f, a, c - eps)
right, error_right = quad(f, c + eps, b)
epsilon_results.append(left + right)
# Use the most refined approximation corresponding to the
,→ smallest epsilon
approx_value = epsilon_results[-1]
return approx_value, epsilon_results
171
# Demonstration of the above algorithms
if __name__ == "__main__":
# Example 1: [1,) 1/x^2 dx
# For p-integrals [a,) 1/x^p dx, convergence occurs if p > 1.
f1 = lambda x: 1.0 / (x**2)
result, error = improper_integral_infinite_upper(f1, 1)
print("[1,) 1/x^2 dx =", result, "with error estimate", error)
# Example 2: [-,0] exp(x) dx
# The exponential decays to 0 on the negative side.
f2 = lambda x: [Link](x)
result, error = improper_integral_infinite_lower(f2, 0)
print("[-,0] exp(x) dx =", result, "with error estimate", error)
# Example 3: [0,1] 1/sqrt(x) dx
# The integrand is singular at x = 0; quad can handle this if
,→ the singular point is specified.
f3 = lambda x: 1 / [Link](x)
result, error = quad(f3, 0, 1, points=[0])
print("[0,1] 1/sqrt(x) dx =", result, "with error estimate",
,→ error)
# Example 4: [0,2] 1/(x-1) dx
# There is a singularity at x = 1, so we split the integral.
f4 = lambda x: 1 / (x - 1)
result, eps_details = improper_integral_singularity(f4, 0, 1, 2)
print("[0,2] 1/(x-1) dx approximated =", result)
print("Intermediate approximations for various epsilons:",
,→ eps_details)
172
Chapter 29
The Fundamental
Theorem of Calculus,
Part I
Preliminaries and Formal Statement
Let f : [a, b] → R be a function that is continuous on the closed
interval [a, b]. Define the function F : [a, b] → R by
Z x
F (x) = f (t) dt.
a
The theorem asserts that the function F is differentiable on the
open interval (a, b) and that its derivative is given by
F ′ (x) = f (x) for all x ∈ (a, b).
This statement establishes the precise connection between differen-
tiation and integration, thereby demonstrating that the operation
of integration, when viewed as the accumulation of area under the
curve of a continuous function, reverses the process of differentia-
tion.
173
Proof of the Fundamental Theorem of Cal-
culus, Part I
For an arbitrary point x in the open interval (a, b), consider the
difference quotient defined by
!
F (x + h) − F (x) 1 1 x+h
Z x+h Z x Z
= f (t) dt − f (t) dt = f (t) dt.
h h a a h x
The continuity of f on the compact interval [x, x + h] ensures that
the Mean Value Theorem for integrals is applicable. Consequently,
there exists a point c in [x, x + h] (or in [x + h, x] if h is negative)
such that Z x+h
f (t) dt = f (c) · h.
x
Substituting back into the difference quotient yields
F (x + h) − F (x)
= f (c).
h
Taking the limit as h tends to 0, and invoking the continuity of f ,
one deduces that
F ′ (x) = lim f (c) = f (x).
h→0
Thus, the derivative of the accumulation function F coincides with
the original continuous function f , thereby rigorously establishing
the theorem.
Analysis of Differentiability and Its Con-
sequences
The foregoing proof delineates a fundamental principle: the oper-
ation of integration, when effected on a continuous function, pro-
duces an antiderivative whose local rate of change recaptures the
original function. The derivation hinges on the continuity of f ,
which guarantees that the mean value of f over a diminishing in-
terval approaches the function’s value at the point of interest. This
intrinsic link not only justifies the procedure of computing integrals
as antiderivatives but also underpins a host of further analytical
methods.
174
The differentiability of the function F , defined as the integral
of f , epitomizes the seamless transition between the two principal
operations of calculus. In rigorous terms, the continuity hypothesis
on f ensures that oscillatory or irregular behavior is precluded,
thereby allowing the limiting process employed in the derivative
definition to yield a unique and well-defined tangent. In situations
where f may exhibit discontinuities on a set of measure zero yet
remains integrable, analogous results hold in almost every point
of the domain, though additional care is required to formulate the
precise conditions under which F retains differentiability.
By codifying the relationship between differentiation and inte-
gration in such an explicit manner, the theorem serves as a concep-
tual cornerstone in the analysis of functions, offering an operational
method for recovering an integrand from its accumulated sum. The
interplay between the smooth behavior of continuous functions and
their integral representations reveals a structural harmony that is
central to the theory of real analysis.
Python Code Snippet
import numpy as np
import [Link] as plt
from [Link] import quad
# Define a continuous function f(t); here we choose f(t) = sin(t) as
,→ an example.
def f(t):
return [Link](t)
# Set the lower limit of integration 'a'
a = 0.0
# Define the accumulation function F(x) as the definite integral of
,→ f from a to x:
# F(x) = [a,x] f(t) dt
def F(x):
# Using quad to numerically integrate f from a to x.
result, _ = quad(f, a, x)
return result
# Compute the derivative of F at a point x using the difference
,→ quotient.
# This approximates F'(x) (F(x+h) - F(x-h)) / (2h)
def derivative_F_center(x, h=1e-5):
return (F(x + h) - F(x - h)) / (2 * h)
175
# Alternatively, one may compute the derivative using the forward
,→ difference quotient:
def derivative_F_forward(x, h=1e-5):
return (F(x + h) - F(x)) / h
# Verification of the Fundamental Theorem of Calculus:
# According to the theorem, for a continuous function f and
,→ F(x)=[a,x] f(t) dt,
# we must have F'(x) = f(x).
# Create an array of x values over the interval of interest.
x_values = [Link](0, 2 * [Link], 100)
# Compute the numerical derivative approximation at each x using the
,→ central difference method.
F_prime_approx = [Link]([derivative_F_center(x) for x in
,→ x_values])
# Compute the original function values f(x)
f_values = f(x_values)
# Plotting the function f(x) and its corresponding derivative F'(x)
,→ approximation.
[Link](figsize=(8, 6))
[Link](x_values, f_values, label="f(x)", linewidth=2)
[Link](x_values, F_prime_approx, '--', label="Approximation of
,→ F'(x)", linewidth=2)
[Link]("Verification of the Fundamental Theorem of Calculus")
[Link]("x")
[Link]("Value")
[Link]()
[Link](True)
[Link]()
# Display a sample numerical comparison at a specific x value.
test_x = [Link] / 4
print(f"For x = {test_x:.4f}:")
print(f"f(x) = {f(test_x):.6f}")
print(f"F'(x) approx = {derivative_F_center(test_x):.6f}")
# Explanation:
# 1. The function F(x) is defined as the integral of f from a fixed
,→ lower limit a up to x.
# 2. The derivative of F, computed numerically as (F(x+h) - F(x-h))
,→ / (2h), should approach f(x)
# as h tends to zero, which is the claim of the Fundamental
,→ Theorem of Calculus, Part I.
# 3. The plot visually confirms that the numerical derivative of
,→ F(x)—the accumulation function—matches f(x).
176
Chapter 30
The Fundamental
Theorem of Calculus,
Part II
Formal Statement and Interpretations
Let f : [a, b] → R be a continuous function and let F : [a, b] → R
denote any antiderivative of f , so that F ′ (x) = f (x) for all x in
the interval [a, b]. The theorem asserts that
Z b
f (x) dx = F (b) − F (a).
a
This equality encapsulates the elegant synthesis of the two central
operations of calculus. In this framework, the process of integra-
tion is reinterpreted through the determination of an antideriva-
tive. The evaluation of the definite integral is achieved by the
simple computation of the difference F (b) − F (a), which reflects
the net accumulation of the continuous function f on the interval
[a, b]. This formulation not only provides computational efficiency
but also reveals a profound insight into the structural relationship
between differentiation and integration.
177
Proof and Justification
Consider the antiderivative F of the function f , satisfying F ′ (x) =
f (x) for every x ∈ [a, b]. Define an auxiliary function G : [a, b] → R
by Z x
G(x) = f (t) dt − F (x).
a
Since f is continuous on [a, b], the function G is differentiable on
(a, b), and differentiation yields
Z x
d
G′ (x) = f (t) dt − F ′ (x) = f (x) − f (x) = 0.
dx a
The vanishing of the derivative G′ (x) on (a, b) indicates that G is
a constant function. Evaluating G at the point x = a, one obtains
Z a
G(a) = f (t) dt − F (a) = 0 − F (a) = −F (a).
a
Hence, G(x) = −F (a) for every x ∈ [a, b], which implies that
Z x
f (t) dt = F (x) − F (a).
a
In particular, setting x = b in the above relation leads directly to
Z b
f (t) dt = F (b) − F (a).
a
This rigorous argument substantiates the theorem and emphasizes
the validity of evaluating a definite integral via an antiderivative.
On the Uniqueness of Antiderivatives and
the Evaluation of Definite Integrals
The preceding discussion implicitly relies on the well-known prop-
erty of antiderivatives: any two antiderivatives of the same con-
tinuous function differ only by a constant. Suppose that F and
H are both antiderivatives of the function f on [a, b], so that
F ′ (x) = H ′ (x) = f (x) for each x in the interval. It follows that
the function K(x) = F (x) − H(x) satisfies
K ′ (x) = F ′ (x) − H ′ (x) = 0.
178
Therefore, K(x) is constant on [a, b], and there exists a constant
C such that F (x) = H(x) + C for every x ∈ [a, b]. This con-
stant difference is of no consequence when computing the difference
F (b) − F (a), as
F (b) − F (a) = [H(b) + C] − [H(a) + C] = H(b) − H(a).
Thus, the evaluation of the definite integral
Z b
f (x) dx = F (b) − F (a)
a
is independent of the particular antiderivative chosen. This inher-
ent uniqueness ensures that the antiderivative method serves as a
robust and unambiguous tool in the analysis and computation of
definite integrals.
Python Code Snippet
# Import necessary libraries for symbolic and numerical computations
import sympy as sp
import numpy as np
from [Link] import quad
import [Link] as plt
# ------------------------------------------------------
# Define the symbolic variable and function
# Let f(x) be a continuous function; we choose f(x) = sin(x) for
,→ demonstration.
x, t = [Link]('x t')
f_expr = [Link](x)
# Compute the antiderivative F(x) of f(x) symbolically.
# For f(x) = sin(x), an antiderivative is F(x) = -cos(x) (up to an
,→ arbitrary constant).
F_expr = [Link](f_expr, x) # F_expr = -cos(x)
# Set up the integration limits, a and b.
a_val = 0
b_val = [Link] # Using symbolic pi
# ------------------------------------------------------
# Fundamental Theorem of Calculus: Evaluate the definite integral
,→ symbolically.
# According to the theorem:
# f(x) dx = F(b) - F(a)
F_b = F_expr.subs(x, b_val)
F_a = F_expr.subs(x, a_val)
179
integral_symbolic = [Link](F_b - F_a)
print("Symbolic Definite Integral of sin(x) from 0 to :")
print(integral_symbolic)
# ------------------------------------------------------
# Validate the result using numerical integration with
,→ [Link].
# Convert the symbolic function to a numerical (lambda) function.
f_numeric = [Link](x, f_expr, 'numpy')
integral_numeric, error = quad(f_numeric, float(a_val),
,→ float(b_val))
print("\nNumerical Definite Integral of sin(x) from 0 to :")
print(integral_numeric)
# ------------------------------------------------------
# Demonstrate the uniqueness of antiderivatives.
# If F(x) is an antiderivative of f(x), then so is F(x) = F(x) + C
,→ for any constant C.
constant_term = 3 # Arbitrary constant
F2_expr = F_expr + constant_term
# Compute F(b) - F(a) which should equal the original F(b) - F(a)
F2_b = F2_expr.subs(x, b_val)
F2_a = F2_expr.subs(x, a_val)
integral_F2 = [Link](F2_b - F2_a)
print("\nDifference using alternative antiderivative (F(x) + 3):")
print(integral_F2)
# ------------------------------------------------------
# Define an auxiliary function G(x) to illustrate the proof of the
,→ theorem.
# Let G(x) = f(t) dt - F(x). Its derivative G'(x) should be zero.
G_expr = [Link](f_expr, (t, a_val, x)) - F_expr
G_expr_simplified = [Link](G_expr)
# The constant value should be -F(a).
constant_G = -F_expr.subs(x, a_val)
print("\nAuxiliary function G(x) simplifies to (constant):")
print(G_expr_simplified)
print("Expected constant value (-F(a)):")
print(constant_G)
# ------------------------------------------------------
# Optional: Plot f(x) and its antiderivative F(x) for visualization.
# Convert F_expr to a numerical function.
F_numeric = [Link](x, F_expr, 'numpy')
# Generate x-values from a to b.
x_vals = [Link](float(a_val), float(b_val), 400)
180
f_vals = f_numeric(x_vals) # Numerical values of f(x)
F_vals = F_numeric(x_vals) # Numerical values of F(x)
# Create the plot.
[Link](figsize=(10, 6))
[Link](x_vals, f_vals, label="f(x) = sin(x)", color='blue')
[Link](x_vals, F_vals, label="F(x) = -cos(x) (antiderivative)",
color='red', linestyle='--')
[Link]("Visualization of f(x) and its Antiderivative F(x)")
[Link]("x")
[Link]("Function values")
[Link]()
[Link](True)
[Link]()
181
Chapter 31
Properties of Definite
Integrals
Linearity of Definite Integrals
Let f and g be integrable functions on the closed interval [a, b], and
let α and β be arbitrary real constants. The linearity property of
the definite integral is expressed by the identity
Z b Z b Z b
(αf (x) + βg(x)) dx = α f (x) dx + β g(x) dx.
a a a
This formula is a direct consequence of the definition of the Rie-
mann integral, where the process of forming Riemann sums pre-
serves the linear combination of function values multiplied by the
width of the subintervals. The fundamental nature of limits, when
applied to these linear combinations, underpins the validity of the
aforementioned equality. The property not only simplifies com-
putations involving sums and scalar multiples but also lays the
groundwork for further theoretical developments in integration the-
ory.
Additivity and Interval Decomposition
For an integrable function f defined on [a, b], consider an arbitrary
point c such that a ≤ c ≤ b. The additivity property, also known
as the interval decomposition property, asserts that the definite
182
integral over the entire interval can be decomposed as the sum of
integrals over the subintervals. More precisely,
Z b Z c Z b
f (x) dx = f (x) dx + f (x) dx.
a a c
This equality reflects the intrinsic additive structure of the definite
integral. In the construction of Riemann sums, the total area under
the curve on [a, b] is obtained by partitioning the interval and sum-
ming the contributions from each subinterval. The property holds
regardless of the location of the partition point c, provided that the
integrability of f on the respective subintervals is maintained. Such
a decomposition is particularly useful in both theoretical proofs
and practical computations, as it allows the integration process to
be localized and managed in smaller segments, thereby facilitating
the study of functions whose behavior may vary significantly over
different parts of the interval.
Symmetry Properties of Definite Integrals
The symmetry properties of definite integrals reveal significant
structural insights when the integrand exhibits specific symmetries.
A primary example is encountered in the case of even and odd func-
tions. A function f : [−a, a] → R is said to be even if f (−x) = f (x)
for all x in its domain. When f is even, the evaluation of the inte-
gral over the symmetric interval [−a, a] simplifies to
Z a Z a
f (x) dx = 2 f (x) dx,
−a 0
since the contributions from the intervals [−a, 0] and [0, a] are
equal. In contrast, if f is odd, so that f (−x) = −f (x), then the
integral over the symmetric interval vanishes:
Z a
f (x) dx = 0.
−a
These results derive from the inherent cancellation or doubling ef-
fects induced by the symmetry of the function.
Another aspect of symmetry in definite integrals pertains to
the effect of reversing the limits of integration. For an integrable
function f on [a, b], the following relation holds:
Z b Z a
f (x) dx = − f (x) dx.
a b
183
This sign change emerges naturally from the orientation of the in-
terval used in the definition of the integral, and it is rigorously jus-
tified by the properties of the Riemann sums and the corresponding
limit process.
The collection of symmetry properties not only streamlines the
evaluation of certain integrals but also provides a deeper insight
into the operation of integration itself, by revealing how the struc-
ture of the integrand interacts with the limits of integration to
produce simplifications and cancellations.
Python Code Snippet
import numpy as np
from [Link] import quad
# Define example functions for integration
def f(x):
"""Example function: f(x) = x^2"""
return x**2
def g(x):
"""Example function: g(x) = sin(x)"""
return [Link](x)
def even_func(x):
"""Even function example: cos(x) is even, since
,→ cos(-x)=cos(x)"""
return [Link](x)
def odd_func(x):
"""Odd function example: sin(x) is odd, since sin(-x) =
,→ -sin(x)"""
return [Link](x)
# A simple Riemann sum algorithm to approximate an integral
def riemann_sum(func, a, b, n=10000):
"""
Approximate the definite integral of a function 'func' over [a,
,→ b]
using a left Riemann sum with n subintervals.
"""
dx = (b - a) / n
x = [Link](a, b - dx, n)
return [Link](func(x)) * dx
# Set up integration parameters
a, b = 0, 1 # Interval for demonstration of linearity and
,→ additivity
184
alpha, beta = 3.0, 2.0 # Arbitrary constants
# ----------------------------------------------------------
# 1. Demonstration of Linearity of Definite Integrals:
#
# The linearity property states that:
# [ f(x) + g(x)] dx = f(x) dx + g(x) dx
# ----------------------------------------------------------
# Compute the integral of the linear combination directly
integral_linear = quad(lambda x: alpha * f(x) + beta * g(x), a,
,→ b)[0]
# Compute the separate integrals and then combine
integral_f = quad(f, a, b)[0]
integral_g = quad(g, a, b)[0]
integral_linear_separated = alpha * integral_f + beta * integral_g
print("Linearity of Definite Integrals:")
print(" Integral of (·f + ·g) over [a, b] =", integral_linear)
print(" ·(Integral of f) + ·(Integral of g) =",
,→ integral_linear_separated)
print(" Difference =", abs(integral_linear -
,→ integral_linear_separated))
print()
# ----------------------------------------------------------
# 2. Demonstration of Additivity and Interval Decomposition:
#
# The additivity property states that:
# f(x) dx = f(x) dx + _c f(x) dx, for any c in [a, b]
# ----------------------------------------------------------
# Choose an intermediate point c in [a, b]
c = 0.5
integral_total = quad(f, a, b)[0]
integral_decomposed = quad(f, a, c)[0] + quad(f, c, b)[0]
print("Additivity and Interval Decomposition:")
print(" Integral over [a, b] =", integral_total)
print(" Integral over [a, c] + [c, b] =", integral_decomposed)
print(" Difference =", abs(integral_total - integral_decomposed))
print()
# ----------------------------------------------------------
# 3. Demonstration of Symmetry Properties of Definite Integrals:
#
# (a) Even function: If f(-x) = f(x), then
# f(x) dx = 2 f(x) dx.
#
# (b) Odd function: If f(-x) = -f(x), then
# f(x) dx = 0.
#
185
# (c) Reversal of limits:
# f(x) dx = - f(x) dx.
# ----------------------------------------------------------
# Even function example: cos(x) over a symmetric interval
sym_limit = [Link] / 3 # Define a symmetric limit
integral_even = quad(even_func, -sym_limit, sym_limit)[0]
integral_even_half = 2 * quad(even_func, 0, sym_limit)[0]
print("Symmetry Properties - Even Function (cos):")
print(" Integral over [-a, a] =", integral_even)
print(" 2 * (Integral over [0, a]) =", integral_even_half)
print(" Difference =", abs(integral_even - integral_even_half))
print()
# Odd function example: sin(x) over a symmetric interval
sym_limit_odd = [Link] / 2
integral_odd = quad(odd_func, -sym_limit_odd, sym_limit_odd)[0]
print("Symmetry Properties - Odd Function (sin):")
print(" Integral over [-a, a] (should be 0) =", integral_odd)
print()
# Reversal of integration limits: using f(x) = x^2 on [a, b]
integral_normal = quad(f, a, b)[0]
integral_reversed = quad(f, b, a)[0]
print("Reversal of Integration Limits:")
print(" Integral over [a, b] =", integral_normal)
print(" Integral over [b, a] =", integral_reversed)
print(" Reversal check (|I[a,b] + I[b,a]|) =", abs(integral_normal
,→ + integral_reversed))
print()
# ----------------------------------------------------------
# 4. Additional Demonstration with Riemann Sum Integration:
#
# Using a Riemann sum to approximate the integral of f(x) = x^2 over
,→ [a, b]
# ----------------------------------------------------------
riemann_integral = riemann_sum(f, a, b, n=100000)
print("Riemann Sum Approximation for f(x) = x^2 over [0, 1]:")
print(" Riemann Sum result =", riemann_integral)
print(" Quad integration result =", integral_f)
print(" Difference =", abs(riemann_integral - integral_f))
186
Chapter 32
Area Under a Curve
Riemann Sums and the Limit Process
Consider a function f defined on the closed interval [a, b]. The
concept of area under the curve, when f is integrable, is rigor-
ously established through the construction of Riemann sums. Let
a partition of the interval [a, b] be given by
P = {x0 , x1 , x2 , . . . , xn }, a = x0 < x1 < · · · < xn = b.
In each subinterval [xi−1 , xi ], define the width as ∆xi = xi − xi−1 .
Select a sample point ξi ∈ [xi−1 , xi ], and consider the sum
n
X
S(P, f ) = f (ξi )∆xi .
i=1
As the norm of the partition, max1≤i≤n ∆xi , approaches zero, these
sums converge (provided that f is integrable) to the definite inte-
gral of f over [a, b]:
Z b n
X
f (x) dx = lim f (ξi )∆xi .
a max ∆xi →0
i=1
This limit encapsulates the precise notion of approximating the
area between the graph of f and the horizontal axis by increasingly
refined collections of rectangles.
187
The Definite Integral as an Area Mea-
surement
When the function f is nonnegative on the interval [a, b], the defi-
nite integral
Z b
f (x) dx
a
can be interpreted geometrically as the area of the region bounded
by the graph of f , the vertical lines x = a and x = b, and the hori-
zontal axis. The additivity properties of the integral ensure that if
the interval [a, b] is subdivided into smaller intervals, the total area
is obtained by summing the areas over these subintervals. In this
context, the integral not only represents a limit of a sum of rect-
angular areas, but also the exact measure of the two-dimensional
region lying under the curve and above the axis. When f assumes
negative values over part of the interval, the integral represents
a signed area, with those portions of the graph lying below the
axis contributing negative values. Consequently, for the purpose of
measuring physical area, one must take the absolute value of such
contributions where appropriate.
Fundamental Theorem of Calculus and
Computation of Areas
For continuous functions defined on [a, b], the process of computing
the area under the curve is significantly simplified by the Funda-
mental Theorem of Calculus. If there exists a function F such
that
F ′ (x) = f (x) for all x ∈ [a, b],
then the area corresponding to the region under f from x = a to
x = b is given by
Z b
f (x) dx = F (b) − F (a).
a
This relation not only substantiates the limiting process involved
in the definition of the definite integral but also provides a practical
computational tool. In many contexts, finding an antiderivative F
reduces the task of evaluating the integral to the substitution of
the endpoints into F , yielding the exact area between the curve
188
and the axis. The method is particularly effective when f or its
antiderivative possesses a closed-form expression, allowing for an
elegant and succinct computation of the area.
Python Code Snippet
import numpy as np
import [Link] as plt
import sympy as sp
def f(x):
"""
Define the function f(x) to be integrated.
Here we use f(x) = x**2 as an example.
"""
return x**2
def riemann_sum(f, a, b, n, method='midpoint'):
"""
Compute the Riemann sum approximation of the definite integral
,→ of f on [a, b]
using the specified method: 'left', 'right', or 'midpoint'.
Parameters:
f : function - the function to integrate.
a, b : float - the integration limits.
n : int - number of subintervals.
method : str - sampling method: 'left', 'right', or
,→ 'midpoint'.
Returns:
sum_val : float - approximate value of the integral.
"""
# Create a partition of [a, b]
x = [Link](a, b, n + 1)
dx = (b - a) / n
if method == 'left':
x_sample = x[:-1]
elif method == 'right':
x_sample = x[1:]
elif method == 'midpoint':
x_sample = (x[:-1] + x[1:]) / 2.0
else:
raise ValueError("Method must be 'left', 'right', or
,→ 'midpoint'")
# Compute the sum f(x_sample) * dx
sum_val = [Link](f(x_sample)) * dx
return sum_val
189
def plot_riemann(f, a, b, n, method='midpoint'):
"""
Plot the function f and its Riemann rectangles for the
,→ approximate integral
using the chosen method over the interval [a, b] with n
,→ subintervals.
Parameters:
f : function - the function to visualize.
a, b : float - the endpoints of the interval.
n : int - number of rectangles (subintervals).
method : str - sampling method: 'left', 'right', or
,→ 'midpoint'.
"""
x = [Link](a, b, n + 1)
dx = (b - a) / n
if method == 'left':
x_sample = x[:-1]
elif method == 'right':
x_sample = x[1:]
elif method == 'midpoint':
x_sample = (x[:-1] + x[1:]) / 2.0
# Evaluate f at the sampling points
y_rect = f(x_sample)
# Generate finer points for plotting the curve of f
x_fine = [Link](a, b, 400)
y_fine = f(x_fine)
[Link](figsize=(8, 4))
[Link](x_fine, y_fine, 'b', label='f(x)')
[Link](x_sample, y_rect, width=dx, alpha=0.3, align='center',
,→ edgecolor='black',
label=f'Riemann ({method}) rectangles')
[Link]('x')
[Link]('f(x)')
[Link](f'Riemann Sum Approximation using
,→ {[Link]()} Method (n = {n})')
[Link]()
[Link](True)
[Link]()
def compute_exact_integral(f_sym, a, b):
"""
Compute the exact value of the integral of the symbolic function
,→ f_sym over [a, b]
using symbolic integration (Fundamental Theorem of Calculus).
Parameters:
f_sym : sympy expression - symbolic representation of f(x).
190
a, b : float/int or sympy expression - integration limits.
Returns:
exact_value : sympy expression - the exact evaluated
,→ integral.
"""
x = [Link]('x')
F = [Link](f_sym, x) # Compute the antiderivative of
,→ f_sym.
exact_value = [Link](x, b) - [Link](x, a) # Evaluate F(b) -
,→ F(a)
return [Link](exact_value)
if __name__ == "__main__":
# Integration limits and number of subintervals
a = 0
b = 3
n = 50
# Compute Riemann sums with different sampling methods
left_sum = riemann_sum(f, a, b, n, method='left')
right_sum = riemann_sum(f, a, b, n, method='right')
midpoint_sum = riemann_sum(f, a, b, n, method='midpoint')
print("Riemann Sum Approximations for _{}^{} f(x) dx, with
,→ f(x)=x2:".format(a, b))
print("Left Riemann Sum =", left_sum)
print("Right Riemann Sum =", right_sum)
print("Midpoint Riemann Sum =", midpoint_sum)
# Plot the function and the Riemann rectangles (using midpoint
,→ method)
plot_riemann(f, a, b, n, method='midpoint')
# Define the symbolic representation of f(x) = x^2 for exact
,→ integration
x = [Link]('x')
f_sym = x**2
exact_integral = compute_exact_integral(f_sym, a, b)
print("\nExact Integral (via the Fundamental Theorem of
,→ Calculus) =", exact_integral)
# Demonstrate improvement with a larger number of intervals
n_large = 1000
midpoint_sum_large = riemann_sum(f, a, b, n_large,
,→ method='midpoint')
print("\nWith n =", n_large, ": Midpoint Riemann Sum =",
,→ midpoint_sum_large)
191
Chapter 33
Volumes of Solids of
Revolution: Disk and
Washer Methods
Disk Method
Let a continuous function f (x) be defined on the closed interval
[a, b], with the property that f (x) ≥ 0 for all x ∈ [a, b]. When the
region under the curve y = f (x) is revolved about the x-axis, the
resulting solid is composed of a continuum of circular disks, each
perpendicular to the x-axis. Consider a representative slice at a
point x with an infinitesimally small thickness dx. The radius of
the circular disk formed by the revolution is f (x), and therefore
the area of the cross section is given by
2
A(x) = π [f (x)] .
The volume of the thin disk is consequently
2
dV = π [f (x)] dx.
The volume V of the entire solid is obtained by summing the vol-
umes of these differential disks over the interval [a, b]. In the limit
as the thickness dx tends to zero, the Riemann sum becomes a
definite integral:
Z b
2
V = π [f (x)] dx.
a
192
This formulation is justified by the process of taking limits of Rie-
mann sums, which ensures that the approximation converges to the
exact volume of the solid of revolution.
Washer Method
In more complex scenarios, the region to be revolved may be bounded
by two distinct functions. Suppose that two continuous functions,
R(x) and r(x), satisfy R(x) ≥ r(x) on the interval [a, b], and con-
sider the region between the curves y = R(x) and y = r(x). When
this region is revolved about the x-axis, each cross-sectional ele-
ment is an annular disk, or washer, with an outer radius R(x) and
an inner radius r(x). The area of the washer is computed as the
difference between the areas of the outer circle and the inner circle:
n o
2 2
A(x) = π [R(x)] − [r(x)] .
A typical washer of infinitesimal thickness dx then contributes a
volume element
n o
2 2
dV = π [R(x)] − [r(x)] dx.
The total volume of the solid formed by the revolution of the region
is determined by integrating these differential volumes over [a, b]:
Z b n o
2 2
V = π [R(x)] − [r(x)] dx.
a
The derivation of this expression follows from the same limiting
process that underlies the disk method, with the modification that
the presence of a hollow region requires subtraction of the volume
corresponding to the inner curve.
Analytical Considerations
The accurate computation of volumes by these methods necessi-
tates a precise determination of the radii defining the cross-sectional
areas. When the solid of revolution is generated by revolving a re-
gion about the x-axis, the radii are measured vertically with respect
to x. In cases where the axis of revolution is displaced from the
coordinate axes, modifications to the expressions for the radii are
required. For instance, revolving a region about the line y = k,
193
where k is a constant, results in a radius expressed as |f (x) − k| or
|R(x) − k| and |r(x) − k| in the washer case. Similarly, if the axis
of revolution is vertical, the roles of x and y must be interchanged,
and the corresponding integrals are set up with respect to y.
The rationale behind both methods derives from the concept of
summing the contributions of infinitely many infinitesimally thin
slices. By partitioning the region into subintervals and considering
the limit as the maximum subinterval width tends to zero, the
Riemann sum yields the exact volume. This approach not only
provides a clear geometric interpretation but also reinforces the
fundamental interplay between integration and the computation of
physical quantities in a rigorous mathematical framework.
The methodical distinction between the disk and washer tech-
niques reflects the inherent geometric characteristics of the region
being revolved. In the absence of an inner boundary, the disk
method directly applies, whereas the existence of a cavity necessi-
tates the use of the washer method. Both formulations exemplify
the versatility and power of integration in resolving intricate volu-
metric problems and underscore the elegant synthesis of geometric
intuition with analytical rigor.
Python Code Snippet
# Import necessary libraries
import numpy as np
from [Link] import quad
import [Link] as plt
# Disk Method: Compute the volume of a solid of revolution when
,→ rotating a region under a curve y = f(x)
def disk_method_volume(f, a, b):
"""
Compute the volume of a solid of revolution using the disk
,→ method.
Parameters:
-----------
f : function
The function defining the curve y = f(x) which is
,→ non-negative on [a, b].
a, b : float
The interval limits of integration.
Returns:
--------
194
volume : float
The computed volume of the solid.
"""
# Define the integrand as pi * [f(x)]^2 (area of the disk)
integrand = lambda x: [Link] * (f(x))**2
volume, error = quad(integrand, a, b)
return volume
# Washer Method: Compute the volume when the region between two
,→ curves is revolved about the x-axis.
def washer_method_volume(R, r, a, b):
"""
Compute the volume of a solid of revolution using the washer
,→ method.
Parameters:
-----------
R : function
The function defining the outer boundary, y = R(x).
r : function
The function defining the inner boundary, y = r(x), where
,→ R(x) >= r(x) on [a, b].
a, b : float
The interval limits of integration.
Returns:
--------
volume : float
The computed volume of the solid.
"""
# The area of a washer is pi * ( [R(x)]^2 - [r(x)]^2 )
integrand = lambda x: [Link] * ((R(x))**2 - (r(x))**2)
volume, error = quad(integrand, a, b)
return volume
# Adjusted Volume for a different axis of rotation (e.g., y = k
,→ instead of the x-axis)
def adjusted_disk_volume(f, a, b, k=0):
"""
Compute the volume of a solid of revolution when the region
,→ under f(x) is rotated
about the horizontal line y = k using the adjusted disk method.
The effective radius becomes |f(x) - k|.
Parameters:
-----------
f : function
The function defining the curve y = f(x).
a, b : float
The interval limits for integration.
k : float, optional
195
The y-coordinate of the axis of rotation (default is 0 which
,→ corresponds to the x-axis).
Returns:
--------
volume : float
The computed volume of the solid.
"""
integrand = lambda x: [Link] * (abs(f(x) - k))**2
volume, error = quad(integrand, a, b)
return volume
# Example usage of the implemented methods
if __name__ == "__main__":
# Example 1: Disk Method with f(x) = sqrt(x) over the interval
,→ [0, 4].
f = lambda x: [Link](x)
a, b = 0, 4
vol_disk = disk_method_volume(f, a, b)
print("Volume using disk method (f(x) = sqrt(x), rotation about
,→ x-axis):", vol_disk)
# Example 2: Washer Method with R(x) = sqrt(x) and r(x) = x/2
,→ over the interval [0, 4].
R = lambda x: [Link](x)
r = lambda x: x / 2
vol_washer = washer_method_volume(R, r, a, b)
print("Volume using washer method (Outer: sqrt(x), Inner: x/2,
,→ rotation about x-axis):", vol_washer)
# Example 3: Adjusted Disk Method for rotation about the line y
,→ = 1 with f(x) = sqrt(x) over [0, 4].
k = 1
vol_adjusted = adjusted_disk_volume(f, a, b, k)
print("Volume using adjusted disk method (f(x) = sqrt(x),
,→ rotation about y = 1):", vol_adjusted)
# Visualization for better understanding
x_vals = [Link](a, b, 400)
y_vals = [Link]([f(x) for x in x_vals])
y_R = [Link]([R(x) for x in x_vals])
y_r = [Link]([r(x) for x in x_vals])
[Link](figsize=(10, 6))
[Link](x_vals, y_vals, label="f(x) = sqrt(x)")
[Link](x_vals, y_R, 'r--', label="R(x) = sqrt(x)")
[Link](x_vals, y_r, 'g--', label="r(x) = x/2")
[Link](0, color="black", linewidth=0.5)
[Link](1, color="purple", linestyle="--", label="y = 1")
[Link]("Functions for Disk and Washer Methods")
[Link]("x")
[Link]("y")
[Link]()
196
[Link](True)
[Link]()
197
Chapter 34
Volumes by the Shell
Method
Fundamental Concepts
The shell method provides an alternative approach for determin-
ing the volume of a solid of revolution. In contrast to the disk and
washer methods, which assemble the volume from a series of disks
or washers perpendicular to the axis of rotation, the shell method
constructs the solid by summing the volumes of slender cylindri-
cal shells. Each shell is generated by revolving an infinitesimally
thin element of the plane about the axis of rotation. When con-
sidering an element located at a distance x from the axis, with an
infinitesimal thickness dx, the resulting shell exhibits a mean ra-
dius of x and a height denoted by h(x). The lateral surface area
of such a cylindrical shell, excluding the top and bottom faces, is
given by 2πx h(x), and multiplication by the thickness dx yields
the differential volume
dV = 2πx h(x) dx.
This relationship encapsulates the geometric foundation of the shell
method and underscores its utility in cases where the region is more
naturally partitioned into elements parallel to the axis of rotation.
198
Derivation of the Integral Expression
The derivation begins with the consideration of a representative
cylindrical shell produced by the rotation of a narrow strip of the
region. For a solid obtained by revolving a region around a vertical
axis, the coordinate x serves as the radius of the shell. If the upper
boundary of the region is described by a function f (x) and the
lower boundary coincides with the axis of rotation, then the height
of the shell is precisely f (x). The volume of this infinitesimal shell
is thus expressed as
dV = 2πx f (x) dx.
Extending this reasoning to regions that are bounded by two curves,
for instance by f (x) and g(x) with f (x) ≥ g(x) on an interval [a, b],
the effective height of the shell becomes f (x) − g(x), resulting in
the differential volume element
dV = 2πx f (x) − g(x) dx.
In both scenarios, the overall volume of the solid is obtained by the
process of integration, yielding
Z b Z b
V = 2π x f (x) dx or V = 2π x f (x) − g(x) dx,
a a
as determined by the specific boundaries of the region. The passage
from the sum of discrete shells to an integral over a continuous
variable is rigorously justified by the limit definition of the Riemann
integral.
Integral Representation and Adaptability
The shell method is particularly advantageous when the region of
interest is defined in terms of the variable that runs parallel to the
axis of rotation. When the axis is vertical, the natural partitioning
of the region into vertical strips leads directly to a formulation in
which x represents both the position of each shell and its associated
radius. Moreover, the method adapts gracefully to configurations
where the axis of rotation is displaced from the coordinate axes.
For example, if the solid is obtained by revolving a region about
the vertical line defined by x = k, the radius of an individual shell
requires modification to become
r(x) = x − k .
199
Consequently, the corresponding differential volume is reformu-
lated as
dV = 2π x − k h(x) dx,
and the aggregate volume of the solid is determined by
Z b
V = 2π x − k h(x) dx.
a
This adaptability illustrates the versatility of the shell method in
handling a broad spectrum of rotational solids. The method’s re-
liance on the concept of accumulation via integration ensures both
its rigor and its effectiveness in solving volumetric problems in a
variety of contexts.
Python Code Snippet
import math
import numpy as np
from [Link] import quad
import sympy as sp
def shell_volume_single(f, a, b):
"""
Compute the volume of a solid of revolution using the shell
,→ method for
a region bounded by the curve f(x) and the axis of rotation
,→ (assumed to be the x-axis).
The solid is generated by revolving the region around the
,→ y-axis.
The volume is calculated using:
V = 2 * pi * [a, b] x * f(x) dx
Parameters:
f : function
The function defining the upper boundary of the region.
a : float
The lower limit of integration.
b : float
The upper limit of integration.
Returns:
volume : float
The computed volume.
"""
integrand = lambda x: x * f(x)
result, error = quad(integrand, a, b)
200
volume = 2 * [Link] * result
return volume
def shell_volume_double(f, g, a, b):
"""
Compute the volume of a solid of revolution using the shell
,→ method when the region
is bounded by two curves, f(x) (upper) and g(x) (lower), and is
,→ revolved around the y-axis.
The volume is calculated using:
V = 2 * pi * [a, b] x * (f(x) - g(x)) dx
Parameters:
f : function
The function defining the upper boundary of the region.
g : function
The function defining the lower boundary of the region.
a : float
The lower limit of integration.
b : float
The upper limit of integration.
Returns:
volume : float
The computed volume.
"""
integrand = lambda x: x * (f(x) - g(x))
result, error = quad(integrand, a, b)
volume = 2 * [Link] * result
return volume
def shell_volume_shifted(f, a, b, k=0):
"""
Compute the volume of a solid of revolution using the shell
,→ method when the axis
of rotation is a vertical line x = k (which can be different
,→ from the y-axis).
The differential volume element is given by:
dV = 2 * pi * |x - k| * f(x) dx
and the total volume is:
V = 2 * pi * [a, b] |x - k| * f(x) dx
Parameters:
f : function
The function defining the boundary of the region.
a : float
The lower limit of integration.
b : float
The upper limit of integration.
k : float, optional
201
The x-coordinate of the vertical axis of rotation.
,→ Default is 0 (y-axis).
Returns:
volume : float
The computed volume.
"""
integrand = lambda x: abs(x - k) * f(x)
result, error = quad(integrand, a, b)
volume = 2 * [Link] * result
return volume
if __name__ == "__main__":
# Example 1: Single boundary function
# Define the function f(x) = sqrt(4 - x^2) representing the
,→ upper boundary
# of a semicircular region of radius 2.
f = lambda x: [Link](4 - x**2) if x >= 0 and x <= 2 else 0
volume_single = shell_volume_single(f, 0, 2)
print("Volume (single boundary, y-axis rotation):",
,→ volume_single)
# Example 2: Double boundary functions
# Define f(x) = sqrt(4 - x^2) as the upper boundary and g(x) = x
,→ / 2 as the lower boundary.
# The region between these curves is revolved around the y-axis.
f2 = lambda x: [Link](4 - x**2) if x >= 0 and x <= 2 else 0
g2 = lambda x: x / 2
volume_double = shell_volume_double(f2, g2, 0, 2)
print("Volume (bounded by two curves, y-axis rotation):",
,→ volume_double)
# Example 3: Axis shifted by k (rotating about x = k)
# Compute the volume when the region under f(x) = sqrt(4 - x^2)
,→ (semicircular region)
# is revolved about the vertical line x = 1.
k = 1
volume_shifted = shell_volume_shifted(f, 0, 2, k)
print("Volume (rotation about vertical line x = 1):",
,→ volume_shifted)
# Example 4: Verification using symbolic integration (for the
,→ single function case)
x = [Link]('x', real=True, positive=True)
f_sym = [Link](4 - x**2)
integral_sym = [Link](x * f_sym, (x, 0, 2))
volume_sym = 2 * [Link] * integral_sym
print("Symbolic Volume (y-axis rotation, single function):",
,→ volume_sym.evalf())
202
Chapter 35
Arc Length
Calculations
Fundamental Concepts and Differential El-
ements
Consider a smooth curve in the Euclidean plane. Let two neighbor-
ing points on the curve have coordinates (x, y) and (x + dx, y + dy),
respectively. The infinitesimal distance between these points is
given by
ds = (dx)2 + (dy)2 .
p
This quantity ds, known as the differential arc length, serves as
the building block for the integral formulation of the total length.
Its derivation is a direct consequence of the Pythagorean theorem
applied in the limit as the separation between points tends to zero.
Arc Length for Graphs in Cartesian Co-
ordinates
For a curve represented as the graph of a continuously differentiable
function y = f (x) over an interval [a, b], the vertical differential dy
is related to dx by
dy = f ′ (x) dx.
203
Substitution into the differential arc length formula yields
q q
2 2
ds = dx + (f (x) dx) = 1 + (f ′ (x)) dx.
2 ′
The complete length L of the curve is then given by the Riemann
integral
Z bq
2
L= 1 + (f ′ (x)) dx.
a
This formulation encapsulates the geometric properties of the curve,
summarizing the incremental contributions of each segment of the
curve.
Arc Length for Parametrically Defined Curves
When a curve is defined parametrically by
x = x(t), y = y(t), t ∈ [α, β],
the differentials transform as dx = dxdt dt and dy = dt dt. Conse-
dy
quently, the differential element of arc length becomes
s
2 2
dx dy
ds = + dt.
dt dt
Thus, the total arc length L is computed via
s
Z β 2 2
dx dy
L= + dt.
α dt dt
This result is valid under the assumption that the functions x(t)
and y(t) are continuously differentiable over the interval [α, β],
thereby ensuring a well-defined and continuous integrand.
Arc Length in Polar Coordinates
A curve described in polar coordinates is given by the equation
r = r(θ), with θ ranging in the interval [θ1 , θ2 ]. The Cartesian
coordinates associated with this curve are expressed as
x = r(θ) cos θ, y = r(θ) sin θ.
204
Differentiation with respect to θ leads to
dr
dx = cos θ − r(θ) sin θ dθ,
dθ
dr
dy = sin θ + r(θ) cos θ dθ.
dθ
Upon computing dx2 + dy 2 , the terms involving cos2 θ and sin2 θ
combine by virtue of the identity sin2 θ + cos2 θ = 1. This simpli-
fication yields the differential arc length
s 2
dr
ds = r(θ)2 + dθ.
dθ
Thus, the total length of the curve is determined by the integral
s 2
Z θ2
dr
L= r(θ)2 + dθ.
θ1 dθ
This expression elegantly captures the interplay between the radial
function r(θ) and its variation with respect to the polar angle θ,
and it extends the technique of arc length calculation to curves
possessing rotational symmetry.
Python Code Snippet
import sympy as sp
# Define the symbols used in our expressions
x = [Link]('x')
t = [Link]('t')
theta = [Link]('theta')
def arc_length_cartesian(f, x, a, b):
"""
Compute the arc length of the graph of a function f = f(x) over
,→ the interval [a, b].
Uses the formula:
L = [a to b] sqrt(1 + (f'(x))^2) dx.
"""
# Compute the derivative f'(x)
f_prime = [Link](f, x)
# Define the integrand sqrt(1 + (f'(x))^2)
integrand = [Link](1 + f_prime**2)
# Compute the integral from a to b
205
L = [Link](integrand, (x, a, b))
return [Link](L)
def arc_length_parametric(x_t, y_t, t, t1, t2):
"""
Compute the arc length of a parametrically defined curve:
x = x(t), y = y(t), for t in [t1, t2].
Uses the formula:
L = [t1 to t2] sqrt((dx/dt)^2 + (dy/dt)^2) dt.
"""
# Compute the derivatives dx/dt and dy/dt
dx_dt = [Link](x_t, t)
dy_dt = [Link](y_t, t)
# Define the integrand sqrt((dx/dt)^2 + (dy/dt)^2)
integrand = [Link](dx_dt**2 + dy_dt**2)
# Compute the integral over the parameter interval
L = [Link](integrand, (t, t1, t2))
return [Link](L)
def arc_length_polar(r_expr, theta, theta1, theta2):
"""
Compute the arc length of a curve expressed in polar
,→ coordinates:
r = r(theta), for theta in [theta1, theta2].
Uses the formula:
L = [theta1 to theta2] sqrt(r(theta)^2 + (dr/dtheta)^2)
,→ dtheta.
"""
# Calculate the derivative dr/dtheta
dr_dtheta = [Link](r_expr, theta)
# Define the integrand sqrt(r^2 + (dr/dtheta)^2)
integrand = [Link](r_expr**2 + dr_dtheta**2)
# Compute the integral over the interval [theta1, theta2]
L = [Link](integrand, (theta, theta1, theta2))
return [Link](L)
if __name__ == '__main__':
# Example 1: Cartesian Arc Length
# Compute arc length for f(x) = sin(x) on the interval [0, pi]
f = [Link](x)
L_cartesian = arc_length_cartesian(f, x, 0, [Link])
print("Cartesian Arc Length for f(x) = sin(x) from x = 0 to
,→ pi:")
[Link](L_cartesian)
print("Numerical Approximation:", sp.N(L_cartesian))
# Example 2: Parametric Arc Length
# Define a circle with parametric equations: x(t) = cos(t), y(t)
,→ = sin(t) for t in [0, 2*pi]
x_t = [Link](t)
y_t = [Link](t)
L_parametric = arc_length_parametric(x_t, y_t, t, 0, 2*[Link])
206
print("\nParametric Arc Length for the circle x = cos(t), y =
,→ sin(t) from t = 0 to 2*pi:")
[Link](L_parametric)
print("Numerical Approximation:", sp.N(L_parametric))
# Example 3: Polar Arc Length
# Consider the circle in polar coordinates given by r(theta) = 1
,→ for theta in [0, 2*pi]
r_expr = 1
L_polar = arc_length_polar(r_expr, theta, 0, 2*[Link])
print("\nPolar Arc Length for r(theta) = 1 from theta = 0 to
,→ 2*pi:")
[Link](L_polar)
print("Numerical Approximation:", sp.N(L_polar))
# Additional Example: Polar Arc Length of a Spiral Curve
# Let r(theta) = theta, for theta in the interval [0, 2*pi]
r_spiral = theta
L_spiral = arc_length_polar(r_spiral, theta, 0, 2*[Link])
print("\nPolar Arc Length for the spiral r(theta) = theta from
,→ theta = 0 to 2*pi:")
[Link](L_spiral)
print("Numerical Approximation:", sp.N(L_spiral))
207
Chapter 36
Surface Area of Solids
of Revolution
Differential Element of Surface Area
The derivation of the surface area for a solid of revolution begins
with a meticulous analysis of an infinitesimal segment of the gen-
erating curve. Let a smooth function y = f (x) be defined on the
closed interval [a, b], with f possessing a continuous first derivative.
The differential arc length along the curve may be expressed as
q
2
ds = 1 + (f ′ (x)) dx.
Upon revolving this differential element about the x-axis, the trace
describes a narrow ribbon-like band. The local radius of the revo-
lution is given by f (x), and the corresponding circular path at this
ordinate has circumference 2πf (x). Accordingly, the differential
contribution to the lateral surface area is
q
2
dS = 2πf (x) ds = 2πf (x) 1 + (f ′ (x)) dx.
This formulation encapsulates both the intrinsic geometry of the
curve and the modulation introduced by its rotation about the axis.
208
Surface Area for Curves Revolved about
the x-Axis
In the classical setting where the curve y = f (x) is revolved about
the x-axis, the total lateral surface area is obtained by integrat-
ing the differential surface element over the relevant interval. The
surface area S is given formally by
Z b q
2
S = 2π f (x) 1 + (f ′ (x)) dx.
a
Here, the integrand 2πf (x) quantifies the circumferential q length of
2
the elemental ring at a typical ordinate, while the factor 1 + (f ′ (x))
accounts for the stretching of the arc element due to the slope of
the curve. The integral synthesizes these contributions over the
interval [a, b], yielding the exact surface area of the resulting solid.
Surface Area for Curves Revolved about
the y-Axis
An analogous derivation applies to curves represented in the form
x = g(y), where g is continuously differentiable on the interval
[c, d]. In this context, the differential arc length is expressed in
terms of the variable y as
q
2
ds = 1 + (g ′ (y)) dy.
Revolving the curve about the y-axis, the instantaneous radius of
revolution is provided by g(y), and the corresponding differential
surface area becomes
q
2
dS = 2πg(y) ds = 2πg(y) 1 + (g ′ (y)) dy.
Integration over the interval [c, d] thus leads to the total surface
area Z d q
2
S = 2π g(y) 1 + (g ′ (y)) dy.
c
This formulation mirrors the methodology applied for revolution
about the x-axis, with the roles of the variables appropriately in-
terchanged.
209
Generalization to Parametric Represen-
tations
The integration techniques may be further generalized to encom-
pass curves described by parametric equations. Let the generating
curve be defined by
x = x(t), y = y(t), t ∈ [α, β],
where the functions x(t) and y(t) are continuously differentiable.
In this framework, the differential arc length is given by
s
2 2
dx dy
ds = + dt.
dt dt
When the curve is revolved about the x-axis, the distance from an
arbitrary point on the curve to the axis is y(t), and the differential
surface area is
s
2 2
dx dy
dS = 2πy(t) ds = 2πy(t) + dt.
dt dt
This expression yields the total surface area through the integral
s
Z β 2 2
dx dy
S = 2π y(t) + dt.
α dt dt
A corresponding derivation for revolution about the y-axis involves
replacing y(t) with x(t) as the distance from the axis of revolution.
These parametric formulations serve to unify and extend the clas-
sical results, accommodating a broad class of curves with complex
geometries.
Python Code Snippet
import numpy as np
from [Link] import quad
def numerical_derivative(func, x, h=1e-6):
"""
Computes the numerical derivative of 'func' at a point x using
the central difference method:
210
f'(x) [func(x+h) - func(x-h)] / (2*h)
"""
return (func(x + h) - func(x - h)) / (2 * h)
def surface_area_x_axis(f, a, b):
"""
Computes the lateral surface area of a solid generated by
,→ revolving
the curve y = f(x) about the x-axis over the interval [a, b].
The formula used is:
S = 2 [a,b] f(x) * sqrt(1 + (f'(x))^2) dx
Parameters:
f : function
The function defining the curve y = f(x).
a, b : float
The limits of integration (domain of x).
Returns:
Surface area S as a float.
"""
integrand = lambda x: f(x) * [Link](1 + numerical_derivative(f,
,→ x)**2)
area, error = quad(integrand, a, b)
return 2 * [Link] * area
def surface_area_y_axis(g, c, d):
"""
Computes the lateral surface area of a solid generated by
,→ revolving
the curve x = g(y) about the y-axis over the interval [c, d].
The formula used is:
S = 2 [c,d] g(y) * sqrt(1 + (g'(y))^2) dy
Parameters:
g : function
The function defining the curve x = g(y).
c, d : float
The limits of integration (domain of y).
Returns:
Surface area S as a float.
"""
integrand = lambda y: g(y) * [Link](1 + numerical_derivative(g,
,→ y)**2)
area, error = quad(integrand, c, d)
return 2 * [Link] * area
def surface_area_parametric(x_func, y_func, t0, t1, axis='x'):
"""
211
Computes the lateral surface area for a solid generated by
,→ revolving
a curve defined parametrically by:
x = x_func(t), y = y_func(t), for t in [t0, t1]
For revolution about the x-axis, the formula is:
S = 2 [t0,t1] y(t) * sqrt((dx/dt)^2 + (dy/dt)^2) dt
For revolution about the y-axis, the formula is:
S = 2 [t0,t1] x(t) * sqrt((dx/dt)^2 + (dy/dt)^2) dt
Parameters:
x_func, y_func : functions
The parametric functions defining the curve.
t0, t1 : float
The parameter interval.
axis : str, optional
The axis of revolution ('x' or 'y'). Default is 'x'.
Returns:
Surface area S as a float.
"""
# Define the derivative of the parametric functions in terms of
,→ t.
ds_dt = lambda t: [Link](numerical_derivative(x_func, t)**2 +
numerical_derivative(y_func, t)**2)
if axis == 'x':
# For revolution about the x-axis, the radius is y(t)
integrand = lambda t: y_func(t) * ds_dt(t)
elif axis == 'y':
# For revolution about the y-axis, the radius is x(t)
integrand = lambda t: x_func(t) * ds_dt(t)
else:
raise ValueError("The argument 'axis' must be either 'x' or
,→ 'y'.")
area, error = quad(integrand, t0, t1)
return 2 * [Link] * area
# ----------------------------------------------
# Demonstration of the implemented functions
# ----------------------------------------------
if __name__ == '__main__':
# Example 1: Explicit function y = f(x)
# Consider f(x) = sqrt(x) defined on the interval [0, 1].
# The lateral surface area when revolved about the x-axis is
,→ computed.
def f(x):
return [Link](x)
a, b = 0, 1
area_x = surface_area_x_axis(f, a, b)
212
print("Surface area (revolution about x-axis) for y = sqrt(x)
,→ from x = 0 to 1:")
print(area_x)
# Example 2: Explicit function x = g(y)
# Consider g(y) = y^2 defined on the interval [0, 1].
# The lateral surface area when revolved about the y-axis is
,→ computed.
def g(y):
return y**2
c, d = 0, 1
area_y = surface_area_y_axis(g, c, d)
print("\nSurface area (revolution about y-axis) for x = y^2 from
,→ y = 0 to 1:")
print(area_y)
# Example 3: Parametric representation
# Define a parametric curve: x = t, y = sqrt(1 - t^2) for t in
,→ [0, 1]
# This represents a segment of a circle. The surface area
,→ generated
# by revolving this curve about the x-axis is computed.
def x_param(t):
return t
def y_param(t):
return [Link](1 - t**2)
t0, t1 = 0, 1
area_param_x = surface_area_parametric(x_param, y_param, t0, t1,
,→ axis='x')
print("\nSurface area (revolution about x-axis) for the
,→ parametric curve x=t, y=sqrt(1-t^2) from t=0 to 1:")
print(area_param_x)
213
Chapter 37
Applications of
Integration in Physics:
Work and Energy
Work in Mechanical Systems
In classical mechanics, work is defined as the energy transferred by
a force acting over a displacement. When a force is applied along
a one-dimensional path, the incremental work done in moving an
object by an infinitesimal distance is represented by
dW = F (x) dx,
where F (x) denotes the force as a function of the spatial coordinate
x. The cumulative work exerted in moving the object from the
position x = a to x = b is obtained by the definite integral
Z b
W = F (x) dx.
a
This integral formulation rigorously accumulates the contributions
of variable forces along a path and serves as the foundation for
analyzing systems in which the applied force is not uniform.
214
Work along Curvilinear Paths
Considering a particle moving along a smooth curve C in Rn , the
displacement is represented by the differential vector dr. For a force
field F defined in the surrounding space, the work done in moving
the particle along the curve is expressed as the line integral
Z
W = F · dr.
C
In the case of a conservative force field, there exists a scalar poten-
tial function U such that
F = −∇U.
Under this circumstance, the work is independent of the path taken
and depends solely on the initial and final positions. It can be
computed by the potential difference,
W = U (r(a)) − U (r(b)),
thus establishing a direct relationship between the work performed
and the change in potential energy of the system.
Energy Computations via Integration
The computation of various forms of energy in physical systems
frequently utilizes integral calculus. For example, the elastic po-
tential energy stored in a deformed spring can be derived from
Hooke’s Law, which states that the restoring force is proportional
to the displacement:
F (x) = −kx,
with k representing the spring constant. The work done in stretch-
ing or compressing the spring from its equilibrium position at x = 0
to an extension or compression of x is
1
Z x
W = kξ dξ = kx2 .
0 2
This expression quantifies the energy stored in the spring based on
the displacement and the stiffness of the medium.
In gravitational systems, the potential energy associated with a
mass elevated against the gravitational force is also determined by
215
integration. If the magnitude of the gravitational force is expressed
as a function of height y, then the work required to elevate a mass
from the height y0 to y1 is given by
Z y1
W = F (y) dy.
y0
This integral encapsulates the energy necessary to overcome the
gravitational field and is fundamental in studies of mechanical equi-
librium and stability.
Integration in Multidimensional Energy
Calculations
For more sophisticated analyses, the integration techniques extend
naturally to situations in which both the force and the displace-
ment are vector quantities. Let the trajectory of a particle be
described by a parameterized curve r(t) for t ∈ [t0 , t1 ], and let
the corresponding force field be denoted by F(r). The differential
displacement along the curve is given by
dr
dr = dt,
dt
and the work done by the force field is then represented as
Z t1
dr
W = F(r(t)) · dt.
t0 dt
This vector formulation accommodates the analysis of work in sys-
tems influenced by spatially varying forces, including those encoun-
tered in electromagnetic fields and fluid dynamics. The integral
framework permits the precise calculation of energy transfers in
multidimensional settings and serves as an essential tool in the
theoretical and applied study of physical phenomena.
Python Code Snippet
# Python code snippet for computing work and energy integrals from
,→ the chapter:
# "Applications of Integration in Physics: Work and Energy".
216
import numpy as np
from [Link] import quad
import math
# 1. Work in one-dimensional mechanical systems
def force_1d(x):
"""
Variable force function F(x) in one dimension.
Example: A linear force F(x) = 2*x + 3.
"""
return 2 * x + 3
def compute_work_1d(force_func, a, b):
"""
Compute the work done by a force along a one-dimensional path.
The work is given by the definite integral:
W = _a^b F(x) dx.
Parameters:
force_func : function representing F(x)
a, b : integration limits
Returns:
work : computed work value
error : estimate of the integration error
"""
work, error = quad(force_func, a, b)
return work, error
# 2. Elastic Potential Energy using Hooke's Law for a Spring
def spring_force(x, k):
"""
Computes the restoring force in a spring based on Hooke's Law.
For a displacement x, F(x) = k * x.
Parameters:
x : displacement
k : spring constant
Returns:
Restoring force magnitude (ignoring the sign).
"""
return k * x
def compute_spring_energy(displacement, k):
"""
Compute the elastic potential energy stored in a deformed
,→ spring.
The work done (energy) has the integral form:
W = _0^x k * d,
which analytically equals 0.5 * k * x^2.
Parameters:
217
displacement : final displacement from the equilibrium (x)
k : spring constant
Returns:
energy : computed elastic energy
error : integration error estimate
"""
energy, error = quad(lambda xi: k * xi, 0, displacement)
return energy, error
# 3. Gravitational Work: Energy required to lift a mass
def gravitational_force(y, m=1.0, g=9.81):
"""
Returns the gravitational force as a function of height y.
For constant g, F(y) = m * g.
Parameters:
y : height (variable, though force is constant in this
,→ approximation)
m : mass of the object
g : gravitational acceleration (default 9.81 m/s^2)
Returns:
Gravitational force magnitude.
"""
return m * g
def compute_gravitational_work(y0, y1, m=1.0, g=9.81):
"""
Compute the work done against gravity to lift a mass from height
,→ y0 to y1.
The work is calculated by:
W = _{y0}^{y1} F(y) dy.
Parameters:
y0, y1 : initial and final heights
m : mass of the object
g : gravitational acceleration
Returns:
work : computed work needed to lift the mass
error : integration error estimate
"""
work, error = quad(lambda y: gravitational_force(y, m, g), y0,
,→ y1)
return work, error
# 4. Work along a Curvilinear Path in a Vector Field
def parametric_curve(t):
"""
Parameterizes a circular path in two dimensions.
For a circle:
x(t) = cos(t), y(t) = sin(t),
218
with t as the parameter.
Parameters:
t : parameter value
Returns:
A numpy array [x, y] representing the point on the curve.
"""
return [Link]([[Link](t), [Link](t)])
def derivative_parametric_curve(t):
"""
Computes the derivative of the parametrically defined circle.
For x(t) = cos(t) and y(t) = sin(t):
dx/dt = -sin(t), dy/dt = cos(t).
Parameters:
t : parameter value
Returns:
A numpy array [dx/dt, dy/dt].
"""
return [Link]([-[Link](t), [Link](t)])
def force_field(r):
"""
Defines a two-dimensional force field.
Example: a rotational field given by:
F(x, y) = [-y, x].
Parameters:
r : numpy array representing the point [x, y]
Returns:
A numpy array representing the force vector at point r.
"""
x, y = r
return [Link]([-y, x])
def line_integral_integrand(t):
"""
Computes the integrand for the line integral representing work.
At parameter t, the integrand is:
F(r(t)) · r'(t),
where r(t) comes from the parametric_curve.
Parameters:
t : parameter value
Returns:
The dot product value at t.
"""
r_t = parametric_curve(t)
219
dr_dt = derivative_parametric_curve(t)
F = force_field(r_t)
return [Link](F, dr_dt)
def compute_line_integral(t0, t1):
"""
Compute the work done along a curvilinear path via numerical
,→ integration.
The work is represented by:
W = _{t0}^{t1} [F(r(t)) · r'(t)] dt.
Parameters:
t0, t1 : start and end values of the parameter t.
Returns:
work : the computed line integral (work)
error : integration error estimate
"""
work, error = quad(line_integral_integrand, t0, t1)
return work, error
# Main function to demonstrate the computations
def main():
# 1. Compute work in one dimension
a, b = 1.0, 3.0
work_1d_val, work_1d_err = compute_work_1d(force_1d, a, b)
print("1D Work from x = {:.1f} to x = {:.1f}: {:.4f} (error:
,→ {:.4e})"
.format(a, b, work_1d_val, work_1d_err))
# 2. Compute Elastic Potential Energy (Spring)
k = 10.0 # Spring constant
displacement = 0.5 # Displacement in meters
spring_energy_val, spring_energy_err =
,→ compute_spring_energy(displacement, k)
analytic_spring_energy = 0.5 * k * displacement**2
print("Spring Energy (Integration): {:.4f} (error: {:.4e}),
,→ Analytical: {:.4f}"
.format(spring_energy_val, spring_energy_err,
,→ analytic_spring_energy))
# 3. Compute Gravitational Work
y0, y1 = 0.0, 5.0 # Heights in meters
mass = 2.0 # Mass in kilograms
grav_work_val, grav_work_err = compute_gravitational_work(y0,
,→ y1, m=mass)
analytic_grav_work = mass * 9.81 * (y1 - y0)
print("Gravitational Work: {:.4f} (error: {:.4e}), Analytical:
,→ {:.4f}"
.format(grav_work_val, grav_work_err, analytic_grav_work))
# 4. Compute Work along a Curvilinear Path
t0, t1 = 0.0, 2 * [Link]
220
line_work_val, line_work_err = compute_line_integral(t0, t1)
print("Line Integral Work along curvilinear path: {:.4f} (error:
,→ {:.4e})"
.format(line_work_val, line_work_err))
if __name__ == '__main__':
main()
221
Chapter 38
Separable Differential
Equations
Definition and Formulation
Consider a first-order ordinary differential equation expressed in
the form
dy
= f (x, y).
dx
The equation is classified as separable if there exist functions F (x)
and G(y) such that
dy
= F (x) G(y).
dx
Upon the assumption that G(y) ̸= 0, it is possible to rearrange the
equation to isolate the variables,
1
dy = F (x) dx.
G(y)
This reorganization establishes a framework wherein each side of
the equation depends solely on one variable, thereby permitting
independent integration.
Method of Separation and Integration
For a separable differential equation of the form
dy
= F (x) G(y),
dx
222
the variables are separated through the algebraic manipulation that
leads to
1
dy = F (x) dx.
G(y)
Subsequent to separation, both sides are integrated with respect to
their corresponding variables:
1
Z Z
dy = F (x) dx.
G(y)
The validity of this procedure is supported by the assumption that
the function G(y) does not vanish on the interval of interest. The
integration typically introduces an arbitrary constant, thereby pro-
ducing an implicit representation of the general solution. When the
result of the integration admits an explicit formulation, the solution
may be written in the form
y = Ψ(x, C),
where Ψ denotes an appropriate function derived from the an-
tiderivatives and C represents the constant of integration.
General Solutions and Integration Tech-
niques
The integration of the separated form,
1
Z Z
dy = F (x) dx,
G(y)
naturally introduces a constant C, leading to an implicit general
solution of the form
H(y) = Φ(x) + C,
where H(y) and Φ(x) are antiderivatives of G(y)
1
and F (x), respec-
tively. In instances where the integrated equation exhibits loga-
rithmic terms, it is customary to exponentiate the expression in
order to isolate the dependent variable. For example, an equation
of the form
ln|h(y)| = Θ(x) + C
can be reexpressed as
|h(y)| = eΘ(x) eC ,
223
with eC subsumed into a new arbitrary constant, often denoted by
A, so that
|h(y)| = A eΘ(x) .
The process of separation and subsequent integration thus not only
yields a family of solutions but also provides insight into the struc-
tural relationship between the variables.
Illustrative Examples
An instructive example is provided by the differential equation
dy
= x y.
dx
This equation is separable and may be reformulated as
1
dy = x dx.
y
Integration of both sides leads to
1
Z Z
dy = x dx,
y
which yields
1 2
ln|y| = x + C.
2
Exponentiating both sides produces the general solution in the im-
plicit form
1 2 1 2
|y| = e 2 x +C = Ae 2 x ,
where A = eC is an arbitrary positive constant.
A more intricate example considers the differential equation
dy xy
= .
dx 1 + y2
The separable structure is revealed by rewriting the equation as
1 + y2
dy = x dx.
y
Decomposition of the left-hand side allows the equation to be ex-
pressed as
1
+ y dy = x dx.
y
224
Integrating term by term,
1
Z Z
+ y dy = x dx,
y
leads to
1 1
ln|y| + y 2 = x2 + C.
2 2
This implicit relation encapsulates the general solution associated
with the original differential equation, with the constant C em-
bodying the family of solutions corresponding to different initial
conditions.
The method of separation of variables serves as a powerful and
widely applicable technique for addressing first-order differential
equations that admit a separable structure. Through systematic
algebraic manipulation and integration, the procedure yields solu-
tions that, while sometimes only implicit, frequently provide sig-
nificant analytical insight into the behavior of the system under
consideration.
Python Code Snippet
# Import necessary libraries for symbolic computation and plotting
import sympy as sp
import numpy as np
import [Link] as plt
# Define symbolic variables and the constant of integration
x, y, C = [Link]('x y C', real=True)
# Define a generic function f, if needed
f = [Link]('f')
def solve_separable_equation(F_expr, G_expr):
"""
Solves a separable differential equation of the form:
dy/dx = F(x) * G(y)
under the assumption that G(y) 0 over the interval of interest.
The method rearranges the equation to:
1/G(y) dy = F(x) dx
and integrates both sides. The general implicit solution is
,→ given by:
H(y) = (x) + C
where H(y) and (x) are antiderivatives of 1/G(y) and F(x),
,→ respectively.
Parameters:
225
F_expr : sympy expression in x (the F(x) part)
G_expr : sympy expression in y (the G(y) part)
Returns:
sol : A sympy Equality object representing the implicit
,→ general solution.
"""
# Separate variables: integrate 1/G(y) with respect to y and
,→ F(x) with respect to x
integral_y = [Link](1/G_expr, y)
integral_x = [Link](F_expr, x)
# Form the implicit general solution
sol = [Link](integral_y, integral_x + C)
return sol
# -----------------------------------------------------------
# Example 1: Solve the separable differential equation: dy/dx = x*y
#
# This equation can be written as:
# (1/y) dy = x dx
# Integrating both sides yields:
# ln|y| = (1/2)x^2 + C
# Exponentiation then gives the explicit solution:
# y = A * exp((1/2)x^2), where A = exp(C)
# -----------------------------------------------------------
F_expr1 = x # F(x) = x, from dy/dx = x*y
G_expr1 = y # G(y) = y, so that 1/G(y) = 1/y
solution1 = solve_separable_equation(F_expr1, G_expr1)
print("General (Implicit) Solution for dy/dx = x*y:")
sp.pretty_print(solution1)
# Exponentiating to obtain the explicit solution:
# ln|y| = (1/2)x**2 + C -> |y| = exp((1/2)x**2 + C) =
,→ A*exp((1/2)x**2)
explicit_solution1 = [Link](y, [Link](([Link](1,2))*x**2 + C))
print("\nGeneral Explicit Form (up to the absolute value and
,→ arbitrary constant):")
sp.pretty_print(explicit_solution1)
# -----------------------------------------------------------
# Example 2: Solve the separable differential equation: dy/dx =
,→ (x*y)/(1+y**2)
#
# Rearranging gives:
# (1+y**2)/y dy = x dx
# Integrating yields:
# ln|y| + (1/2)y**2 = (1/2)x**2 + C
# This implicit equation represents the general solution.
# -----------------------------------------------------------
F_expr2 = x # F(x) = x
226
G_expr2 = y/(1+y**2) # G(y) = y/(1+y**2), so that 1/G(y) =
,→ (1+y**2)/y
solution2 = solve_separable_equation(F_expr2, G_expr2)
print("\nGeneral (Implicit) Solution for dy/dx = (x*y)/(1+y**2):")
sp.pretty_print(solution2)
# -----------------------------------------------------------
# Plot the solution curve for Example 1 with an initial condition
#
# For the equation dy/dx = x*y, if we choose y(0)=1 then A = 1, and
,→ the explicit
# solution is: y = exp((1/2)x^2).
# We plot this solution over a chosen interval.
# -----------------------------------------------------------
# Set the constant A (A = exp(C)) based on the initial condition
,→ y(0)=1.
A = 1
# Create a numerical function from the explicit solution
f_solution = [Link](x, A*[Link](([Link](1,2))*x**2),
,→ 'numpy')
# Generate an array of x values
x_vals = [Link](-2, 2, 400)
# Compute the corresponding y values using the numerical function
y_vals = f_solution(x_vals)
# Plot the solution curve
[Link](figsize=(8, 4))
[Link](x_vals, y_vals, label=r'$y = e^{x^2/2}$')
[Link]('Solution Curve for dy/dx = x*y with y(0)=1')
[Link]('x')
[Link]('y')
[Link]()
[Link](True)
[Link]()
227
Chapter 39
First Order Linear
Differential Equations
General Form and Preliminaries
A first order linear differential equation is conventionally expressed
in the form
dy
+ P (x) y = Q(x),
dx
where P (x) and Q(x) are functions defined on an interval of the
real line. The structure of linearity in the dependent variable y
permits the diverse application of analytical techniques. In this
formulation, the coefficient function P (x) plays a central role in
characterizing the behavior of the homogeneous part of the equa-
tion, while Q(x) represents an external forcing term. Under the
assumption that P (x) and Q(x) are continuous on the interval in
consideration, existence and uniqueness theorems guarantee that
given an initial condition, a unique solution exists.
Derivation and Application of the Inte-
grating Factor
The integrating factor method is a systematic technique for re-
solving the canonical form of the linear differential equation. The
approach is anchored in the observation that multiplication of the
228
entire equation by an appropriately chosen function µ(x) can con-
vert the left-hand side into the derivative of a product. Let
R
µ(x) = e P (x) dx .
Multiplication of the differential equation by µ(x) yields
dy
µ(x) + µ(x)P (x) y = µ(x)Q(x).
dx
The left-hand side of the equation may be recognized as the deriva-
tive with respect to x of the product µ(x)y, since
d dy
(µ(x)y) = µ(x) + µ′ (x)y and µ′ (x) = µ(x)P (x).
dx dx
Thus, the differential equation is recast as
d
(µ(x)y) = µ(x)Q(x).
dx
Integration with respect to x furnishes
Z
µ(x)y = µ(x)Q(x) dx + C,
where C is the constant of integration. Isolation of the dependent
variable leads to an explicit representation of the solution:
1
Z
y(x) = µ(x)Q(x) dx + C .
µ(x)
This method leverages the product rule and the properties of expo-
nential functions, thus reducing the task of solving the differential
equation to the evaluation of integrations.
Solution via Decomposition into Homo-
geneous and Particular Components
An alternate systematic method entails decomposing the solution
into its homogeneous and particular parts. The homogeneous equa-
tion associated with
dy
+ P (x)y = Q(x)
dx
229
is given by
dy
+ P (x)y = 0.
dx
This separable equation admits a general solution of the form
R
yh (x) = Ce− P (x) dx ,
where C is an arbitrary constant. For the inhomogeneous equation,
a particular solution yp (x) is sought such that when substituted
into the complete equation the differential relation is satisfied. One
method for finding yp (x) involves the variation of parameters tech-
nique. In this approach, the constant C in the homogeneous solu-
tion is replaced by a function u(x), so that
R
yp (x) = u(x)e− P (x) dx .
Substitution of yp (x) into the differential equation results in an
equation for u(x) that is amenable to separation and integration.
In many instances, the particular form of Q(x) facilitates the direct
determination of u(x), thereby yielding an explicit expression for
yp (x).
Once a particular solution is identified, the general solution to
the original equation is expressed by the superposition principle as
R
y(x) = yh (x) + yp (x) = Ce− P (x) dx + yp (x).
This decomposition not only underscores the linearity of the dif-
ferential equation but also provides substantial insight into the un-
derlying structure of the solution space.
Each of the methodologies outlined, whether via the integrating
factor or the decomposition into homogeneous and particular parts,
systematically reduces the problem to the evaluation of integrals.
The methods exhibit considerable elegance and power when applied
to linear differential equations, ensuring that the procedure remains
both general in its applicability and concrete in its execution.
Python Code Snippet
# Import required functions from sympy for symbolic mathematics
from sympy import symbols, Function, exp, integrate, dsolve, Eq,
,→ pprint, init_printing
230
# Initialize pretty printing for nice output display in the console
init_printing(use_unicode=True)
# Define the independent variable and the arbitrary constant of
,→ integration
x, C1 = symbols('x C1')
# Define the dependent function y as a function of x
y = Function('y')
def solve_first_order_linear_ode(P_expr, Q_expr):
"""
Solves a first order linear differential equation of the form:
dy/dx + P(x)*y = Q(x)
using the integrating factor method.
Parameters:
P_expr : sympy expression representing P(x)
Q_expr : sympy expression representing Q(x)
Returns:
mu : The integrating factor mu(x) =
,→ exp(integrate(P(x), x))
homogeneous : The homogeneous solution y_h(x) =
,→ C1*exp(-integrate(P(x), x))
general : The general solution y(x) =
,→ (integrate(mu*Q(x), x) + C1) / mu(x)
dsolve_result : The solution from sympy's dsolve (for
,→ verification)
"""
# Step 1: Compute the integrating factor
mu = exp(integrate(P_expr, x))
# Step 2: Write the homogeneous solution:
# y_h(x) = C1 * exp(-integrate(P(x), x))
homogeneous = C1 * exp(-integrate(P_expr, x))
# Step 3: Multiply the original ODE by the integrating factor so
,→ that the left-hand side
# becomes the derivative of (mu(x)*y(x)). Then, integrate to
,→ obtain:
# mu(x)*y(x) = integrate(mu(x)*Q(x), x) + C1
integrated_expr = integrate(mu * Q_expr, x)
# Step 4: Solve for y(x) to get the general solution:
general = (integrated_expr + C1) / mu
# For verification, use sympy's dsolve on the ODE:
# dy/dx + P(x)*y = Q(x)
ode = Eq(y(x).diff(x) + P_expr * y(x), Q_expr)
dsolve_result = dsolve(ode, y(x))
return mu, homogeneous, general, dsolve_result
231
# Example usage:
# Define example functions P(x) and Q(x):
# For instance, consider the differential equation:
# dy/dx + (2/x)*y = 1
# where P(x) = 2/x and Q(x) = 1.
P_expr = 2/x
Q_expr = 1
# Solve the ODE using the integrating factor procedure function
mu, homogeneous_solution, general_solution, dsolve_solution =
,→ solve_first_order_linear_ode(P_expr, Q_expr)
# Display the computed integrating factor
print("Integrating Factor, mu(x):")
pprint(mu)
# Display the homogeneous solution
print("\nHomogeneous Solution, y_h(x) = C1*exp(-P(x)dx):")
pprint(homogeneous_solution)
# Display the general solution obtained via the integrating factor
,→ method
print("\nGeneral Solution, y(x):")
pprint(general_solution)
# Display the solution from sympy's dsolve for verification
print("\nVerification using dsolve:")
pprint(dsolve_solution)
232
Chapter 40
Exact Differential
Equations and
Integrating Factors
Definition and Identification of Exact Dif-
ferential Equations
A first order differential equation expressed in the form
M (x, y) dx + N (x, y) dy = 0
is said to be exact if there exists a continuously differentiable scalar
function
ψ(x, y)
such that
∂ψ ∂ψ
(x, y) = M (x, y) and (x, y) = N (x, y)
∂x ∂y
for all (x, y) in a simply connected domain. In this case, the total
differential of ψ(x, y) is given by
∂ψ ∂ψ
dψ(x, y) = dx + dy = M (x, y) dx + N (x, y) dy,
∂x ∂y
so that the vanishing of dψ(x, y) implies that ψ(x, y) = C, with
C being a constant. The necessary and sufficient condition for
233
exactness on a simply connected region is the equality of the mixed
partial derivatives, namely,
∂M ∂N
(x, y) = (x, y).
∂y ∂x
Determining the Potential Function
Upon verification of the exactness condition, the next step involves
the reconstruction of the potential function ψ(x, y). Given that
∂ψ
(x, y) = M (x, y),
∂x
an antiderivative of M (x, y) with respect to x is obtained while
treating y as a parameter:
Z
ψ(x, y) = M (x, y) dx + h(y),
where h(y) is an undetermined function solely dependent on y.
Differentiation of the resulting expression with respect to y yields
Z
∂ψ ∂
(x, y) = M (x, y) dx + h′ (y).
∂y ∂y
This expression must coincide with N (x, y). Consequently, the
function h(y) is determined by equating
Z
∂
M (x, y) dx + h′ (y) = N (x, y).
∂y
Integration of h′ (y), once isolated, provides the full specification
of the potential function. The general solution to the differential
equation is then implicit in the relation
ψ(x, y) = C.
Integrating Factors and Their Role in Nonex-
act Equations
A differential equation that fails the exactness test may be rendered
exact by the multiplication of an appropriately chosen function
234
µ(x, y), known as the integrating factor. If there exists a function
µ(x, y) such that the modified differential equation
µ(x, y)M (x, y) dx + µ(x, y)N (x, y) dy = 0
satisfies the condition
∂ ∂
[µ(x, y)M (x, y)] = [µ(x, y)N (x, y)],
∂y ∂x
then the resulting equation is exact. Frequently, the search for an
integrating factor is simplified by assuming specific dependencies;
for example, µ may depend only on x or only on y.
1 Integrating Factors Depending on a Single Vari-
able
Assume that the integrating factor is a function solely of x, denoted
by µ(x). Under this assumption, the exactness condition for the
multiplied equation becomes
d d
[µ(x)M (x, y)] = [µ(x)N (x, y)].
dy dx
Since the derivative of µ(x) with respect to y vanishes, the con-
dition can be rearranged and simplified to an expression involving
µ(x) and its derivative µ′ (x). A similar analysis holds if one as-
sumes that µ is a function solely of y. Once an appropriate inte-
grating factor is determined, its application converts the original
differential equation into an exact one, allowing the methods dis-
cussed in the preceding sections to be applied.
2 Derivation of Integrating Factors
Consider the scenario in which µ = µ(x) is postulated. The asso-
ciated exactness condition transforms into
∂M ∂N
µ(x) (x, y) = µ′ (x)N (x, y) + µ(x) (x, y).
∂y ∂x
Rearrangement for µ′ (x)/µ(x) often yields an expression solely in
terms of x, facilitating determination of µ(x) by integration:
µ′ (x)
= ϕ(x).
µ(x)
235
Integration then provides
Z
µ(x) = exp ϕ(x) dx .
A parallel approach is viable when assuming µ = µ(y). The exis-
tence of such integrating factors, whether dependent on one vari-
able or both, is contingent on the structure of M and N . The invo-
cation of integrating factors is not solely a procedural contrivance
but reveals a deeper structure in the differential equation, encapsu-
lating how nonexactness may be remedied through multiplication
by a strategically chosen function.
Application and Resolution of Nonexact
Equations
For a differential equation that is not exact, the detection of a suit-
able integrating factor the transformation of the equation into an
exact form is the pivotal step before proceeding to the construction
of the potential function. Once µ(x, y) is determined, the proce-
dure outlined above for exact equations is applied, resulting in the
representation
Z
ψ(x, y) = µ(x, y)M (x, y) dx + H(y),
where the function H(y) is adjusted to satisfy
∂ψ
(x, y) = µ(x, y)N (x, y).
∂y
Subsequent imposition of the constant C in the implicit solution
ψ(x, y) = C
completes the resolution of the differential equation. The method
illuminates the intrinsic link between the structure of the differen-
tial equation and the adjustments required to balance the differ-
ential terms. Integration factors thereby serve as a powerful tool
to systematically address nonexactness and to reveal the underly-
ing potential function that governs the dynamics described by the
equation.
236
Python Code Snippet
import sympy as sp
# Define the symbolic variables
x, y = [Link]('x y')
# Define the functions M(x,y) and N(x,y) for the differential
,→ equation:
# M(x,y) dx + N(x,y) dy = 0
# For this example, consider the nonexact differential equation:
# M(x,y) = x*y + y
# N(x,y) = x**2 + x
M = x*y + y
N = x**2 + x
def is_exact(M, N):
"""
Check if the differential equation M(x,y) dx + N(x,y) dy = 0 is
,→ exact.
This is true if the partial derivative of M with respect to y
,→ equals
the partial derivative of N with respect to x.
"""
return [Link]([Link](M, y) - [Link](N, x)) == 0
# Check exactness of the given differential equation
if is_exact(M, N):
print("The differential equation is exact.")
mu = 1 # No integrating factor is needed
else:
print("The differential equation is not exact. Computing an
,→ integrating factor...")
# Attempt to find an integrating factor that depends only on x.
# An integrating factor mu(x) can be computed by:
# mu(x) = exp(integral((M_y - N_x) / N dx))
expr_x = [Link](([Link](M, y) - [Link](N, x)) / N)
# Check if expr_x is a function solely of x
if expr_x.free_symbols <= {x}:
mu = [Link]([Link](expr_x, x))
print("Integrating factor mu(x) found:", mu)
else:
# If not, attempt an integrating factor that depends only on
,→ y:
# mu(y) = exp(integral((N_x - M_y) / M dy))
expr_y = [Link](([Link](N, x) - [Link](M, y)) / M)
if expr_y.free_symbols <= {y}:
mu = [Link]([Link](expr_y, y))
print("Integrating factor mu(y) found:", mu)
else:
print("No integrating factor depending solely on x or y
,→ could be determined.")
237
mu = 1 # Fallback
# Multiply the original equation by the integrating factor mu(x,y)
M_tilde = [Link](mu * M)
N_tilde = [Link](mu * N)
print("\nModified functions after applying the integrating factor:")
print("M_tilde =", M_tilde)
print("N_tilde =", N_tilde)
# Verify that the modified differential equation is now exact
if [Link]([Link](M_tilde, y) - [Link](N_tilde, x)) == 0:
print("\nThe modified equation is exact.")
else:
print("\nError: The integrating factor did not yield an exact
,→ equation.")
# Determine the potential function psi(x,y) such that:
# psi_x = M_tilde and psi_y = N_tilde.
# Begin by integrating M_tilde with respect to x.
psi = [Link](M_tilde, x)
# Note: The integration with respect to x may introduce an arbitrary
,→ function of y.
# Denote this unknown function as h(y) and determine it by
,→ differentiating psi with respect to y.
psi_y_partial = [Link](psi, y)
# The remaining part h'(y) is obtained by:
h_prime_expr = [Link](N_tilde - psi_y_partial)
# Integrate h_prime_expr with respect to y to obtain h(y)
h_expr = [Link](h_prime_expr, y)
# The full potential function psi(x,y) is then:
psi = [Link](psi + h_expr)
print("\nThe potential function psi(x,y) is:")
[Link](psi)
print("\nThe general solution to the differential equation is given
,→ implicitly by:")
print("psi(x,y) = C (where C is an arbitrary constant)")
238
Chapter 41
Slope Fields and
Qualitative Analysis
Fundamental Concepts of Slope Fields
Let dx
dy
= f (x, y) denote a first order ordinary differential equation
defined on a domain Ω ⊂ R2 . For each point (x, y) ∈ Ω, a slope field
assigns a short line segment whose orientation reflects the value
f (x, y). This graphical representation encapsulates the local be-
havior of solution curves by indicating their tangential direction at
each point. Under the hypothesis that f is continuous and satisfies
suitable Lipschitz conditions, the Picard-Lindelöf theorem guaran-
tees that through every point in Ω there exists a unique solution
curve whose tangent at (x, y) coincides with the computed slope
f (x, y). Despite the potential intractability of obtaining an explicit
solution, the aggregate of these infinitesimal directional precursors
conveys the qualitative structure of the differential system.
Graphical Construction of Slope Fields
The construction of a slope field commences with the discretiza-
tion of the (x, y)-plane into a grid {(xi , yj )}. At each grid point,
the evaluation of mij = f (xi , yj ) determines the slope of a short
line segment drawn through (xi , yj ). These segments, commonly
rendered with uniform length to emphasize directional informa-
tion, collectively form a mosaic that approximates the behavior
239
of tangent lines to potential solution curves. The overlay of iso-
clines, curves along which f (x, y) assumes constant values, further
refines the graphical depiction by highlighting regions of alike slope
characteristics. Such a representation not only reflects the local di-
rectional tendencies but also augments the overall visualization of
the integral curves dictated by the differential equation.
Qualitative Interpretation of Slope Fields
The ensemble of line segments present in a slope field serves as a
canvas upon which the qualitative dynamics of the differential equa-
tion are inscribed. In areas where the segments exhibit coherent
alignment, the corresponding solution trajectories are inferred to
evolve in a nearly uniform manner. Regions where f (x, y) = 0 are
signaled by horizontal line segments, marking equilibrium positions
that may indicate steady states of the system. Conversely, abrupt
variations in slope orientation signal transitions in the behavior
of solutions and may suggest the presence of bifurcation phenom-
ena or structural instabilities. The identification of such patterns
provides insights into the existence of attractors and repellers and
delineates zones of sensitivity relative to initial conditions, thereby
contributing to the comprehensive understanding of the system’s
qualitative features.
Structural Insights from Slope Field Pat-
terns
A meticulous examination of slope field configurations reveals the
inherent structural patterns within the differential equation. The
spatial distribution of the directional segments can uncover invari-
ant manifolds and expose the topology of basins of attraction as-
sociated with equilibria. In the context of autonomous equations,
where the dependency may reduce to f (y), the field naturally par-
titions the phase plane into regions characterized by consistent dy-
namical behavior. Moreover, the observation of isoclines—curves
along which the slope remains constant—allows for the segmenta-
tion of the domain into subregions that share similar qualitative
dynamics. This structural elucidation facilitates the inference of
asymptotic behaviors, such as the emergence of limit cycles or the
divergence of trajectories over time, thereby furnishing a rich and
240
detailed portrait of the underlying differential system.
Python Code Snippet
import numpy as np
import [Link] as plt
# Define the ODE slope function: dy/dx = f(x, y)
# In this example, we use the function f(x, y) = x - y.
def f(x, y):
return x - y
# Function to plot the slope field on a given domain.
def plot_slope_field(f, x_range, y_range, density=20, color='gray'):
# Create a grid of points over the specified domain
x = [Link](x_range[0], x_range[1], density)
y = [Link](y_range[0], y_range[1], density)
X, Y = [Link](x, y)
# At each grid point, compute the slope given by the ODE f(x,y)
U = np.ones_like(X) # x-component of the direction vector
V = f(X, Y) # y-component of the direction vector
# Normalize the direction vectors so that all arrows have the
,→ same length.
N = [Link](U**2 + V**2)
U_norm = U / N
V_norm = V / N
# Draw the slope field using quiver (arrows without arrowheads
,→ to mimic line segments)
[Link](X, Y, U_norm, V_norm, color=color, angles='xy',
,→ pivot='middle',
headlength=0, headwidth=0, headaxislength=0)
# Function to plot isoclines for specified slope values.
# For the ODE f(x,y) = x - y, setting f(x,y) = m leads to x - y = m,
,→ i.e. y = x - m.
def plot_isoclines(f, x_range, slopes, color='blue',
,→ linestyle='--'):
x = [Link](x_range[0], x_range[1], 300)
# Plot an isocline for each provided slope value
for m in slopes:
y = x - m # Derivation: if x - y = m then y = x - m.
[Link](x, y, color=color, linestyle=linestyle,
,→ label=f'Isocline m={m}')
# To avoid duplicate labels, display legend with a smaller font.
[Link](loc='upper right', fontsize='small')
# Euler's method for approximating the solution of the differential
,→ equation.
241
def euler_method(f, x0, y0, x_end, h):
"""
f : function representing dy/dx = f(x, y)
x0 : initial x value
y0 : initial y value
x_end: end value of x for which the solution is approximated
h : step size for the numerical method
Returns arrays of x and y values approximating the solution.
"""
x_values = [x0]
y_values = [y0]
x, y = x0, y0
# Iterate until we reach the end of the x domain.
while x < x_end:
y = y + h * f(x, y) # Euler update step
x = x + h
x_values.append(x)
y_values.append(y)
return [Link](x_values), [Link](y_values)
# Main function to bring together the slope field, isoclines, and
,→ numerical solution curves.
def main():
# Domain of interest for the plot
x_range = (-5, 5)
y_range = (-5, 5)
# Create a new figure for plotting
[Link](figsize=(8, 6))
# Plot the slope field over the domain using the function f(x,y)
plot_slope_field(f, x_range, y_range, density=20, color='gray')
# Overlay isoclines corresponding to select slope values.
isocline_slopes = [-2, -1, 0, 1, 2]
plot_isoclines(f, x_range, isocline_slopes, color='blue',
,→ linestyle='--')
# Use Euler's method to plot approximated solution curves from
,→ various initial conditions.
initial_conditions = [(-4, 4), (0, 0), (4, -4)]
for x0, y0 in initial_conditions:
x_vals, y_vals = euler_method(f, x0, y0, x_end=5, h=0.1)
[Link](x_vals, y_vals, label=f"Euler approx from ({x0},
,→ {y0})")
# Set plot labels, title, limits, and grid for better
,→ readability.
[Link]("x")
[Link]("y")
[Link]("Slope Field, Isoclines, and Euler's Method
,→ Approximations")
[Link](x_range)
242
[Link](y_range)
[Link](True)
[Link](loc="lower left", fontsize="small")
# Display the final plot.
[Link]()
# Execute the main function when the script is run.
if __name__ == "__main__":
main()
243
Chapter 42
Sequences: Definition
and Basic Properties
Definition of Sequences
A sequence is formally defined as a function whose domain is a
subset of the natural numbers N and whose codomain is typically a
subset of the real numbers R. In precise terms, a sequence {an }n∈N
is a mapping
a : N → R, n 7→ an .
This definition encapsulates the inherent order of a sequence, whereby
each natural number n is uniquely associated with the term an ,
thereby establishing an ordered collection of elements.
Notation and Terminology
The common notation for a sequence is either {an } or (an ), where
the subscript denotes the index corresponding to the term in the
sequence. In instances where the sequence is defined explicitly, an
expression of the form
an = f (n)
indicates the functional relationship governing the nth term. In
contrast, a recursively defined sequence is characterized by the pro-
vision of an initial term (or a finite set of initial terms) together
with a recurrence relation that determines subsequent terms. The
244
index n is commonly taken from N, with the starting point specified
as either n ≥ 1 or n ≥ 0, depending on the context.
Basic Properties of Sequences
Central to the study of sequences is the investigation of proper-
ties that describe their behavior. Among the notable properties
are boundedness, monotonicity, and the structural characteristics
evidenced by typical examples.
1 Boundedness
A sequence {an } is said to be bounded above if there exists a real
number M such that
an ≤ M for all n ∈ N.
Similarly, the sequence is bounded below if there exists a real num-
ber m satisfying
an ≥ m for all n ∈ N.
When both conditions are met, the sequence is classified as bounded;
that is, there exist real numbers m and M for which
m ≤ an ≤ M for all n ∈ N.
Boundedness is an essential attribute in analysis, as it restricts the
possible values attained by the sequence and is fundamental in the
formulation of further analytical concepts.
2 Monotonicity
The property of monotonicity provides insight into the ordered
progression of a sequence. A sequence {an } is deemed increasing if
an+1 ≥ an for all n ∈ N,
and it is designated as strictly increasing if
an+1 > an for all n ∈ N.
Conversely, a sequence is termed decreasing if
an+1 ≤ an for all n ∈ N,
245
with the notion of strictly decreasing reserved for sequences that
satisfy
an+1 < an for all n ∈ N.
Monotonicity imposes a form of regularity in the behavior of the
sequence and serves as a useful tool in analyzing its long-term be-
havior.
3 Typical Examples
Sequences are often illustrated by canonical examples that embody
the foregoing definitions and properties. For instance, the constant
sequence defined by
an = c, c ∈ R,
exemplifies boundedness in the most straightforward manner, while
its invariance renders it both increasing and decreasing simultane-
ously. An arithmetic sequence, given by
an = a + (n − 1)d, a, d ∈ R,
exhibits monotonic behavior, with the nature of the monotonicity
being determined by the sign of the common difference d. Likewise,
a geometric sequence defined by
an = a r n−1 , a, r ∈ R,
demonstrates a multiplicatively determined pattern where the in-
terplay of the initial term a and the common ratio r influences both
its boundedness and monotonicity. These examples illustrate the
diverse ways in which sequences can be constructed and provide a
concrete basis for understanding their fundamental properties.
Discussion of Additional Structural Fea-
tures
Beyond boundedness and monotonicity, sequences may be further
scrutinized through properties such as periodicity, recurrence rela-
tions, and other structural characteristics. The elucidation of these
features enriches the understanding of sequences as analytical ob-
jects and lays the groundwork for a rigorous treatment of conver-
gence and series without presupposing further developments.
246
Python Code Snippet
# This Python code defines functions to generate and analyze
,→ sequences,
# illustrating important formulas and algorithms from the chapter on
# "Sequences: Definition and Basic Properties". The code includes
,→ methods
# to create constant, arithmetic, and geometric sequences, as well
,→ as a
# recursive example (Fibonacci sequence) and an alternating
,→ sequence.
#
# It also provides functions to check for boundedness and
,→ monotonicity,
# including both non-strict and strict definitions.
def constant_sequence(c, n_terms):
"""
Generates a constant sequence of n_terms.
Formula: a_n = c, for all n.
"""
return [c for _ in range(n_terms)]
def arithmetic_sequence(a, d, n_terms):
"""
Generates an arithmetic sequence with n_terms.
Formula: a_n = a + (n-1)*d.
"""
return [a + (n - 1) * d for n in range(1, n_terms + 1)]
def geometric_sequence(a, r, n_terms):
"""
Generates a geometric sequence with n_terms.
Formula: a_n = a * r^(n-1).
"""
return [a * (r ** (n - 1)) for n in range(1, n_terms + 1)]
def is_increasing(seq):
"""
Checks if the sequence is non-strictly increasing.
Returns True if for every consecutive pair, a_(n+1) >= a_n.
"""
return all(seq[i + 1] >= seq[i] for i in range(len(seq) - 1))
def is_strictly_increasing(seq):
"""
Checks if the sequence is strictly increasing.
Returns True if for every consecutive pair, a_(n+1) > a_n.
"""
return all(seq[i + 1] > seq[i] for i in range(len(seq) - 1))
def is_decreasing(seq):
247
"""
Checks if the sequence is non-strictly decreasing.
Returns True if for every consecutive pair, a_(n+1) <= a_n.
"""
return all(seq[i + 1] <= seq[i] for i in range(len(seq) - 1))
def is_strictly_decreasing(seq):
"""
Checks if the sequence is strictly decreasing.
Returns True if for every consecutive pair, a_(n+1) < a_n.
"""
return all(seq[i + 1] < seq[i] for i in range(len(seq) - 1))
def get_bounds(seq):
"""
Returns the lower and upper bounds (minimum and maximum values)
of a finite sequence.
"""
if not seq:
return None, None
return min(seq), max(seq)
def analyze_sequence(seq, name="Sequence"):
"""
Analyzes the sequence by printing its first 10 terms, its
,→ bounds,
and its monotonicity properties.
"""
lower, upper = get_bounds(seq)
print(f"{name}:")
print("First 10 terms:", seq[:10])
print("Lower bound:", lower)
print("Upper bound:", upper)
print("Is increasing (non-strict):", is_increasing(seq))
print("Is strictly increasing:", is_strictly_increasing(seq))
print("Is decreasing (non-strict):", is_decreasing(seq))
print("Is strictly decreasing:", is_strictly_decreasing(seq))
print("-" * 50)
if __name__ == "__main__":
n_terms = 20 # Number of terms to generate for each sequence
# Constant Sequence: a_n = c
c = 5
const_seq = constant_sequence(c, n_terms)
analyze_sequence(const_seq, "Constant Sequence (a_n = 5)")
# Arithmetic Sequence: a_n = a + (n-1)*d
a = 2
d = 3
arith_seq = arithmetic_sequence(a, d, n_terms)
analyze_sequence(arith_seq, "Arithmetic Sequence (a_n = 2 +
,→ (n-1)*3)")
248
# Geometric Sequence: a_n = a * r^(n-1)
a_geo = 2
r = 2
geom_seq = geometric_sequence(a_geo, r, n_terms)
analyze_sequence(geom_seq, "Geometric Sequence (a_n = 2 *
,→ 2^(n-1))")
# Alternating Sequence: a_n = (-1)^n, which is non-monotonic
alt_seq = [(-1) ** n for n in range(n_terms)]
analyze_sequence(alt_seq, "Alternating Sequence ((-1)^n)")
# Recursively defined sequence: Fibonacci Sequence
def fibonacci_sequence(n_terms):
"""
Generates the Fibonacci sequence with n_terms.
Starting values: F_0 = 0, F_1 = 1.
"""
if n_terms <= 0:
return []
if n_terms == 1:
return [0]
seq = [0, 1]
while len(seq) < n_terms:
[Link](seq[-1] + seq[-2])
return seq
fib_seq = fibonacci_sequence(n_terms)
analyze_sequence(fib_seq, "Fibonacci Sequence (F_0 = 0, F_1 =
,→ 1)")
249
Chapter 43
Convergence of
Sequences
Definition of Convergence
A sequence {an }n∈N in R is said to be convergent if there exists
a real number L such that for every ε > 0 there exists a positive
integer N satisfying
|an − L| < ε for all n ≥ N.
In this formulation, the number L is termed the limit of the se-
quence and is denoted by
lim an = L.
n→∞
This ε–N definition encapsulates the notion that the terms of the
sequence eventually remain arbitrarily close to the limit L. Should
no such L exist that fulfills this criterion, the sequence is declared
divergent.
The Cauchy Criterion
A related and notable criterion is expressed through the language
of Cauchy sequences. A sequence {an }n∈N is called Cauchy if for
every ε > 0 there exists a positive integer N such that
|an − am | < ε for all n, m ≥ N.
250
In the complete metric space R, the condition of being Cauchy
is both necessary and sufficient for convergence. This equivalence
offers a powerful tool in the analysis of sequences, especially in
contexts where the limit is not immediately evident.
Monotonic Sequences and the Monotone
Convergence Principle
Monotonicity provides an alternative route to verifying the con-
vergence of sequences. Consider an increasing sequence {an }n∈N ,
meaning that
an ≤ an+1 for all n ∈ N.
If such a sequence is bounded above by some M ∈ R, then the
Monotone Convergence Theorem guarantees that
lim an = sup{an : n ∈ N}.
n→∞
Similarly, a decreasing sequence that is bounded below converges
to its infimum. The interplay between monotonicity and bounded-
ness thus serves as a practical criterion for assessing convergence,
reducing the problem to the determination of appropriate bounds.
Limit Superior and Limit Inferior
For sequences that exhibit oscillatory behavior or do not approach a
unique limit in the conventional sense, the notions of limit superior
and limit inferior provide valuable insight. The limit superior of a
sequence {an } is defined as
lim sup an = lim sup{ak : k ≥ n},
n→∞ n→∞
and the limit inferior is given by
lim inf an = lim inf{ak : k ≥ n}.
n→∞ n→∞
When these two quantities coincide, the common value equals the
limit of the sequence. In cases where lim supn→∞ an ̸= lim inf n→∞ an ,
the sequence fails to converge in the classical sense, yet these con-
structs still capture essential asymptotic features of the sequence.
251
Subsequence Convergence
An important test for convergence relies on the behavior of sub-
sequences. If a sequence {an } converges to a limit L, then every
subsequence {ank } also converges to L. Conversely, if there exist at
least two subsequences converging to distinct limits, the sequence
cannot have a unique limit and is therefore divergent. This criterion
provides a robust method for demonstrating divergence, particu-
larly in situations where the overall sequence exhibits oscillatory
or erratic behavior.
Criteria for Divergence
Divergence may be established by the failure to satisfy the condi-
tions of convergence. If no real number L can be identified such
that for every ε > 0 there exists an integer N with
|an − L| < ε for all n ≥ N,
the sequence is divergent. Divergence may manifest through un-
bounded growth (or decay) where the terms of the sequence ex-
ceed any finite bound, or through inconsistent oscillatory behav-
ior wherein different subsequences approach different accumulation
points. The absence of eventual uniformity in the behavior of {an }
constitutes sufficient evidence of divergence.
Python Code Snippet
import math
def approximate_limit(seq, tail_fraction=0.1):
"""
Approximates the limit of a sequence by averaging the last
,→ tail_fraction of the sequence.
Parameters:
seq (list of float): The sequence of numbers.
tail_fraction (float): The fraction of the sequence (from
,→ the end) to consider for approximating the limit.
Returns:
float: Approximated limit of the sequence.
"""
n = len(seq)
252
tail_start = int(n * (1 - tail_fraction))
tail = seq[tail_start:]
return sum(tail) / len(tail)
def check_epsilon_convergence(seq, tol=1e-5, tail_fraction=0.1):
"""
Checks convergence using the epsilon--N definition.
A sequence is considered convergent if all terms in its tail
,→ (last tail_fraction)
are within tol of the approximated limit.
Parameters:
seq (list of float): The sequence of numbers.
tol (float): Tolerance value for checking convergence.
tail_fraction (float): Fraction of sequence considered as
,→ "tail".
Returns:
(bool, float): Tuple of (convergence status, approximated
,→ limit)
"""
L = approximate_limit(seq, tail_fraction)
n = len(seq)
tail_start = int(n * (1 - tail_fraction))
for a in seq[tail_start:]:
if abs(a - L) >= tol:
return False, L
return True, L
def check_cauchy(seq, tol=1e-5, tail_fraction=0.1):
"""
Checks if the sequence satisfies the Cauchy criterion.
For the tail of the sequence, every pair of terms should have a
,→ difference less than tol.
Parameters:
seq (list of float): The sequence of numbers.
tol (float): Tolerance value for the Cauchy condition.
tail_fraction (float): Fraction of sequence considered as
,→ "tail".
Returns:
bool: True if the sequence satisfies the Cauchy criterion,
,→ False otherwise.
"""
n = len(seq)
tail = seq[int(n * (1 - tail_fraction)):]
for i in range(len(tail)):
for j in range(i + 1, len(tail)):
if abs(tail[i] - tail[j]) >= tol:
return False
return True
253
def is_monotonic(seq):
"""
Checks whether the sequence is monotonic increasing or monotonic
,→ decreasing.
Parameters:
seq (list of float): The sequence of numbers.
Returns:
tuple: (is_increasing, is_decreasing) as booleans.
"""
increasing = all(seq[i] <= seq[i + 1] for i in range(len(seq) -
,→ 1))
decreasing = all(seq[i] >= seq[i + 1] for i in range(len(seq) -
,→ 1))
return increasing, decreasing
def compute_limsup_liminf(seq):
"""
Computes the limit superior and limit inferior of a finite
,→ sequence.
For a sequence {a_n}, limsup is approximated as:
limsup = min_{n} ( sup{a_k : k >= n} )
and liminf as:
liminf = max_{n} ( inf{a_k : k >= n} ).
Parameters:
seq (list of float): The sequence of numbers.
Returns:
(float, float): (limsup, liminf) of the sequence.
"""
n = len(seq)
sup_values = []
inf_values = []
for i in range(n):
tail = seq[i:]
sup_values.append(max(tail))
inf_values.append(min(tail))
limsup = min(sup_values)
liminf = max(inf_values)
return limsup, liminf
def extract_subsequence(seq, start, step):
"""
Extracts a subsequence from the given sequence starting at index
,→ `start` with a given `step`.
Parameters:
seq (list): The original sequence.
start (int): The starting index for the subsequence.
step (int): The step size; every step-th element is taken.
254
Returns:
list: The extracted subsequence.
"""
return seq[start::step]
def test_sequence_properties(seq, name="Sequence"):
"""
Tests and prints various properties of a sequence:
- Approximate limit (via epsilon--N criterion)
- Cauchy criterion satisfaction
- Monotonicity (increasing/decreasing)
- Limit Superior and Limit Inferior
- Subsequence behavior (if applicable)
Parameters:
seq (list of float): The sequence of numbers.
name (str): Name of the sequence for reporting.
"""
print("=" * 40)
print(f"Analyzing {name}:")
print(f"First 10 terms: {seq[:10]}")
print(f"Last 10 terms: {seq[-10:]}")
# Approximate limit using tail average
approx_lim = approximate_limit(seq)
print(f"Approximate Limit (last 10%% average):
,→ {approx_lim:.6f}")
# Check convergence using the epsilon definition
convergent, L = check_epsilon_convergence(seq)
status = "Convergent" if convergent else "Not Convergent"
print(f"Convergence Check (epsilon definition): {status},
,→ Approximated Limit = {L:.6f}")
# Check if the sequence satisfies the Cauchy criterion
cauchy = check_cauchy(seq)
print("Cauchy Criterion Check:",
"Satisfies Cauchy Criterion" if cauchy else "Does Not
,→ Satisfy Cauchy Criterion")
# Check monotonicity of the sequence
inc, dec = is_monotonic(seq)
if inc:
print("The sequence is monotonic increasing.")
elif dec:
print("The sequence is monotonic decreasing.")
else:
print("The sequence is not monotonic.")
# Compute limit superior and limit inferior
limsup, liminf = compute_limsup_liminf(seq)
print(f"Limit Superior (limsup): {limsup:.6f}")
print(f"Limit Inferior (liminf): {liminf:.6f}")
255
print()
def main():
# Example 1: Convergent sequence a_n = 1/n
seq_convergent = [1.0 / n for n in range(1, 101)]
test_sequence_properties(seq_convergent, "Convergent Sequence:
,→ 1/n")
# Example 2: Oscillatory (divergent) sequence a_n = (-1)^n
seq_oscillatory = [(-1)**n for n in range(1, 101)]
test_sequence_properties(seq_oscillatory, "Oscillatory Sequence:
,→ (-1)^n")
# Example 3: Monotonic increasing but divergent sequence a_n = n
seq_monotonic_increasing = [n for n in range(1, 101)]
test_sequence_properties(seq_monotonic_increasing, "Monotonic
,→ Increasing Sequence: n")
# Example 4: Monotonic decreasing but divergent sequence a_n =
,→ -n
seq_monotonic_decreasing = [-n for n in range(1, 101)]
test_sequence_properties(seq_monotonic_decreasing, "Monotonic
,→ Decreasing Sequence: -n")
# Example 5: Subsequence extraction from an oscillatory
,→ sequence.
# Extract even-indexed subsequence from the oscillatory
,→ sequence.
subseq_even = extract_subsequence(seq_oscillatory, start=0,
,→ step=2)
print("Subsequence Analysis: Even-indexed terms from Oscillatory
,→ Sequence")
test_sequence_properties(subseq_even, "Even-indexed Subsequence
,→ of (-1)^n")
if __name__ == "__main__":
main()
256
Chapter 44
Introduction to Series
and Convergence Tests
Infinite Series: Definitions and Notation
Let {an }∞n=1 denote a sequence of real or complex numbers. An
infinite series is written in the form
∞
X
an = a1 + a2 + a3 + · · · ,
n=1
and is understood as the limit of the sequence of partial sums
N
X
SN = an .
n=1
The series is said to converge if there exists a finite number S such
that
lim SN = S.
N →∞
Otherwise, the series is classified as divergent. This formulation
underpins much of the analysis, as it shifts the focus to the behavior
of the partial sums.
257
Convergence and Divergence of Infinite
Series
A central task in the study of infinite series is to determine whether
the sequence of partial sums {SN } approaches a finite limit. Con-
vergence is formally defined by the condition that for every ε > 0
there exists a positive integer N0 such that for all integers M, N ≥
N0 the inequality
XM XN
an − an < ε
n=1 n=1
holds. Equivalently, convergence of {SN } is assured by its Cauchy
property, a consequence of the completeness of the real (or com-
plex) numbers. In contrast, divergence may result from the partial
sums growing without bound or exhibiting oscillatory behavior that
precludes the existence of a limit.
Absolute and Conditional Convergence
The notion of convergence can be refined by distinguishing between
absolute and conditional convergence. An infinite series
∞
X
an
n=1
converges absolutely if the series of the absolute values
∞
X
|an |
n=1
also converges. Absolute convergence is a stronger condition than
convergence alone, as it guarantees that any rearrangement of terms
leaves the sum invariant. In cases where a series converges but the
series of absolute values diverges, the original series is said to be
conditionally convergent. This delineation plays a vital role in the
theoretical treatment of series, especially when addressing issues
such as term reordering and the interplay between sign changes
and magnitude.
258
Comparison Tests
The comparison tests offer powerful tools for establishing conver-
gence or divergence by relating the given series to another series
with known behavior. In the direct comparison test, suppose {an }
and {bn } are sequences with nonnegative terms such that
0 ≤ an ≤ bn
for all n beyond a fixed index. If the series
∞
X
bn
n=1
is convergent, then it follows that
∞
X
an
n=1
P∞
must also converge. Conversely,Pif n=1 an diverges and an ≥ bn ≥
∞
0 for sufficiently large n, then n=1 bn diverges as well.
An extension of this method, known as the limit comparison
test, involves evaluating
an
lim = L.
n→∞ bn
P∞
If L exists
P∞ and is a positive finite number, then the series n=1 an
and n=1 bn either both converge or both diverge. This test is
particularly useful when the terms of the series are asymptotically
comparable to those of a benchmark series.
Ratio and Root Tests
For series whose terms involve factorials, exponentials, or other
rapidly varying functions, the ratio and root tests provide decisive
criteria for convergence. The ratio test considers the limit
an+1
ρ = lim .
n→∞ an
The series converges absolutely if ρ < 1, diverges if ρ > 1, and the
test is inconclusive if ρ = 1.
259
Similarly, the root test examines the quantity
λ = lim n |an |.
p
n→∞
The conclusion mirrors that of the ratio test: absolute convergence
occurs when λ < 1, divergence when λ > 1, and no definitive con-
clusion is reached if λ = 1. Both tests rely on the asymptotic
behavior of the sequence and offer a robust framework for address-
ing the convergence of complex series.
Alternating Series and Other Convergence
Tests
Infinite series composed of alternating terms represent another im-
portant class. A typical alternating series takes the form
∞
X
(−1)n−1 bn ,
n=1
where {bn } is a sequence of nonnegative numbers. The alternating
series test (or Leibniz criterion) asserts that if the sequence {bn } is
monotonically decreasing and satisfies limn→∞ bn = 0, then the al-
ternating series converges. This test not only confirms convergence
but also provides bounds for the error incurred when approximat-
ing the sum by a finite number of terms.
Additional tests, such as the integral test, serve to link the con-
vergence of a series with the convergence of an associated improper
integral. If f (x) is a continuous, positive, and monotonically de-
creasing function for x ≥ 1 such that f (n) = an , then the conver-
gence of Z ∞
f (x) dx
1
P∞
implies the convergence of the series n=1 an , and vice versa.
The assortment of convergence tests discussed here underscores
the richness of techniques available for handling infinite series.
Each test exploits distinct properties of the sequence {an }, and the
choice of an appropriate test is guided by the asymptotic behavior
and structure of the terms. The theoretical framework established
by these tests is essential to both pure and applied mathematical
contexts, providing a rigorous foundation for the analysis of series.
260
Python Code Snippet
import math
# Function to compute the sequence of partial sums
def partial_sums(series):
"""
Compute the sequence of partial sums for a given series (list of
,→ terms).
That is, for a series a_n, compute S_N = a_1 + a_2 + ... + a_N.
"""
sums = []
current_sum = 0.0
for term in series:
current_sum += term
[Link](current_sum)
return sums
# Function to check for convergence using the behavior of partial
,→ sums.
def check_convergence_by_partial_sums(series, tol=1e-6,
,→ min_terms=10):
"""
Check convergence based on the difference between successive
,→ partial sums.
Returns a tuple (converged, limit_estimate) where 'converged' is
,→ True
if the change between successive sums becomes less than tol over
,→ a window.
"""
sums = partial_sums(series)
# Look for stabilization after a minimum number of terms.
for i in range(min_terms, len(sums)):
if abs(sums[i] - sums[i-1]) < tol:
# Additional check: ensure stability over the previous
,→ few terms.
if i > 10 and abs(sums[i] - sums[i-5]) < tol:
return True, sums[i]
return False, sums[-1]
# Ratio Test: Computes the limit of |a_{n+1}/a_n| approximately.
def ratio_test(series, start_index=10):
"""
Implements the ratio test by evaluating:
= lim→ |a/a|.
Returns the average ratio computed over terms starting from
,→ start_index.
A result < 1 indicates absolute convergence, while > 1
,→ indicates divergence.
"""
ratios = []
for i in range(start_index, len(series) - 1):
261
if abs(series[i]) > 0:
ratio = abs(series[i+1]) / abs(series[i])
[Link](ratio)
if not ratios:
return None
return sum(ratios) / len(ratios)
# Root Test: Computes the limit of |a_n|^(1/n) approximately.
def root_test(series, start_index=10):
"""
Implements the root test by evaluating:
= lim→ |a|.
Returns the average n-th root computed over terms starting from
,→ start_index.
A result < 1 indicates absolute convergence, while > 1
,→ indicates divergence.
"""
roots = []
for i in range(start_index, len(series)):
n = i + 1 # because indexing starts at 0, term index is n =
,→ i+1
[Link]([Link](abs(series[i]), 1.0 / n))
if not roots:
return None
return sum(roots) / len(roots)
# Alternating Series Test (Leibniz criterion)
def alternating_series_test(series):
"""
Checks conditions for the alternating series test:
1. The sequence is alternating in sign.
2. The sequence of absolute values is nonincreasing.
3. The limit of the terms is zero.
Returns a tuple: (is_alternating, is_nonincreasing, limit_zero)
"""
# Check that the signs alternate.
is_alternating = True
for i in range(1, len(series)):
if series[i] * series[i - 1] >= 0:
is_alternating = False
break
# Check that the absolute values of the terms are nonincreasing.
is_nonincreasing = True
for i in range(1, len(series)):
if abs(series[i]) > abs(series[i - 1]):
is_nonincreasing = False
break
# Check that the limit of the terms is zero.
limit_zero = [Link](series[-1], 0.0, abs_tol=1e-8)
return is_alternating, is_nonincreasing, limit_zero
262
# Trapezoidal Rule: Numerical integration to approximate an
,→ integral.
def trapezoidal_integration(func, a, b, n_intervals=1000):
"""
Approximate the integral of a function f(x) from a to b using
,→ the trapezoidal rule.
This implements:
f(x) dx (h/2)[f(a) + 2_{i=1}^{n-1} f(a + i*h) + f(b)]
where h = (b - a) / n_intervals.
"""
h = (b - a) / n_intervals
total = 0.5 * (func(a) + func(b))
for i in range(1, n_intervals):
total += func(a + i * h)
return total * h
# Integral Test: Uses numerical integration to test convergence of a
,→ corresponding series.
def integral_test(func, a, b, n_intervals=1000):
"""
Applies the integral test by numerically integrating f(x) from a
,→ to b.
For a series with terms a_n = f(n), if f(x) dx converges as b →
,→ ,
then the series is likely to be convergent.
"""
return trapezoidal_integration(func, a, b, n_intervals)
# Demonstration of the tests and algorithms with example series.
if __name__ == '__main__':
# Example 1: Harmonic Series (divergent)
harmonic_series = [1.0 / n for n in range(1, 20000)]
converged_harm, limit_harm =
,→ check_convergence_by_partial_sums(harmonic_series)
print("Harmonic Series Convergence Check:")
print(" Converged:", converged_harm)
print(" Partial Sum Estimate:", limit_harm)
# Example 2: Geometric Series with common ratio 0.5 (absolutely
,→ convergent)
geometric_series = [0.5 ** n for n in range(1, 200)]
converged_geo, limit_geo =
,→ check_convergence_by_partial_sums(geometric_series)
print("\nGeometric Series Convergence Check:")
print(" Converged:", converged_geo)
print(" Partial Sum Estimate:", limit_geo)
# Ratio Test Results
ratio_harm = ratio_test(harmonic_series)
ratio_geo = ratio_test(geometric_series)
print("\nRatio Test Results:")
print(" Harmonic Series Ratio:", ratio_harm)
263
print(" Geometric Series Ratio:", ratio_geo)
# Root Test Results
root_harm = root_test(harmonic_series)
root_geo = root_test(geometric_series)
print("\nRoot Test Results:")
print(" Harmonic Series Root:", root_harm)
print(" Geometric Series Root:", root_geo)
# Example 3: Alternating Harmonic Series (conditionally
,→ convergent)
alt_harmonic = [((-1) ** (n - 1)) / n for n in range(1, 20000)]
alt_conditions = alternating_series_test(alt_harmonic)
converged_alt, limit_alt =
,→ check_convergence_by_partial_sums(alt_harmonic)
print("\nAlternating Harmonic Series Test:")
print(" Alternating Conditions (is_alternating, nonincreasing,
,→ limit_zero):", alt_conditions)
print(" Convergence Check:", converged_alt)
print(" Partial Sum Estimate:", limit_alt)
# Integral Test: p-series where f(x) = 1/x^p.
# For p > 1 the integral converges; for p <= 1 it diverges.
def f_p(x, p):
return 1.0 / (x ** p)
p_convergent = 1.5 # p > 1: should converge
func_p_conv = lambda x: f_p(x, p_convergent)
integral_conv = integral_test(func_p_conv, 1, 10000,
,→ n_intervals=10000)
print("\nIntegral Test for p-series with p =", p_convergent)
print(" Approximate Integral (1 to 10000):", integral_conv)
p_divergent = 0.9 # p <= 1: should diverge
func_p_div = lambda x: f_p(x, p_divergent)
integral_div = integral_test(func_p_div, 1, 10000,
,→ n_intervals=10000)
print("\nIntegral Test for p-series with p =", p_divergent)
print(" Approximate Integral (1 to 10000):", integral_div)
264
Chapter 45
The Comparison and
Limit Comparison
Tests
The Direct Comparison Test
Let {an }∞
n=1 and {bn }n=1 denote sequences of nonnegative real
∞
numbers. Suppose that there exists an integer N0 ∈ N such that
0 ≤ an ≤ bn for all n ≥ N0 .
The direct comparison test asserts that if
∞
X
bn
n=N0
converges, then the series
∞
X
an
n=N0
must also converge. Conversely, if
∞
X
an
n=N0
265
diverges, then
∞
X
bn
n=N0
necessarily diverges as well.
The underpinnings of the test are found in the properties of
nonnegative series. Because the partial sums
N N
(a) (b)
X X
SN = an and SN = bn
n=1 n=1
are monotonically increasing sequences, the inequality an ≤ bn for
every n ≥ N0 implies that
(a) (b)
SN ≤ SN for all N ≥ N0 .
(b) (a)
Therefore, the boundedness of {SPN } is inherited by {SN }, ensur-
∞
ing the convergence of the series n=N0 an . In the alternative sce-
P∞
nario where divergence of n=N0 an is observed, the lower bound
(b)
on an guarantees that {SN } eventually exceeds
P∞ any prescribed
finite value, leading to the conclusion that n=N0 bn diverges.
The Limit Comparison Test
Consider now the sequences {an }∞n=1 and {bn }n=1 , where it is as-
∞
sumed that an > 0 and bn > 0 for every n ≥ 1. The limit compar-
ison test is formulated by examining the limit
an
lim = L.
n→∞ bn
If the limit L exists as a finite number and satisfies
0 < L < ∞,
then the series
∞
X ∞
X
an and bn
n=1 n=1
exhibit identical convergence behavior; that is, either both series
converge or both diverge.
The rationale behind the limit comparison test can be eluci-
dated by the following argument. Given an arbitrary ϵ > 0, the
266
existence of the limit L ensures that there exists an integer N1 ∈ N
such that for all n ≥ N1 ,
an
− L < ϵ.
bn
This inequality can be manipulated to yield
(L − ϵ)bn < an < (L + ϵ)bn ,
for all n ≥ N1 . The inequality establishes that, aside from a multi-
plicative constant arbitrarily close to L, the term an is asymptot-
ically equivalent to bn . Application of the direct comparison test
to the series formed from (L − P ϵ)bn and (L + ϵ)bn then demon-
∞
strates that the convergence
P∞ of n=1 an is inseparably linked to
the convergence of n=1 bn .
It is imperative to note that if the value of L is either zero
or infinite, the limit comparison test does not yield a definitive
conclusion regarding the convergence properties of the series. The
test is effective solely under the condition that the limit of the
ratio lies strictly between zero and infinity, ensuring a controlled
and proportional relationship between the asymptotic behaviors of
an and bn .
Python Code Snippet
import math
def is_convergent(series_func, N0, max_terms=100000, tol=1e-6):
"""
Heuristically tests for convergence of a series defined by
,→ series_func.
Parameters:
series_func : function
A function that returns the nth term of the series.
N0 : int
The starting index of the series.
max_terms : int, optional
Maximum number of terms to compute (default is 100000).
tol : float, optional
Tolerance for checking stabilization of the partial sum
,→ (default is 1e-6).
Returns:
tuple (converges, partial_sum)
267
converges : bool
True if the partial sums stabilize (suggesting
,→ convergence), False otherwise.
partial_sum : float
The computed partial sum at termination.
"""
partial_sum = 0.0
previous_sum = 0.0
for n in range(N0, max_terms):
term = series_func(n)
partial_sum += term
# Check for stabilization every 1000 terms
if (n - N0) % 1000 == 0:
if abs(partial_sum - previous_sum) < tol:
return True, partial_sum
previous_sum = partial_sum
# If the partial sum grows very large, we assume divergence
if abs(partial_sum) > 1e10:
return False, partial_sum
return False, partial_sum
def direct_comparison_test(a_func, b_func, N0, max_terms=100000,
,→ tol=1e-6):
"""
Applies the Direct Comparison Test to two nonnegative series
,→ a(n) and b(n).
The test assumes that there exists an index N0 such that:
0 <= a(n) <= b(n) for all n >= N0.
If the series for b(n) converges, then a(n) is also convergent.
Alternatively, if the series for a(n) diverges, then the series
,→ for b(n) diverges as well.
Parameters:
a_func : function
A function returning the nth term a(n) of the first
,→ series.
b_func : function
A function returning the nth term b(n) of the second
,→ series.
N0 : int
The index from which the inequality a(n) <= b(n) is
,→ assumed to hold.
max_terms : int, optional
Maximum number of terms to use in convergence testing.
tol : float, optional
Tolerance used in the heuristic convergence test.
Returns:
str
A message with the conclusion of the test.
"""
268
# Verify the inequality a(n) <= b(n) holds for a number of terms
,→ starting at N0
check_range = 1000
for n in range(N0, N0 + check_range):
if a_func(n) > b_func(n):
return f"Inequality condition a(n) <= b(n) fails at n =
,→ {n}."
# Test convergence for series b(n)
converges_b, sum_b = is_convergent(b_func, N0, max_terms, tol)
if converges_b:
message = ("Since the series for b(n) converges (partial sum
,→ {:.6f}), "
"the series for a(n) also converges by the Direct
,→ Comparison Test.").format(sum_b)
else:
message = ("Since the series for b(n) diverges (partial sum
,→ grows beyond reasonable bounds), "
"the series for a(n) is concluded to diverge by
,→ the Direct Comparison Test.")
return message
def limit_comparison_test(a_func, b_func, N0, sample_n=10000):
"""
Applies the Limit Comparison Test to two positive series a(n)
,→ and b(n).
The test computes the limit L defined by:
L = lim (n -> ) (a(n) / b(n)).
If 0 < L < , then both series are concluded to have the same
,→ convergence behavior.
Parameters:
a_func : function
A function returning the nth term a(n) of the first
,→ series.
b_func : function
A function returning the nth term b(n) of the second
,→ series.
N0 : int
The starting index for the series (not directly used in
,→ limit approximation, but kept for consistency).
sample_n : int, optional
A large value of n used to approximate the limit
,→ (default is 10000).
Returns:
str
A message with the conclusion based on the approximated
,→ limit ratio.
"""
# Approximate the limit ratio using a large value of n
269
ratio = a_func(sample_n) / b_func(sample_n)
if ratio > 0 and [Link](ratio):
message = ("The limit ratio L = a(n)/b(n) approximated at n
,→ = {} is {:.6f}, "
"indicating that both series have the same
,→ convergence behavior.").format(sample_n,
,→ ratio)
else:
message = ("The limit ratio L = a(n)/b(n) is computed as {}
,→ at n = {}. "
"Thus, the test is inconclusive regarding the
,→ convergence properties.").format(ratio,
,→ sample_n)
return message
# Example series definitions:
# Let a(n) = 1/(n^2 + 1) and b(n) = 1/n^2 for n >= 1.
def series_a(n):
return 1.0 / (n**2 + 1)
def series_b(n):
return 1.0 / (n**2)
if __name__ == "__main__":
N0 = 1 # Starting index for the series
print("Direct Comparison Test:")
result_direct = direct_comparison_test(series_a, series_b, N0)
print(result_direct)
print("\nLimit Comparison Test:")
result_limit = limit_comparison_test(series_a, series_b, N0)
print(result_limit)
270
Chapter 46
Alternating Series and
the Ratio Test
Alternating Series
An alternating series is characterized by the successive change of
sign of its terms. In its classical form, an alternating series is
expressed as
X∞
(−1)n−1 an ,
n=1
where {an }∞n=1 is a sequence of nonnegative real numbers. Equiv-
alently, the series may be written as
∞
X
(−1)n an ,
n=1
where the overall effect on convergence remains unaltered by a fixed
sign shift. This oscillatory behavior, induced by the alternating
factors, is frequently instrumental in establishing convergence in
cases where the corresponding series of absolute values,
∞
X
an ,
n=1
diverges.
The Alternating Series Test, commonly attributed to Leibniz,
provides a succinct criterion for convergence. Specifically, if the
271
sequence {an }∞
n=1 satisfies
an+1 ≤ an for all n ≥ N,
for some N ∈ N, and if
lim an = 0,
n→∞
then the alternating series converges. Notably, rigorous analysis
of such series reveals that the error incurred by approximating the
infinite sum by its N th partial sum, denoted by
N
X
SN = (−1)n−1 an ,
n=1
satisfies the inequality
|S − SN | ≤ aN +1 ,
where S represents the sum of the entire series. This remainder
estimate is of considerable importance in both theoretical investi-
gations and practical approximations.
Conditional convergence is a further nuance in the study of
alternating series. That is, while the series
∞
X
(−1)n−1 an
n=1
may converge, the series formed by taking the absolute values of
its terms,
∞
X
an ,
n=1
may diverge. This phenomenon, absent in series with nonnegative
terms, underscores the subtle interplay between term magnitudes
and sign alternation in governing the overall convergence behavior.
The Ratio Test
The Ratio Test is a powerful method for assessing the convergence
properties of a series, particularly those whose terms incorporate
272
factorials, exponential factors, or other rapidly varying functions.
Consider a series of the form
∞
X
cn .
n=1
Introducing the limit
cn+1
L = lim ,
n→∞ cn
the Ratio Test asserts the following conclusions:
• If L < 1, the series converges absolutely;
• If L > 1, the series diverges;
• If L = 1, the test is inconclusive.
The underlying intuition of the test is derived from comparisons
with a geometric series, whose convergence is determined entirely
by the magnitude of its common ratio. When the limit L is less
than one, each successive term is sufficiently smaller in magnitude
than its predecessor, compelling the partial sums to approach a
finite limit.
In the context of series with alternating terms, the application
of the Ratio Test invariably involves the absolute values of the
terms. This approach necessarily evaluates absolute convergence.
In many instances, an alternating series may converge conditionally
despite the divergence of its non-alternating, absolute counterpart.
In such cases, the Ratio Test, when applied to |cn |, yields a limit
of one and hence fails to furnish decisive information regarding
convergence.
The Ratio Test is particularly effective when the nth term cn
is given in a closed analytical form. Such forms often permit the
simplification of the ratio
cn+1
cn
into an expression that is amenable to standard limiting proce-
dures. A typical illustration is found in series involving factorial
expressions, where the natural recursive structure of factorials en-
sures that the ratio simplifies to a rational function of n. The
subsequent evaluation of the limit L leverages standard techniques
273
in real analysis, and the resultant conclusion regarding convergence
is both clear and robust.
In synthesis, the Ratio Test complements the Alternating Series
Test by providing a method to analyze a broader class of series,
thereby enriching the repertoire of techniques available in the study
of infinite series.
Python Code Snippet
import math
def alternating_series_test(term_function, tol=1e-8,
,→ max_iter=10000):
"""
Computes the sum of an alternating series using the alternating
,→ series test.
The alternating series is assumed to be of the form:
S = sum_{n=1}^{} (-1)^(n-1) * a(n)
where a(n) = term_function(n) gives a sequence of nonnegative
,→ real numbers.
The algorithm accumulates terms until the error bound, which is
given directly by a(n+1), is less than the specified tolerance
,→ tol.
Parameters:
term_function: A function that takes an integer n and
,→ returns a_n.
tol: The tolerance level for the remainder (error) estimate.
max_iter: Maximum number of iterations to avoid infinite
,→ loops.
Returns:
S: The computed partial sum approximation of the series.
iterations: The number of terms used in the approximation.
error_est: The final error estimate based on a(n+1).
"""
S = 0.0
n = 1
while n <= max_iter:
term = term_function(n)
S += (-1)**(n - 1) * term # Add term with alternating sign
error_est = term_function(n + 1) # Remainder bound: |S -
,→ S_N| <= a(n+1)
if error_est < tol:
break
n += 1
return S, n, error_est
274
def ratio_test(sequence_function, start=5, end=20, step=1):
"""
Estimates the limit L = lim_{n -> } |c(n+1)/c(n)| for a series
,→ with terms c(n).
The Ratio Test states:
- If L < 1, the series converges absolutely.
- If L > 1, the series diverges.
- If L = 1, the test is inconclusive.
This function computes the ratios for a range of n values to
,→ show the behavior of the ratio.
Parameters:
sequence_function: A function that takes an integer n and
,→ returns the nth term c(n).
start: The starting index n for evaluating the ratio.
end: The ending index n for evaluation.
step: The increment step for n.
Returns:
ns: A list of n values used.
ratios: A list of corresponding ratio values |c(n+1)/c(n)|.
"""
ns = []
ratios = []
for n in range(start, end, step):
c_n = sequence_function(n)
c_next = sequence_function(n + 1)
# Avoid division by zero
if c_n == 0:
ratio = float('inf')
else:
ratio = abs(c_next / c_n)
[Link](n)
[Link](ratio)
return ns, ratios
# -------------------------------
# Example Usage:
# -------------------------------
# Example 1: Alternating Harmonic Series
# The alternating harmonic series is defined as:
# sum_{n=1}^{} (-1)^(n-1) / n
# It converges conditionally with a remainder estimate |S - S_N| <=
,→ 1/(N+1).
def a_n(n):
"""Term function for the alternating harmonic series."""
return 1.0 / n
275
S, iterations, error = alternating_series_test(a_n, tol=1e-8)
print("Alternating Harmonic Series Approximation:")
print("Partial Sum S =", S)
print("Number of Iterations =", iterations)
print("Error Estimate =", error)
# Example 2: Ratio Test on a Series with Factorials and Exponentials
# Consider the series with terms c(n) defined as:
# c(n) = n! / 10^n
# For this series, the ratio |c(n+1)/c(n)| simplifies to (n+1)/10.
# As n grows, if (n+1)/10 > 1, the series diverges.
def c_n(n):
"""Term function for the series c(n) = n! / 10^n."""
return [Link](n) / (10 ** n)
ns, ratios = ratio_test(c_n, start=5, end=20, step=1)
print("\nRatio Test for the series c(n) = n! / 10^n:")
for n_val, ratio in zip(ns, ratios):
print(f"n = {n_val}, Ratio = {ratio:.6f}")
276
Chapter 47
Root Test and Integral
Test for Series
Convergence
The Root Test
1 Definition and Fundamental Properties
Consider a series
∞
X
cn ,
n=1
with each term cn belonging to the real or complex numbers. The
root test examines the asymptotic behavior of the sequence of terms
by introducing the quantity
L = lim sup n |cn |.
p
n→∞
When this limit superior satisfies L < 1, the series converges ab-
solutely. Conversely, if L > 1, the divergence of the series follows.
In the marginal case where L = 1, the test does not furnish a
conclusive determination.
2 Theoretical Underpinnings
The underlying rationale for the root test lies in comparison with a
geometric progression. Suppose that there exists a constant r with
277
0 ≤ r < 1 such that for all sufficiently large n the inequality
p
n
|cn | ≤ r
holds. Then one immediately obtains
|cn | ≤ rn ,
for all large n, and the convergence of the geometric series
∞
X
rn
n=1
ensures the absolute convergence of the original series. The em-
ployment of the limit superior in p
the definition of L accommodates
sequences for which the limit of n |cn | may not exist, thereby pro-
viding a robust criterion applicable to a wide spectrum of series.
The root test becomes especially effective when the terms of the
series are expressed in forms involving factorials, exponentials, or
exponential-polynomial combinations that allow the nth root to
simplify the analysis of growth characteristics.
The Integral Test
1 Conditions for Validity
The integral test applies to series whose terms are generated by a
function f : [N, ∞) → R, where N is a positive integer, under the
conditions that f is continuous, nonnegative, and monotonically
decreasing on the interval [N, ∞). Given these hypotheses, one
associates the series
∞
X
an ,
n=N
with an = f (n), to the improper integral
Z ∞
f (x) dx.
N
The test asserts that the convergence of the series is equivalent to
the convergence of the integral. In concrete terms, if
Z ∞
f (x) dx
N
converges to a finite value, then so does the series; if the integral
diverges, the series is likewise divergent.
278
2 Analytical Framework and Error Estimation
To elucidate the relationship between sums and integrals, one may
compare the partial sums of the series with the area under the
curve defined by f (x). For each integer n ≥ N , the inequalities
Z ∞ ∞
X Z ∞
f (x) dx ≤ f (k) ≤ f (x) dx
n+1 k=n+1 n
hold, thereby placing the tail of the series between two integrals
that differ only by a finite shift in the lower limit of integration.
This double inequality not only establishes the convergence criteria
but also provides a quantitative estimate for the remainder term
when the series is approximated by its partial sum. Specifically, if
Rn denotes the error after summing the first n terms, then
Z ∞ Z ∞
f (x) dx ≤ Rn ≤ f (x) dx.
n+1 n
Such estimates are instrumental in assessing the error incurred in
truncating the series and form a rigorous basis for the application
of asymptotic analysis techniques. The integral test finds notable
efficacy when applied to functions for which the antiderivative is
known or can be readily approximated, as is the case with p-series
where
1
f (x) = p .
x
In such instances, the convergence criterion deduced from the in-
tegral test relies on the condition p > 1, demonstrating the precise
correspondence between the integrability of f and the summability
of the series.
Python Code Snippet
# Python implementations for the Root Test and the Integral Test for
,→ series convergence
import math
from math import fabs, pow
import numpy as np
from [Link] import quad
def compute_root_sequence(term_func, n_max):
"""
279
Compute the sequence of nth roots for the absolute value of the
,→ terms of a series.
Parameters:
term_func: A function that takes an integer n and returns
,→ the nth term of the series.
n_max: The maximum value of n (number of terms) to be
,→ considered.
Returns:
A list containing the computed values of |c_n|^(1/n) for n
,→ from 1 to n_max.
"""
roots = []
for n in range(1, n_max + 1):
term = term_func(n)
# Avoid computing the root for a zero term; define
,→ 0^(1/n)=0.
if term == 0:
[Link](0)
else:
root_value = pow(abs(term), 1.0 / n)
[Link](root_value)
return roots
def estimate_limsup(root_sequence, window_size=50):
"""
Estimate the limit superior (limsup) of a sequence.
Parameters:
root_sequence: List of computed nth root values.
window_size: Number of final elements used to estimate the
,→ limsup.
Returns:
An estimate of the limsup of the sequence.
"""
if len(root_sequence) < window_size:
window = root_sequence
else:
window = root_sequence[-window_size:]
return max(window)
def root_test(term_func, n_max=1000, window_size=50, tol=1e-3):
"""
Execute the root test for series convergence.
The test examines the quantity L = limsup (|c_n|^(1/n)). If L <
,→ 1 the series converges
absolutely; if L > 1 it diverges; if L = 1 (within a tolerance)
,→ the test is inconclusive.
Parameters:
280
term_func: Function that returns the nth term of the series.
n_max: Total number of terms for which the computation is
,→ done.
window_size: Number of last terms used to approximate the
,→ limsup.
tol: Tolerance used to decide the inconclusive region near L
,→ = 1.
Prints:
The estimated limsup and the conclusion about convergence.
"""
roots = compute_root_sequence(term_func, n_max)
L = estimate_limsup(roots, window_size)
print("Estimated limsup (L):", L)
if L < 1 - tol:
print("The series converges absolutely by the root test.")
elif L > 1 + tol:
print("The series diverges by the root test.")
else:
print("The root test is inconclusive (L is approximately
,→ 1).")
def integral_test(f, N):
"""
Apply the integral test for series convergence.
The function f should be continuous, nonnegative, and
,→ monotonically decreasing on [N, infinity).
The test compares the convergence of the improper integral _N^()
,→ f(x) dx with that of the series
_{n=N}^ f(n). It also provides basic bounds for the error
,→ (remainder) in approximating the series
by its partial sums.
Parameters:
f: A function of a real variable representing the
,→ term-generating function.
N: The starting index (a positive integer) for the series
,→ and the integral.
Prints:
The value of the improper integral and error bounds for the
,→ remainder after summing a finite number
of terms.
"""
# Compute the integral from N to infinity
integral_value, integral_error = quad(f, N, float('inf'))
print("Value of the integral from", N, "to infinity:",
,→ integral_value)
# Decide convergence based on the numerical value of the
,→ integral.
281
# A very large value or one identified as infinity implies
,→ divergence.
if [Link](integral_value) or integral_value > 1e6:
print("The integral diverges, hence the series diverges by
,→ the integral test.")
else:
print("The integral converges, hence the series converges by
,→ the integral test.")
# Estimate the remainder (error bounds) using:
# _(n+1)^() f(x) dx R_n _n^() f(x) dx.
n_tail = N + 10 # Example index to illustrate the remainder
,→ estimation.
R_lower, _ = quad(f, n_tail + 1, float('inf'))
R_upper, _ = quad(f, n_tail, float('inf'))
print("Estimated error (remainder) bounds after summing terms up
,→ to n =", n_tail)
print("Lower bound of remainder:", R_lower)
print("Upper bound of remainder:", R_upper)
# Example implementations for demonstration purposes
if __name__ == "__main__":
# Example 1: Root Test on a geometric series with ratio 1/3
print("Example 1: Root Test for geometric series a_n = (1/3)^n")
def geo_series(n):
return (1/3) ** n
root_test(geo_series, n_max=1000, window_size=50)
print("\nExample 2: Root Test for series a_n = 1/n! (rapidly
,→ convergent series)")
def factorial_series(n):
return 1 / [Link](n)
root_test(factorial_series, n_max=100, window_size=20)
# Example 3: Integral Test for the p-series with p = 2
,→ (convergent series)
print("\nExample 3: Integral Test for p-series with p = 2, a_n =
,→ 1/n^2")
def f_p2(x):
return 1 / (x ** 2)
integral_test(f_p2, 1)
# Example 4: Integral Test for the p-series with p = 1
,→ (divergent harmonic series)
print("\nExample 4: Integral Test for p-series with p = 1, a_n =
,→ 1/n")
def f_p1(x):
return 1 / x
integral_test(f_p1, 1)
282
Chapter 48
Power Series
Representation of
Functions
Definition and Convergence Properties
1 Definition of a Power Series
A power series is an infinite series of the form
∞
X
an (x − c)n ,
n=0
where the coefficients an are elements of a given field, and c serves
as the center of the series. The convergence of the series depends
on the value of x relative to c, and the radius of convergence R is
determined by the Cauchy–Hadamard formula
1
= lim sup n |an |.
p
R n→∞
For all x satisfying |x − c| < R, the series converges absolutely and
defines an analytic function, whereas for |x − c| > R divergence
occurs. The behavior at points where |x − c| = R necessitates
further analysis on a case-by-case basis.
283
2 Convergence and Analyticity
Within the interval of absolute convergence, the power series con-
verges uniformly on any closed subinterval and exhibits the notable
property of termwise differentiability and integrability. As a conse-
quence, an analytic function represented by a power series admits
a unique expansion in a neighborhood of the center, with the coef-
ficients given by the relation
f (n) (c)
an = ,
n!
provided the function is infinitely differentiable at the point c. Uni-
form convergence on compact subsets ensures that standard oper-
ations such as differentiation and integration may be performed on
the series term by term, consolidating the link between the local
behavior of the function and its global analytic structure.
Techniques for Constructing Power Series
Representations
1 Taylor Series Expansion
For functions that are smooth in the vicinity of a point, Taylor
series expansion constitutes a primary method for formulating a
power series representation. If a function f is analytic at the point
c, then it can be expressed as
∞
X f (n) (c)
f (x) = (x − c)n ,
n=0
n!
with the interval of convergence determined by the nature of f
around c. This expansion encapsulates all information about the
function within its radius of convergence and provides an exact rep-
resentation in the limit of infinitely many terms. The method relies
on the availability of the derivatives of f at the center, and the re-
sulting series often permits subsequent manipulation and analysis.
2 Alternative Methods and Series Manipulation
In addition to direct computation via Taylor series, alternative
techniques exist for constructing power series representations. A
284
common approach involves starting with a known series, such as
the geometric series
∞
1 X
= xn , |x| < 1,
1 − x n=0
and then generating new series representations through algebraic
transformations, substitutions, and termwise differentiation or in-
tegration. These operations yield new series with modified coef-
ficients and shifted centers, yet the underlying convergence prop-
erties remain closely related to those of the original series. Such
manipulations not only simplify the derivation of series represen-
tations for a wide range of functions but also reinforce the intrinsic
connection between series operations and standard analytical pro-
cedures.
Advantages of Series Representations
1 Termwise Operations and Analytic Continua-
tion
The structure afforded by power series representations yields sig-
nificant advantages in the context of analytical operations. Within
the radius of convergence, differentiation and integration may be ef-
fected term by term, permitting a straightforward derivation of the
derivatives and antiderivatives of complex functions. This property
is central to the theory of analytic functions and provides a pow-
erful tool for the study of local behavior. The ability to perform
termwise operations also facilitates analytic continuation, as the se-
ries can be extended to larger domains by considering overlapping
regions of convergence, thereby offering a pathway to investigate
the global properties of functions defined initially by local data.
2 Approximation and Computational Efficacy
Power series representations afford an efficient mechanism for ap-
proximating functions to a high degree of precision. Truncating the
series after a finite number of terms yields polynomial approxima-
tions whose errors can be quantitatively bounded using remainder
estimates derived from Taylor’s theorem. This feature is particu-
larly valuable in numerical analysis, where the computation of func-
tion values or the evaluation of integrals can be accomplished with
285
controlled accuracy. Moreover, the algebraic simplicity of power
series enables the resolution of complicated functional equations
by reducing problems to operations on series coefficients. In this
manner, power series serve as a bridge between abstract analytical
theory and practical computational applications, providing insight
into the behavior of functions while also streamlining calculations
across a diverse array of contexts.
Python Code Snippet
# Import necessary modules
import sympy as sp
import numpy as np
import math
# Define the symbol for our variable
x = [Link]('x')
def taylor_series_coefficients(f, c, num_terms):
"""
Compute the Taylor series coefficients for a given function f
,→ about the center c.
The coefficient a_n is given by:
a_n = f^(n)(c) / n!
where f^(n)(c) is the nth derivative of f evaluated at c.
Parameters:
f : sympy expression representing the function f(x)
c : the center (constant) about which to expand
num_terms : number of terms to compute
Returns:
A list of coefficients [a_0, a_1, ..., a_{num_terms-1}]
"""
coeffs = []
for n in range(num_terms):
# Compute the nth derivative of f
f_n = [Link](f, x, n)
# Evaluate the derivative at x = c
f_n_at_c = f_n.subs(x, c)
# Compute the coefficient using the factorial
a_n = f_n_at_c / [Link](n)
[Link](sp.N(a_n)) # Convert to a numerical
,→ approximation if possible
return coeffs
def evaluate_series(coeffs, x_val, c):
"""
286
Evaluate the power series sum_{n=0}^{N-1} a_n*(x - c)^n at a
,→ given x value.
Parameters:
coeffs : list of coefficients a_n
x_val : the value at which to evaluate the series
c : center of the series
Returns:
Numerical value of the truncated series at x_val.
"""
sum_val = 0
for n, a_n in enumerate(coeffs):
sum_val += a_n * ((x_val - c)**n)
return sum_val
def approximate_radius_of_convergence(coeffs):
"""
Approximate the radius of convergence for a power series using
,→ the
Cauchy--Hadamard formula:
1/R = limsup_{n->infty} (|a_n|)^(1/n)
For a finite list of coefficients, we approximate limsup using
,→ the maximum
nth-root observed among the computed coefficients.
Parameters:
coeffs : list of coefficients a_n
Returns:
Approximate radius of convergence R.
"""
roots = []
for n, a_n in enumerate(coeffs):
if n == 0:
continue # Skip the zeroth term
a_val = abs(a_n)
if a_val == 0:
continue # Avoid division by zero if any coefficient is
,→ 0
[Link](a_val**(1.0/n))
if len(roots) == 0:
return [Link] # Convergence for all x if higher coefficients
,→ vanish
limsup = max(roots)
if limsup == 0:
return [Link]
else:
return 1.0 / limsup
# Example 1: Taylor Series for exp(x) about x = 0
f_exp = [Link](x)
center = 0
287
num_terms = 10 # Number of terms to include in the Taylor series
,→ approximation
coeffs_exp = taylor_series_coefficients(f_exp, center, num_terms)
print("Taylor series coefficients for exp(x) at x = 0:")
print(coeffs_exp)
# Evaluate the series approximation for exp(x) at x = 1
x_val = 1
approx_value = evaluate_series(coeffs_exp, x_val, center)
true_value = sp.N([Link](x))
print("\nApproximated exp(1) using Taylor series with {} terms:
,→ {}".format(num_terms, approx_value))
print("True exp(1):", true_value)
# Approximate the radius of convergence for the exp(x) series
R_exp = approximate_radius_of_convergence(coeffs_exp)
print("\nApproximate Radius of Convergence for exp(x) Taylor
,→ series:", R_exp)
# Example 2: Geometric Series for 1/(1-x)
# The geometric series has known coefficients: a_n = 1 for all n
,→ (for |x| < 1).
def geometric_series_sum(x_val, num_terms):
"""
Compute the sum of the geometric series:
1/(1-x) = sum_{n=0}^{num_terms-1} x^n, for |x| < 1.
Parameters:
x_val : the value at which the series is evaluated
num_terms : number of terms in the series
Returns:
Partial sum of the geometric series.
"""
s = sum([x_val**n for n in range(num_terms)])
return s
x_val_geom = 0.5
approx_geom = geometric_series_sum(x_val_geom, 10)
true_geom = 1/(1-x_val_geom)
print("\nGeometric series approximation for 1/(1 - x) at x = {} with
,→ 10 terms: {}".format(x_val_geom, approx_geom))
print("True 1/(1 - x):", true_geom)
# Demonstrating Termwise Differentiation:
# For the Taylor series of sin(x) expanded about 0, differentiate
,→ termwise to obtain cos(x).
f_sin = [Link](x)
coeffs_sin = taylor_series_coefficients(f_sin, 0, num_terms)
def differentiate_series(coeffs):
"""
288
Differentiate a power series term by term.
If f(x) = sum_{n=0}^{N-1} a_n * x^n, then its derivative is
,→ given by:
f'(x) = sum_{n=1}^{N-1} n * a_n * x^(n-1)
Parameters:
coeffs : list of coefficients a_n of f(x)
Returns:
List of coefficients for the derivative series.
"""
derived_coeffs = []
for n in range(1, len(coeffs)):
derived_coeffs.append(n * coeffs[n])
return derived_coeffs
coeffs_cos_from_series = differentiate_series(coeffs_sin)
# Evaluate the derived series (approximation of cos(x)) at x = 0.5
x_val_diff = 0.5
approx_cos = evaluate_series(coeffs_cos_from_series, x_val_diff, 0)
true_cos = sp.N([Link](x_val_diff))
print("\nApproximated cos(0.5) using termwise differentiation of
,→ sin(x) Taylor series:")
print("Approximated cos(0.5):", approx_cos)
print("True cos(0.5):", true_cos)
# Demonstrating Termwise Integration:
# Integrate the power series for 1/(1-x) term by term to approximate
,→ an antiderivative.
def integrate_series(coeffs):
"""
Integrate a power series term by term.
If f(x) = sum_{n=0}^{N-1} a_n*x^n, an antiderivative is given
,→ by:
F(x) = C + sum_{n=0}^{N-1} (a_n/(n+1)) * x^(n+1)
Here, we take the constant of integration C = 0.
Returns:
A new list of coefficients with the constant term as the first
,→ element.
"""
integrated_coeffs = [0] # C = 0
for n, a in enumerate(coeffs):
integrated_coeffs.append(a / (n+1))
return integrated_coeffs
# Using coefficients for the geometric series (all ones)
coeffs_geom = [1] * num_terms
integrated_geom_coeffs = integrate_series(coeffs_geom)
# This integrated series approximates -ln(1-x)
x_val_int = 0.3
approx_integral = evaluate_series(integrated_geom_coeffs, x_val_int,
,→ 0)
289
true_integral = -[Link](1 - x_val_int)
print("\nApproximated integral of 1/(1-x) (i.e., -ln(1-x)) at x = {}
,→ using 10 terms: {}".format(x_val_int, approx_integral))
print("True -ln(1-x):", sp.N(true_integral))
290
Chapter 49
Determining the
Interval of Convergence
for Power Series
Preliminaries and Fundamental Definitions
Consider a power series expressed in the form
∞
X
an (x − c)n ,
n=0
where the sequence {an }∞
n=0 consists of coefficients defined over a
field, and c represents the center of the expansion. The convergence
properties of this series are intimately connected with the concept
of the radius of convergence, denoted by R. This critical value is
determined by the formula
1
= lim sup n |an |,
p
R n→∞
which encapsulates the asymptotic behavior of the sequence of co-
efficients. For each x satisfying |x − c| < R, the series converges
absolutely; for |x − c| > R, divergence is guaranteed. The scenarios
at the boundary points where |x − c| = R require further, more
refined convergence tests in order to classify the behavior as either
conditional convergence or divergence.
291
Techniques for Calculating the Radius of
Convergence
A variety of analytic techniques are available for the determination
of the radius of convergence. Two prominent methods that are
employed in practice are the Root Test and the Ratio Test.
1 Application of the Root Test
The Root Test is naturally aligned with the definition of the radius
of convergence via the limit superior. Define
L = lim sup n |an |.
p
n→∞
Then the radius of convergence is given by
1
R= ,
L
with the conventions that if L = 0, then R = ∞, and if L = ∞, then
R = 0. This method is particularly effective when the coefficients
{an } display behavior that allows for an explicit computation of
their nth roots.
2 Utilization of the Ratio Test
In circumstances where the limit
an+1
lim
n→∞ an
exists, the Ratio Test provides an alternative pathway for determin-
ing the radius of convergence. In such cases, the radius is obtained
from
an
R = lim ,
n→∞ an+1
assuming that the limit exists and is finite. This approach is often
advantageous when the sequence of coefficients involves factorial or
exponential expressions, as these terms tend to simplify the com-
putation of the limit.
292
Determination of the Interval of Conver-
gence
Having determined the radius of convergence R, the next stage is
to establish the interval of convergence itself. The open interval
defined by
{x ∈ R : |x − c| < R}
serves as the domain where the power series converges absolutely.
However, the convergence properties at the endpoints, where |x −
c| = R, cannot be inferred directly from the radius of convergence.
Each endpoint must be examined independently using appropriate
convergence tests.
At these boundary points, the power series assumes the form
∞
X
an (x − c)n with |x − c| = R.
n=0
The nature of convergence in each case may be investigated via
tests such as the Alternating Series Test, comparison tests, or
Abel’s Test, depending on the specific structure of the series. Such
analyses determine whether the series converges conditionally at
an endpoint or diverges altogether. The endpoints may, therefore,
be included in the interval of convergence if conditional conver-
gence can be established, or they may be excluded if divergence is
detected.
The techniques described herein provide a comprehensive frame-
work for determining both the radius and the complete interval of
convergence for power series. The rigorous analysis of these con-
vergence properties lays the foundation for the subsequent study
of analytic functions represented by such series.
Python Code Snippet
import math
def compute_limsup(seq):
"""
Compute the limit superior (limsup) of a finite sequence.
For practical purposes with a finite list, we return the maximum
,→ value.
"""
if not seq:
293
return None
return max(seq)
def radius_via_root_test(coeffs):
"""
Compute the radius of convergence using the Root Test.
For a power series a_n (x - c)^n, the radius R satisfies:
1/R = limsup (|a_n|^(1/n)) as n -> infinity.
If the computed limsup L is 0, then R is interpreted as
,→ infinity.
"""
if len(coeffs) < 2:
return None
nth_roots = []
for n in range(1, len(coeffs)):
# Avoid issues with negative or zero coefficients by taking
,→ absolute value.
current = coeffs[n]
nth_root = abs(current)**(1/n)
nth_roots.append(nth_root)
# Approximate the limsup by taking the maximum value of the
,→ computed nth roots.
L = compute_limsup(nth_roots)
if abs(L) < 1e-12:
return float('inf')
return 1 / L
def radius_via_ratio_test(coeffs):
"""
Compute the radius of convergence using the Ratio Test.
If the limit L = lim |a_(n+1)/a_n| exists, then
R = 1 / L.
With a finite set of coefficients, we approximate L by averaging
the ratio of successive terms from the tail of the sequence.
"""
ratios = []
for n in range(len(coeffs) - 1):
if abs(coeffs[n]) > 1e-12:
ratio = abs(coeffs[n+1]) / abs(coeffs[n])
[Link](ratio)
if not ratios:
return None
# Use the average of the last few ratio values (tail) as an
,→ approximation of the limit.
tail_length = min(5, len(ratios))
L_approx = sum(ratios[-tail_length:]) / tail_length
if abs(L_approx) < 1e-12:
return float('inf')
return 1 / L_approx
def series_sum(coeffs, x, center=0, num_terms=50):
"""
Compute the partial sum of the power series:
294
S(x) = [n=0]^(num_terms-1) a_n * (x - center)^n
This function can be used to approximate the sum of the series
,→ at a given x.
"""
total = 0.0
for n in range(min(num_terms, len(coeffs))):
total += coeffs[n] * ((x - center)**n)
return total
def generate_exponential_series(num_terms):
"""
Generate coefficients for the power series representation of
,→ e^x.
For e^x, the coefficients are given by a_n = 1/n!.
"""
coeffs = []
for n in range(num_terms):
[Link](1 / [Link](n))
return coeffs
def generate_geometric_series(num_terms):
"""
Generate coefficients for a geometric series with a_n = 1.
The power series is (x - c)^n, which has a radius of
,→ convergence R = 1.
"""
return [1] * num_terms
def main():
num_terms = 50
# Example 1: Exponential Series (e^x)
exp_coeffs = generate_exponential_series(num_terms)
print("Exponential series (e^x) coefficients:")
print(exp_coeffs)
R_root_exp = radius_via_root_test(exp_coeffs)
R_ratio_exp = radius_via_ratio_test(exp_coeffs)
print("Radius of convergence via Root Test (e^x series):",
,→ R_root_exp)
print("Radius of convergence via Ratio Test (e^x series):",
,→ R_ratio_exp)
# Example 2: Geometric Series (a_n = 1)
geo_coeffs = generate_geometric_series(num_terms)
print("\nGeometric series coefficients (a_n = 1):")
print(geo_coeffs)
R_root_geo = radius_via_root_test(geo_coeffs)
R_ratio_geo = radius_via_ratio_test(geo_coeffs)
print("Radius of convergence via Root Test (geometric series):",
,→ R_root_geo)
print("Radius of convergence via Ratio Test (geometric
,→ series):", R_ratio_geo)
295
# Evaluate partial sums of the geometric series at specific
,→ x-values.
# For a geometric series with center c = 0, convergence occurs
,→ when |x| < 1.
center = 0
x_convergent = 0.5 # Within the radius of convergence.
x_divergent = 1.5 # Outside the radius of convergence.
sum_geo_convergent = series_sum(geo_coeffs, x_convergent,
,→ center=center, num_terms=num_terms)
print("\nSum of geometric series at x =", x_convergent, ":",
,→ sum_geo_convergent)
sum_geo_divergent = series_sum(geo_coeffs, x_divergent,
,→ center=center, num_terms=num_terms)
print("Partial sum of geometric series at x =", x_divergent,
"(series diverges):", sum_geo_divergent)
if __name__ == "__main__":
main()
296
Chapter 50
Taylor and Maclaurin
Series
Derivation of the Taylor Series
Consider a function f that is analytic on an interval containing a
point a ∈ R. The function is assumed to be infinitely differentiable
in a neighborhood of a. Taylor’s theorem asserts that for each
positive integer N , the function f (x) can be represented in the
vicinity of a as
N
X f (n) (a)
f (x) = (x − a)n + RN (x),
n=0
n!
where f (n) (a) denotes the nth derivative of f evaluated at a, and
RN (x) is the remainder term. In its Lagrange form, the remainder
is given by
f (N +1) (ξ)
RN (x) = (x − a)N +1
(N + 1)!
for some ξ between a and x. This representation elucidates the
manner in which the error associated with truncating the series
after N terms depends on the (N + 1)th derivative, the factorial
term, and the (N + 1)st power of the deviation (x − a). The deriva-
tion rests on an iterative application of the Mean Value Theorem
and underpins the convergence behavior of the polynomial approx-
imation to f .
297
Maclaurin Series: The Special Case at
Zero
When the center of expansion is chosen to be a = 0, the Taylor
series specializes to what is known as the Maclaurin series. In this
instance, the expansion takes the form
∞
X f (n) (0) n
f (x) = x .
n=0
n!
The Maclaurin series is especially useful when the function and
all its derivatives are readily expressible at the origin. Classical
examples include functions such as the exponential function, where
∞
X xn
ex = ,
n=0
n!
and trigonometric functions like sine and cosine, whose series ex-
pansions provide elegant representations that are valid for all x ∈
R. This formulation not only simplifies computations but also al-
lows for a clear depiction of how the function behaves in a vicinity
around 0, with each term in the series contributing progressively
finer corrections.
Error Analysis and the Remainder Term
A critical component of the Taylor series framework is the esti-
mation of the error incurred when the series is truncated. The
remainder term
f (N +1) (ξ)
RN (x) = (x − a)N +1 ,
(N + 1)!
encapsulates the discrepancy between the exact value of f (x) and
the approximation provided by the Taylor polynomial of degree N .
In many applications, particularly when f (N +1) (x) can be bounded
by a constant M on the interval of interest, an inequality of the
form
M N +1
|RN (x)| ≤ |x − a|
(N + 1)!
is established. Such bounds play a central role in rigorous error
analysis as they guarantee that the approximation converges to the
298
actual function value when the remainder tends to zero as N → ∞.
Moreover, understanding the behavior of the remainder term is
essential when estimating the number of terms necessary to achieve
a desired level of accuracy in practical computations.
Applications to Local Function Approxi-
mations
The Taylor and Maclaurin series serve as a powerful method for
local approximation of analytic functions by polynomials. The ex-
pression
∞
X f (n) (a)
f (x) = (x − a)n
n=0
n!
provides a polynomial that approximates the behavior of f (x) in a
neighborhood of a. In many contexts, particularly when the eval-
uation of f (x) directly is challenging, these series enable the re-
placement of a potentially complicated function with a polynomial
whose properties are well understood. The local approximation is
instrumental in the analysis of limits, the computation of integrals,
and the solution of differential equations. By truncating the series
to a finite number of terms, one obtains a Taylor polynomial whose
accuracy is quantified by the remainder term, thereby facilitating
error estimates in numerical applications. The capacity to repre-
sent a function locally by its derivatives encapsulates the essence
of analytic behavior, providing a bridge between differential prop-
erties and algebraic representations, and opening avenues for both
theoretical and applied investigations in mathematical analysis.
Python Code Snippet
# Comprehensive Python example for implementing Taylor and Maclaurin
,→ series,
# including derivation of the Taylor polynomial, error estimation
,→ using Lagrange's remainder,
# and visualization of local function approximations.
import math
import numpy as np
import [Link] as plt
import sympy as sp
299
# Define the symbol for symbolic computations
x = [Link]('x')
def taylor_series(f_expr, a, order):
"""
Compute the Taylor series expansion of a given function f_expr
,→ about the point 'a'
up to the specified 'order'. The function f_expr should be a
,→ sympy expression.
Parameters:
f_expr : sympy expression representing the function f(x)
a : center of the expansion (float)
order : the highest degree of polynomial (integer)
Returns:
series_expr : sympy expression for the Taylor polynomial
"""
series_expr = 0
for n in range(order + 1):
# Compute the nth derivative of f_expr
f_deriv = [Link](f_expr, x, n)
# Evaluate the nth derivative at x = a
f_deriv_at_a = f_deriv.subs(x, a)
# Construct the nth term: f^(n)(a)/n! * (x - a)^n
term = f_deriv_at_a / [Link](n) * (x - a)**n
series_expr += term
series_expr = [Link](series_expr)
return series_expr
def remainder_estimate(M, order, x_val, a):
"""
Estimate the error (remainder) in the Taylor polynomial
,→ approximation based on
the Lagrange form of the remainder.
The bound is given by:
|R_N(x)| <= M/(order+1)! * |x - a|^(order+1)
where M is an upper bound for |f^(order+1)()| on the interval
,→ between a and x.
Parameters:
M : Upper bound on the absolute value of the
,→ (order+1)th derivative
order : Degree of the Taylor polynomial (integer)
x_val : The point where the function is approximated
,→ (float)
a : The center of the expansion (float)
Returns:
error_bound : The estimated absolute error in the
,→ approximation (float)
"""
300
error_bound = M / [Link](order + 1) * abs(x_val -
,→ a)**(order + 1)
return error_bound
#==================================================
# Example 1: Taylor Series for the Exponential Function (e^x)
# Using Maclaurin series (a = 0) as a special case
#==================================================
# Define the function f(x) = e^x as a sympy expression
f_expr_exp = [Link](x)
a_exp = 0 # Center of expansion (Maclaurin series)
order_exp = 10 # Degree of the Taylor polynomial
# Compute the Taylor series expansion for exp(x)
taylor_exp_expr = taylor_series(f_expr_exp, a_exp, order_exp)
print("Taylor series expansion of exp(x) up to order
,→ {}:".format(order_exp))
sp.pretty_print(taylor_exp_expr)
# Convert sympy expressions to numerical functions for evaluation
f_exp_numeric = [Link](x, f_expr_exp, 'numpy')
taylor_exp_numeric = [Link](x, taylor_exp_expr, 'numpy')
# Define x-values for plotting the functions
x_vals = [Link](-2, 2, 400)
y_true_exp = f_exp_numeric(x_vals)
y_taylor_exp = taylor_exp_numeric(x_vals)
# Plot true exp(x) and its Taylor series approximation
[Link](figsize=(10, 6))
[Link](x_vals, y_true_exp, label='exp(x) True', color='blue')
[Link](x_vals, y_taylor_exp, label='Taylor Approximation',
,→ color='red', linestyle='--')
[Link]('Taylor Series Approximation of exp(x)')
[Link]('x')
[Link]('f(x)')
[Link]()
[Link](True)
[Link]()
# Perform error analysis at a specific point, for instance, x = 0.5.
# For f(x) = exp(x), all derivatives equal exp(x). For x in [0, 0.5]
,→ the maximum is exp(0.5).
x_point_exp = 0.5
M_exp = math.e**(x_point_exp) # Upper bound for the (order+1)-th
,→ derivative
error_bound_exp = remainder_estimate(M_exp, order_exp, x_point_exp,
,→ a_exp)
print("\nEstimated error bound (remainder) for exp(x) at x = {}:
,→ {}".format(x_point_exp, error_bound_exp))
#==================================================
301
# Example 2: Taylor Series for the Sine Function (sin(x))
# Using Maclaurin series (a = 0) as the expansion point
#==================================================
# Define the function f(x) = sin(x) as a sympy expression
f_expr_sin = [Link](x)
a_sin = 0 # Center of expansion
order_sin = 7 # Degree of the Taylor polynomial
# Compute the Taylor series expansion for sin(x)
taylor_sin_expr = taylor_series(f_expr_sin, a_sin, order_sin)
print("\nTaylor series expansion of sin(x) up to order
,→ {}:".format(order_sin))
sp.pretty_print(taylor_sin_expr)
# Convert sympy expressions to numerical functions for evaluation
f_sin_numeric = [Link](x, f_expr_sin, 'numpy')
taylor_sin_numeric = [Link](x, taylor_sin_expr, 'numpy')
# Define x-values for plotting sin(x) and its approximation
x_vals_sin = [Link](-[Link], [Link], 400)
y_true_sin = f_sin_numeric(x_vals_sin)
y_taylor_sin = taylor_sin_numeric(x_vals_sin)
# Plot true sin(x) and its Taylor series approximation
[Link](figsize=(10, 6))
[Link](x_vals_sin, y_true_sin, label='sin(x) True', color='green')
[Link](x_vals_sin, y_taylor_sin, label='Taylor Approximation',
,→ color='orange', linestyle='--')
[Link]('Taylor Series Approximation of sin(x)')
[Link]('x')
[Link]('f(x)')
[Link]()
[Link](True)
[Link]()
# Perform error analysis for sin(x) at x = 0.8.
# For sin(x), the absolute value of any derivative is bounded by 1.
x_point_sin = 0.8
M_sin = 1 # Upper bound for the (order+1)-th derivative of sin(x)
error_bound_sin = remainder_estimate(M_sin, order_sin, x_point_sin,
,→ a_sin)
print("\nEstimated error bound (remainder) for sin(x) at x = {}:
,→ {}".format(x_point_sin, error_bound_sin))
302
Chapter 51
Applications of Taylor
Series Approximations
Local Approximations via Taylor Series
Let f be an analytic function defined on an interval about a point
a ∈ R. Its behavior in the vicinity of a is completely characterized
by its Taylor series expansion
∞
X f (n) (a)
f (x) = (x − a)n ,
n=0
n!
which represents the function as an infinite sum of polynomial
(n)
terms. Each coefficient f n!(a) embodies the local rate of change
of f of order n, and the powers of (x − a) capture the infinitesi-
mal displacement from the chosen center. In practice, truncating
this infinite series after a finite number of terms yields a Taylor
polynomial
N
X f (n) (a)
PN (x) = (x − a)n ,
n=0
n!
which approximates f (x) in a neighborhood of a. The rapid con-
vergence of the series is often ensured by the factorial growth in the
denominator, which frequently overtakes any growth of the deriva-
tives f (n) (a). This local approximation provides a potent tool for
analyzing the behavior of non-linear functions in a manner that
reduces complex phenomena to the study of a polynomial form.
303
Error Estimation and Convergence Prop-
erties
The effectiveness of a Taylor polynomial approximation is inti-
mately connected with the estimation of the truncation error. When
PN (x) is used to approximate f (x), the discrepancy is quantified
by the remainder term RN (x), which in the Lagrange form is ex-
pressed as
f (N +1) (ξ)
RN (x) = (x − a)N +1 ,
(N + 1)!
for some ξ between a and x. This expression offers a precise mea-
sure of the error induced by neglecting the higher order terms. In
many applications, an upper bound is sought so that
M
|RN (x)| ≤ |x − a|N +1 ,
(N + 1)!
where M is an upper bound for the absolute value of the (N + 1)th
derivative on the interval of interest. The interplay between the
magnitude of (x − a) and the factorial in the denominator is cru-
cial in establishing conditions for convergence. When |x − a| is
sufficiently small or when f (N +1) remains modest in magnitude,
the remainder becomes negligibly small. Such rigorous error anal-
ysis is indispensable in determining the number of terms required
to achieve a prescribed accuracy in numerical and analytical com-
putations.
Applications in Practical Problem Solv-
ing
Applications of Taylor series approximations extend to a variety of
practical problems where complex functions are replaced by sim-
pler polynomial forms. In the analysis of nonlinear equations, for
instance, the original function may resist a straightforward solu-
tion, yet its Taylor polynomial can be manipulated more directly
to obtain approximate roots or to construct iterative schemes that
converge rapidly. The polynomial structure permits the use of al-
gebraic techniques in solving equations that might otherwise be
intractable.
Moreover, Taylor series approximations serve as a foundational
element in the evaluation of integrals and the solution of differential
304
equations where an analytic antiderivative is not available. By
substituting the series expansion of a function into an integral, one
obtains a series of integrals over monomials, each of which can be
computed explicitly. Similarly, in the study of dynamical systems,
the local behavior near equilibrium points is analyzed in terms of
the first few terms of the Taylor expansion, with the quadratic
and higher-order components revealing the stability properties and
curvature of the function.
In many physical and engineering contexts, models involve func-
tions whose exact forms are cumbersome. Approximations via Tay-
lor series not only simplify the functional expressions but also pro-
vide quantitative insights into the behavior of the system under
small perturbations. The derivation of linearized models from in-
herently nonlinear equations is based on truncating the Taylor se-
ries after the first or second order term, thereby yielding a linear
approximation that is amenable to classical solution techniques.
The profound capacity of Taylor series to encapsulate local behav-
ior makes them an essential instrument in both theoretical investi-
gations and practical computations within applied mathematics.
Python Code Snippet
# This Python script demonstrates the computation of a Taylor series
,→ approximation
# for an analytic function, the estimation of the truncation error
,→ using the
# Lagrange remainder, and a graphical comparison between the Taylor
,→ polynomial
# and the actual function.
#
# The Taylor series expansion of an analytic function f(x) about a
,→ point a is given by:
# f(x) = sum_{n=0}^{} (f(a)/n!)*(x - a)^n,
# while the Taylor polynomial of degree N is:
# P_N(x) = sum_{n=0}^{N} (f(a)/n!)*(x - a)^n.
# The remainder (error) in the Lagrange form is:
# R_N(x) = (f1()/(N+1)!)*(x - a)^(N+1)
# for some between a and x. An upper bound for the error can be
,→ given by:
# |R_N(x)| (M/(N+1)!)*|x - a|^(N+1),
# where M is an upper bound for |f1()| over the interval of
,→ interest.
#
# In this example, we use f(x) = exp(x) as a representative function
,→ since
305
# its derivatives remain the same (i.e., exp(x)) and are easy to
,→ bound.
import math
import numpy as np
import [Link] as plt
import sympy as sp
# Define the symbolic variable and function expression
x = [Link]('x')
f_expr = [Link](x) # Example function: exp(x)
def taylor_series_poly(expr, a, N):
"""
Compute the Taylor polynomial of a sympy expression 'expr'
about the point 'a' up to degree N.
Parameters:
expr : sympy expression representing f(x)
a : the center point around which to expand
N : degree of the Taylor polynomial
Returns:
A sympy expression representing the Taylor polynomial.
"""
poly = 0
for n in range(0, N+1):
# Compute the n-th derivative of the expression.
deriv_n = [Link](expr, x, n)
# Evaluate the derivative at x = a.
deriv_at_a = deriv_n.subs(x, a)
# Compute the n-th term: (f^(n)(a)/n!)*(x - a)^n.
poly += deriv_at_a / [Link](n) * (x - a)**n
return [Link](poly)
def sympy_to_lambda(expr):
"""
Convert a sympy expression to a Python function (lambda)
for numerical evaluation using numpy and math modules.
Parameters:
expr : sympy expression
Returns:
A lambda function that can be used for numerical computations.
"""
return [Link](x, expr, modules=['numpy', 'math'])
def lagrange_remainder(a, x_val, N, M):
"""
Estimate the upper bound of the Lagrange remainder for the
,→ Taylor polynomial
306
approximation of a function at a point x_val. The estimate is
,→ given by:
R_N(x) <= M/(N+1)! * |x - a|^(N+1)
Parameters:
a : expansion point
x_val : point at which to evaluate the remainder estimate
N : degree of the Taylor polynomial used for approximation
M : an upper bound of |f^(N+1)()| over the interval
,→ between a and x_val
Returns:
The estimated absolute error bound.
"""
return M / [Link](N+1) * abs(x_val - a)**(N+1)
# Set expansion parameters
a = 0 # Center of expansion
N = 10 # Degree of the Taylor polynomial
# Compute the Taylor polynomial for f_expr about x = a
taylor_poly_expr = taylor_series_poly(f_expr, a, N)
# Display the Taylor polynomial (symbolic form)
print("Taylor Polynomial of degree", N, "for exp(x) about x =", a)
print([Link](taylor_poly_expr))
# Convert both the Taylor polynomial and the original function to
,→ lambda functions
taylor_poly_func = sympy_to_lambda(taylor_poly_expr)
f_func = sympy_to_lambda(f_expr)
# Generate a set of x values for demonstration (from -1 to 1)
x_vals = [Link](-1, 1, 400)
f_vals = f_func(x_vals) # Actual exp(x) values
taylor_vals = taylor_poly_func(x_vals) # Taylor polynomial
,→ approximations
# Calculate the absolute error between exp(x) and its Taylor
,→ polynomial approximation
abs_error = [Link](f_vals - taylor_vals)
# Compute the error bound using the Lagrange remainder estimate.
# For f(x) = exp(x), all derivatives are exp(x); on [a, x] with a=0
,→ and x>=0,
# we can choose M = exp(max(a, x)).
error_bound = [Link]([lagrange_remainder(a, xv, N, [Link](max(a,
,→ xv))) for xv in x_vals])
# Plot the actual function, the Taylor polynomial, and the
,→ theoretical error bound.
[Link](figsize=(10, 6))
[Link](x_vals, f_vals, label='exp(x)', color='blue')
307
[Link](x_vals, taylor_vals, label=f'Taylor Polynomial (degree
,→ {N})',
color='red', linestyle='--')
plt.fill_between(x_vals, taylor_vals - error_bound, taylor_vals +
,→ error_bound,
color='gray', alpha=0.3, label='Error Bound')
[Link]('Taylor Series Approximation of exp(x) and Lagrange
,→ Remainder Estimate')
[Link]('x')
[Link]('f(x)')
[Link]()
[Link](True)
[Link]()
# Output the maximum absolute error observed over the interval
print("Maximum absolute error on the interval:", [Link](abs_error))
308
Chapter 52
Parametric Equations
and Calculus
Parametric Representations of Curves
1 Definition and Notation
Let I ⊂ R be an interval and let x : I → R and y : I → R
be continuous functions. A curve in the Euclidean plane may be
represented by the set
C = { (x(t), y(t)) : t ∈ I }.
This parametric description affords a versatile framework for the
representation of curves, extending beyond the confines of ordinary
functions of the form y = f (x). In particular, the representation
by means of a parameter t enables the modeling of curves that have
vertical tangents, self-intersections, or multiple branches, thereby
providing a more general and flexible approach to geometric and
analytic investigations.
2 Canonical Examples
A typical instance of a parametric curve is furnished by the circle
of radius r, which admits the parametrization
x(t) = r cos t, y(t) = r sin t, t ∈ [0, 2π].
309
Similarly, ellipses, cycloids, and other curves of significant interest
in both pure and applied mathematics are often most naturally ex-
pressed in parametric form. The freedom to select an appropriate
parameterization proves instrumental in revealing intrinsic prop-
erties of the curve that may remain obscured when attempting to
express the curve by a single functional relation between x and y.
Differentiation of Parametric Curves
1 Computation of the First Derivative
Consider a parametric curve given by the functions x(t) and y(t),
each possessing continuous derivatives on the interval I. The deriva-
tive of y with respect to x, denoted by dxdy
, is obtained by apply-
ing the chain rule via the intermediate variable t. Specifically, if
x′ (t) ̸= 0 for t ∈ I, then
dy dy/dt
= .
dx dx/dt
This expression encapsulates the instantaneous rate of change of
y relative to x and is valid wherever the derivative dx/dt remains
nonzero. The formulation offers an expedient route to studying
the local behavior of the curve, particularly when the coordinate
functions are not invertible in the classical sense.
2 Computation of the Second Derivative
The curvature and subtle geometric features of a parametric curve
d2 y
are further elucidated by the second derivative dx 2 . Differentiating
dy
dx with respect to t and subsequently dividing by dx/dt yields the
expression
d dy
d2 y
d dy dt dx
2
= = .
dx dx dx dx/dt
This formula is instrumental in the analysis of curvature and in-
flection points, providing a measure of the concavity or convexity
of the curve at a given point. The interplay between the first and
second derivatives thus lays the foundation for a detailed local and
global analysis of the behavior of parametric curves.
310
Integration Techniques in Parametric Cal-
culus
1 Arc Length Calculation
For a parametric curve defined by continuously differentiable func-
tions x(t) and y(t) on the interval [t1 , t2 ], the arc length L is deter-
mined by summing the infinitesimal Euclidean distances along the
curve. Formally, the length is given by
Z t2 q
2 2
L= (x′ (t)) + (y ′ (t)) dt.
t1
This formula is derived through an application of the Pythagorean
theorem to the differential displacement vector x′ (t) dt, y ′ (t) dt
and is valid whenever the square root expression remains well-
defined. The arc length integral thus provides a rigorous measure
of the distance traversed along the curve between the endpoints
corresponding to t1 and t2 .
2 Area Computations for Parametric Curves
In many instances, it is of interest to compute the area enclosed
by a parametric curve or the area between the curve and one of
the coordinate axes. When the vertical displacement is of primary
concern, the area A bounded by the curve and the x-axis may be
expressed as Z t2
A= y(t) x′ (t) dt,
t1
provided that the functions involved satisfy the necessary regular-
ity and orientation conditions. This formulation generalizes the
standard integration technique for areas under a graph, accommo-
dating the potentially more intricate relationships between x and
y that occur in parametric representations. Through appropriate
adjustments, analogous expressions may be derived for areas com-
puted with respect to the y-axis or for regions bounded by multiple
parametric curves.
In this manner, the integration methods tailored to paramet-
ric curves not only extend traditional calculus techniques but also
enable a comprehensive analysis of a wide array of geometric and
physical phenomena.
311
Python Code Snippet
import numpy as np
from [Link] import quad
import [Link] as plt
# Parametric functions: Example using a circle of radius r
def x(t, r=1):
"""x-coordinate function for a circle: x = r * cos(t)"""
return r * [Link](t)
def y(t, r=1):
"""y-coordinate function for a circle: y = r * sin(t)"""
return r * [Link](t)
# First derivatives with respect to t
def dx_dt(t, r=1):
"""Derivative of x(t) with respect to t: dx/dt = -r * sin(t)"""
return -r * [Link](t)
def dy_dt(t, r=1):
"""Derivative of y(t) with respect to t: dy/dt = r * cos(t)"""
return r * [Link](t)
# Compute the first derivative dy/dx using the chain rule
def dy_dx(t, r=1):
"""
Computes the first derivative of y with respect to x using:
dy/dx = (dy/dt) / (dx/dt)
"""
denominator = dx_dt(t, r)
# To avoid division by zero, use [Link] and return [Link] when
,→ denominator is zero.
return [Link]([Link](denominator) > 1e-8, dy_dt(t, r) /
,→ denominator, [Link])
# Compute the second derivative d^2y/dx^2 by differentiating dy/dx
,→ with respect to t
def d_dy_dx_dt(t, r=1, h=1e-5):
"""
Numerical approximation of the derivative d/dt (dy/dx) using the
,→ central difference method.
"""
return (dy_dx(t + h, r) - dy_dx(t - h, r)) / (2 * h)
def d2y_dx2(t, r=1):
"""
Computes the second derivative d^2y/dx^2 using:
d^2y/dx^2 = [d/dt(dy/dx)] / (dx/dt)
"""
denom = dx_dt(t, r)
deriv = d_dy_dx_dt(t, r)
312
# Avoid division by zero
return [Link]([Link](denom) > 1e-8, deriv / denom, [Link])
# Compute the arc length of a parametric curve between t1 and t2
def arc_length(t1, t2, r=1):
"""
Calculates the arc length L of the curve defined by x(t) and
,→ y(t) using:
L = _t1^t2 sqrt((dx/dt)^2 + (dy/dt)^2) dt
"""
integrand = lambda t: [Link](dx_dt(t, r)**2 + dy_dt(t, r)**2)
L, _ = quad(integrand, t1, t2)
return L
# Compute the area under the curve with respect to the x-axis
def area_x_axis(t1, t2, r=1):
"""
Calculates the area A bounded by the parametric curve and the
,→ x-axis:
A = _t1^t2 y(t) * (dx/dt) dt.
The sign of the area depends on the orientation of the curve.
"""
integrand = lambda t: y(t, r) * dx_dt(t, r)
A, _ = quad(integrand, t1, t2)
return A
# Main execution to demonstrate all computations
if __name__ == "__main__":
# Set the radius for the circle and define the interval for t
r = 1
t_start = 0
t_end = 2 * [Link]
t_vals = [Link](t_start, t_end, 1000)
# Evaluate the parametric functions
x_vals = x(t_vals, r)
y_vals = y(t_vals, r)
# Compute derivatives over the t interval (for potential
,→ analysis)
dy_dx_vals = dy_dx(t_vals, r)
d2y_dx2_vals = d2y_dx2(t_vals, r)
# Compute arc length and area under the curve (with respect to
,→ the x-axis)
L = arc_length(t_start, t_end, r)
A = area_x_axis(t_start, t_end, r)
print("Parametric Representation: Circle of radius", r)
print("Arc Length L =", L)
print("Area under the curve (w.r.t. the x-axis) A =", A)
# Plot the parametric curve
313
[Link](figsize=(8, 6))
[Link](x_vals, y_vals, label="Parametric Curve (Circle)")
[Link]("x")
[Link]("y")
[Link]("Parametric Representation of a Circle")
[Link]()
[Link]("equal")
[Link](True)
[Link]()
314
Chapter 53
Polar Coordinates and
Graphing
The Polar Coordinate System
A point in the Euclidean plane may be characterized by its distance
from the origin and the angle measured from a fixed reference di-
rection. In the polar coordinate system, a point is represented by
the ordered pair (r, θ), where r ≥ 0 denotes the radial distance
from the origin and θ represents the angular displacement, typi-
cally measured in radians from the positive x-axis. The conversion
between polar and Cartesian coordinates is governed by the rela-
tions
x = r cos θ and y = r sin θ.
Due to the periodic nature of the angular coordinate, the represen-
tation (r, θ) is equivalent to (r, θ+2πk) for any integer k. Moreover,
when negative radial values are permitted, the equivalence
(−r, θ) = (r, θ + π)
emerges, thereby introducing an inherent symmetry that is absent
in the Cartesian description.
315
Plotting Techniques for Polar Curves
Curves in the polar coordinate system are commonly described by
equations of the form
r = f (θ),
where f is a real-valued function defined on a specified interval
of θ. The process of graphing such curves involves evaluating the
function f (θ) at a dense set of points within the interval and subse-
quently transforming these polar coordinates into their Cartesian
counterparts via the relations x = r cos θ and y = r sin θ. This
transformation facilitates the visualization of the curve, revealing
properties such as symmetry, periodicity, and the existence of self-
intersections.
Attention to the behavior of f (θ), including its zeros, extrema,
and points at which r assumes negative values, is essential for an
accurate rendering. Negative values of r imply that the correspond-
ing point is located in the direction opposite to that indicated by θ,
a fact that may necessitate subdividing the interval of θ to capture
the complete geometry of the curve. This method of plotting is
particularly effective in the context of curves such as rose curves,
cardioids, and spirals, where the polar formulation offers a more
natural and revealing description than a Cartesian representation.
Comparison with Cartesian Representa-
tions
A notable distinction exists between the polar and Cartesian co-
ordinate systems in the manner of representing points and curves.
In Cartesian coordinates, each point is uniquely identified by an
ordered pair (x, y); in contrast, the polar coordinates (r, θ) admit
multiple representations for the same point because of the period-
icity of the angular coordinate. The transformation
x = r cos θ and y = r sin θ
provides a local isomorphism between the two systems, yet it also
highlights the redundancy inherent in polar representations.
Polar equations often reveal symmetries and periodic proper-
ties that might be obscured in their Cartesian forms. Equations
such as r = a cos(kθ) or r = a sin(kθ), for instance, directly exhibit
rotational symmetries and periodic repetitions that simplify the
316
analysis of their geometric properties. Conversely, when a Carte-
sian equation is reformulated in polar coordinates, certain features
such as the uniform scaling of radial distances and the presence of
angular periodicity become more transparent. This comparative
analysis underscores the advantages of utilizing polar coordinates
when investigating curves that naturally embody radial or angular
attributes, providing a complementary perspective to that offered
by Cartesian methods.
Python Code Snippet
import numpy as np
import [Link] as plt
# Function to convert polar coordinates (r, theta) to Cartesian
,→ coordinates (x, y)
def polar_to_cartesian(r, theta):
"""
Convert polar coordinates to Cartesian coordinates.
Parameters:
r (float or [Link]): The radial distance(s).
theta (float or [Link]): The angular coordinate(s) in
,→ radians.
Returns:
x, y (float or [Link]): The Cartesian coordinates.
Uses:
x = r * cos(theta)
y = r * sin(theta)
"""
x = r * [Link](theta)
y = r * [Link](theta)
return x, y
# Function to generate polar curve data for a given function r =
,→ f(theta)
def generate_polar_curve(f, theta_start, theta_end,
,→ num_points=1000):
"""
Generate theta, r, x, and y data to illustrate a polar curve
,→ defined by the function r = f(theta).
Parameters:
f (function): The function of theta returning r.
theta_start (float): The starting angle (in radians).
theta_end (float): The ending angle (in radians).
num_points (int): The number of points to generate.
317
Returns:
theta, r, x, y: Arrays containing the angle, radial
,→ distance,
and corresponding Cartesian x and y
,→ coordinates.
"""
theta = [Link](theta_start, theta_end, num_points)
r = f(theta)
x, y = polar_to_cartesian(r, theta)
return theta, r, x, y
# Example polar functions illustrating the key formulas
def rose_curve(theta, a=2, k=3):
"""
Rose Curve: r = a * cos(k * theta)
Parameters:
theta (float or [Link]): Angular coordinate(s) in radians.
a (float): Amplitude (controls size of the petals).
k (int): Determines number of petals; if k is odd, there
,→ will be k petals,
and if k is even, there are 2k petals.
Returns:
r (float or [Link]): Radial distance(s).
"""
return a * [Link](k * theta)
def cardioid(theta):
"""
Cardioid: r = 1 + cos(theta)
Represents a heart-shaped curve in the polar coordinate system.
Parameters:
theta (float or [Link]): Angular coordinate(s) in radians.
Returns:
r (float or [Link]): Radial distance(s).
"""
return 1 + [Link](theta)
def archimedean_spiral(theta, b=0.2):
"""
Archimedean Spiral: r = b * theta
Parameters:
theta (float or [Link]): Angular coordinate(s) in radians.
b (float): Constant that controls the distance between
,→ successive turns.
318
Returns:
r (float or [Link]): Radial distance(s).
"""
return b * theta
# Plotting function to visualize polar curves in both Cartesian and
,→ polar coordinate systems
def plot_polar_and_cartesian(f, theta_start, theta_end, title):
"""
Plots the polar curve defined by r = f(theta) in two subplots:
1. In the Cartesian coordinate system by converting (r,
,→ theta) to (x, y).
2. Directly in the polar coordinate system.
Parameters:
f (function): Function that computes r given theta.
theta_start (float): Start of the theta interval (radians).
theta_end (float): End of the theta interval (radians).
title (str): Title of the plot.
"""
# Generate curve data
theta, r, x, y = generate_polar_curve(f, theta_start, theta_end)
# Create a new figure with 2 subplots side by side
[Link](figsize=(12, 6))
# Cartesian Plot
[Link](1, 2, 1)
[Link](x, y, 'b-', linewidth=2)
[Link]("x")
[Link]("y")
[Link](title + " (Cartesian)")
[Link]('equal')
[Link](True)
# Polar Plot using the polar projection of matplotlib
ax = [Link](1, 2, 2, projection='polar')
[Link](theta, r, 'r-', linewidth=2)
ax.set_title(title + " (Polar)", va='bottom')
[Link](True)
# Adjust layout and display the plot
plt.tight_layout()
[Link]()
# Main execution: plotting several polar curves illustrating the key
,→ equations.
if __name__ == '__main__':
# Define theta range for typical curves (0 to 2*pi) and extended
,→ range for spirals if needed.
theta_start = 0
theta_end = 2 * [Link]
319
# Plot 1: Rose Curve r = 2 * cos(3 * theta)
plot_polar_and_cartesian(lambda theta: rose_curve(theta, a=2,
,→ k=3),
theta_start, theta_end,
"Rose Curve: r = 2*cos(3*theta)")
# Plot 2: Cardioid r = 1 + cos(theta)
plot_polar_and_cartesian(cardioid,
theta_start, theta_end,
"Cardioid: r = 1+cos(theta)")
# Plot 3: Archimedean Spiral r = 0.2 * theta; use an extended
,→ theta range (0 to 4*pi)
plot_polar_and_cartesian(lambda theta: archimedean_spiral(theta,
,→ b=0.2),
theta_start, 4 * [Link],
"Archimedean Spiral: r = 0.2*theta")
# Demonstration of equivalence in polar coordinates:
# The same point can be represented with different angles.
# For a given r and theta, (r, theta) is equivalent to (r, theta
,→ + 2*pi)
sample_theta = [Link] / 4 # 45 degrees
sample_r = 3
x1, y1 = polar_to_cartesian(sample_r, sample_theta)
x2, y2 = polar_to_cartesian(sample_r, sample_theta + 2 * [Link])
print("Demonstration of polar coordinate equivalence:")
print("For (r, theta) = (3, /4): Cartesian coordinates (x, y)
,→ =", (round(x1, 4), round(y1, 4)))
print("For (r, theta + 2) = (3, /4 + 2): Cartesian coordinates
,→ (x, y) =", (round(x2, 4), round(y2, 4)))
320
Chapter 54
Calculus in Polar
Coordinates:
Derivatives
Differentiation of Polar Functions
A curve expressed in polar form is given by the equation
r = f (θ),
where the function f is assumed to be differentiable over an interval
of θ. In order to study the behavior of such a curve, an effective
technique is to convert the polar representation into a parametric
form via the standard coordinate transformations
x = r cos θ and y = r sin θ.
Assuming that r = f (θ) is differentiable, the functions x(θ) and
y(θ) are differentiable as compositions of differentiable functions.
Differentiation with respect to θ yields
dx dr
= cos θ − r sin θ
dθ dθ
and
dy dr
= sin θ + r cos θ.
dθ dθ
321
The quotient of these derivatives provides the slope of the tangent
line in Cartesian coordinates:
dy
dy r′ sin θ + r cos θ
= dθ
= ,
dx dx
dθ
r′ cos θ − r sin θ
where r′ denotes dθ
dr
. This formula remains valid provided that the
denominator r cos θ − r sin θ is nonzero.
′
Calculation of the Cartesian Slope
The expression for the derivative
dy r′ sin θ + r cos θ
= ′
dx r cos θ − r sin θ
encapsulates the combined effects of both the radial and angular
variations of the curve. The numerator r′ sin θ + r cos θ and the
denominator r′ cos θ − r sin θ arise from an application of the chain
rule to the parametric definitions of x and y. In this context, the
parameter θ governs the motion along the curve, and the derivative
dx represents the instantaneous rate of change of the y-coordinate
dy
with respect to the x-coordinate.
It is noteworthy that the obtained slope may assume a finite,
zero, or even an infinite value. In the event that the denominator
vanishes while the numerator remains nonzero, the tangent line be-
comes vertical in the Cartesian plane. On the other hand, when the
numerator is zero and the denominator is nonzero, the tangent has
a horizontal orientation. The interplay between these two quan-
tities consequently reveals critical geometric features of the curve,
including the identification of points of inflection or potential sin-
gularities.
Interpretation of the Polar Derivative
The derivative calculated in the preceding sections carries signif-
icant geometric interpretation. The underlying formula provides
insight into how variations in the radial function r = f (θ) and in
the angular parameter θ contribute to the orientation of the tangent
line in the Cartesian plane. Specifically, the term r′ accounts for
the direct rate of change of the radial distance, while the trigono-
metric factors cos θ and sin θ mediate the projection of this change
onto the x and y axes.
322
In many cases, the polar representation elucidates inherent sym-
metries that remain less apparent when the curve is described solely
in Cartesian coordinates. The derivative dx
dy
thus serves not only as
a measure of the instantaneous slope but also as a tool for under-
standing the overall geometric behavior of the curve. The appear-
ance of mixed trigonometric terms in both the numerator and the
denominator underscores the fact that the evolution of the curve’s
shape is influenced simultaneously by the magnitude of the radius
and by its angular displacement.
Moreover, the formula for dx dy
reveals that the rate at which
the curve departs from a radial line does not depend solely on the
radial function r in isolation, but rather on the combination of
r and its derivative r′ . This observation is particularly relevant
when analyzing curves with oscillatory or rapidly changing radial
components, where the balance between these two contributions
determines the orientation and curvature of the tangent line at any
given point.
The detailed structure of the derivative expression permits a
comprehensive examination of both local and global properties of
polar curves. As such, the techniques for computing and interpret-
ing derivatives in polar coordinates form an essential component
in the broader study of curve behavior and differential calculus in
non-Cartesian settings.
Python Code Snippet
import numpy as np
import [Link] as plt
import sympy as sp
# Define the symbolic variable and the polar function.
theta = [Link]('theta', real=True)
# Example polar function: r = 1 + cos(theta) (cardioid)
r_expr = 1 + [Link](theta)
# Compute the derivative dr/dtheta.
r_prime_expr = [Link](r_expr, theta)
# Convert the polar function to Cartesian coordinates:
# x = r*cos(theta) and y = r*sin(theta)
x_expr = r_expr * [Link](theta)
y_expr = r_expr * [Link](theta)
# Compute the derivatives with respect to theta using the chain
,→ rule.
323
# dx/dtheta = dr/dtheta * cos(theta) - r * sin(theta)
dx_dtheta_expr = r_prime_expr * [Link](theta) - r_expr *
,→ [Link](theta)
# dy/dtheta = dr/dtheta * sin(theta) + r * cos(theta)
dy_dtheta_expr = r_prime_expr * [Link](theta) + r_expr *
,→ [Link](theta)
# Compute the slope of the tangent line in Cartesian coordinates:
# dy/dx = (dy/dtheta)/(dx/dtheta) (with the assumption that
,→ dx/dtheta != 0)
dy_dx_expr = [Link](dy_dtheta_expr / dx_dtheta_expr)
# Display the symbolic expression for dy/dx.
print("Symbolic expression for dy/dx:")
[Link](dy_dx_expr)
# Lambdify the expressions for numerical evaluation.
f_r = [Link](theta, r_expr, 'numpy')
f_r_prime = [Link](theta, r_prime_expr, 'numpy')
f_dx_dtheta = [Link](theta, dx_dtheta_expr, 'numpy')
f_dy_dtheta = [Link](theta, dy_dtheta_expr, 'numpy')
f_dy_dx = [Link](theta, dy_dx_expr, 'numpy')
# Generate numerical theta values over the interval [0, 2*pi].
theta_vals = [Link](0, 2 * [Link], 400)
r_vals = f_r(theta_vals)
x_vals = r_vals * [Link](theta_vals)
y_vals = r_vals * [Link](theta_vals)
# Plot the polar curve in Cartesian coordinates.
[Link](figsize=(8, 6))
[Link](x_vals, y_vals, label='Polar Curve: r = 1 + cos(theta)')
[Link]('x')
[Link]('y')
[Link]('Polar Curve and its Tangent Line')
[Link]('equal')
[Link](True)
# Choose a specific theta to compute and plot the tangent line.
theta0 = [Link] / 4 # You can change this value to test other
,→ points.
r0 = f_r(theta0)
x0 = r0 * [Link](theta0)
y0 = r0 * [Link](theta0)
# Compute the slope dy/dx at theta0.
slope = f_dy_dx(theta0)
print("\nTangent slope at theta =", theta0, "is", slope)
# Calculate the tangent line: y = slope*(x - x0) + y0.
x_tangent = [Link](x0 - 1, x0 + 1, 100)
y_tangent = slope * (x_tangent - x0) + y0
324
# Plot the tangent line along with the original curve.
[Link](x_tangent, y_tangent, 'r--', label='Tangent line at = /4')
[Link](x0, y0, 'ko', label='Point of tangency')
[Link]()
[Link]()
325
Chapter 55
Calculus in Polar
Coordinates: Area and
Arc Length
Area in Polar Coordinates
Let the polar curve be defined by the relation r = f (θ), where
f is assumed to be continuously differentiable on the interval θ ∈
[θ1 , θ2 ]. An infinitesimal change in the angular coordinate, denoted
by dθ, subtends a small circular sector whose area is approximated
by
1
dA = r2 dθ.
2
This expression is derived from the geometric observation that the
area of a sector of a circle with radius r and central angle dθ (in
radians) is given by one-half the product of the square of the radius
and the angle. Partitioning the interval [θ1 , θ2 ] into subintervals
and summing the corresponding area elements leads, in the limit
as the partition is refined, to the integral representation of the total
area:
1 θ2 2
Z
A= r dθ.
2 θ1
This formula encapsulates the interaction between the radial dis-
tance and the angular displacement and provides a natural method
for computing areas of regions that are more conveniently described
in polar coordinates.
326
Arc Length in Polar Coordinates
For a curve expressed in polar form, the calculation of arc length re-
quires an integration of infinitesimal line elements along the curve.
Expressing the polar curve as r = f (θ), the conversion to Cartesian
coordinates proceeds via the relations
x = r cos θ and y = r sin θ.
The differential arc length element in Cartesian coordinates is given
by p
ds = dx2 + dy 2 .
By applying the chain rule, the differentials of x and y with respect
to θ are computed as
dx dr dy dr
= cos θ − r sin θ, = sin θ + r cos θ.
dθ dθ dθ dθ
Thus, the differential length ds can be written in terms of θ as
s 2 2
dr dr
ds = cos θ − r sin θ + sin θ + r cos θ dθ.
dθ dθ
A careful expansion of the squared terms and the subsequent appli-
cation of the Pythagorean trigonometric identity, cos2 θ+sin2 θ = 1,
lead to a considerable simplification:
s
2
dr
ds = + r2 dθ.
dθ
Integration of the differential element over the interval θ ∈ [θ1 , θ2 ]
yields the total arc length L of the curve:
s
Z θ2 2
dr
L= + r2 dθ.
θ1 dθ
q
dr 2
The integrand, + r2 , encapsulates both the rate of change
dθ
of the radial function and the inherent contribution of the radius it-
self, thereby reflecting the combined influence of radial and angular
variations in determining the length of the curve.
327
Python Code Snippet
# Import necessary libraries
import numpy as np
import [Link] as plt
from [Link] import simps # Simpson's rule for numerical
,→ integration
# Define the polar function r = f(theta)
# For demonstration purposes, we use r(theta) = 1 + 0.5*cos(theta)
# This example function generates a limaçon curve.
def f(theta):
return 1 + 0.5 * [Link](theta)
# Define the numerical derivative of f with respect to theta.
# This function computes dr/dtheta using a central difference method
,→ via [Link].
def compute_derivative(theta, r_values):
# [Link] computes the derivative taking into account the
,→ spacing in theta.
return [Link](r_values, theta)
# Set the angular interval [theta1, theta2]
theta1 = 0
theta2 = 2 * [Link]
# Create an array of theta values
N = 1000 # number of sample points for integration
theta = [Link](theta1, theta2, N)
# Compute the corresponding r values for each theta
r = f(theta)
# -------------------------------
# Calculation of Area in Polar Coordinates
# -------------------------------
# The formula for the area of a region bounded by a polar curve is
,→ given by:
# dA = 1/2 * r^2 * dtheta,
# and the total area (A) is:
# A = 1/2 * integral from theta1 to theta2 of r^2 dtheta.
area = 0.5 * simps(r**2, theta)
# -------------------------------
# Calculation of Arc Length in Polar Coordinates
# -------------------------------
# The differential element of arc length for a polar curve is
,→ defined as:
# ds = sqrt((dr/dtheta)^2 + r^2) dtheta,
# and the total arc length (L) is obtained by integrating this
,→ element:
328
# L = integral from theta1 to theta2 of sqrt((dr/dtheta)^2 +
,→ r^2) dtheta.
# Compute the derivative dr/dtheta for the given r values.
dr_dtheta = compute_derivative(theta, r)
# Compute the integrand for the arc length formula
integrand = [Link](dr_dtheta**2 + r**2)
arc_length = simps(integrand, theta)
# Print the computed area and arc length
print("Computed Area in Polar Coordinates: ", area)
print("Computed Arc Length in Polar Coordinates: ", arc_length)
# -------------------------------
# Plotting the Polar Curve
# -------------------------------
# We use matplotlib to plot the polar curve for visualization.
fig, ax = [Link](subplot_kw={'projection': 'polar'})
[Link](theta, r, label='r = 1 + 0.5*cos(theta)', color='b')
ax.set_title("Polar Curve: r = 1 + 0.5*cos(theta)")
[Link](loc='upper right')
[Link]()
329
Chapter 56
Vectors in the Plane:
Introduction and
Operations
Definition and Notation
Vectors in the plane are mathematical entities that encapsulate
both magnitude and direction. In the context of two-dimensional
Euclidean space, denoted by R2 , a vector is represented as an or-
dered pair of real numbers. A typical vector ⃗v is expressed in
Cartesian form as
⃗v = (v1 , v2 ),
where v1 and v2 are the components corresponding to the horizontal
and vertical axes, respectively. The canonical basis for R2 is given
by the unit vectors
i = (1, 0) and j = (0, 1),
so that any vector ⃗v admits a unique decomposition
⃗v = v1 i + v2 j.
This ordered pair notation precisely captures both the extent and
the orientation of displacement in the plane.
330
Operations on Vectors
The structure of vectors permits a variety of algebraic operations
that conform to the properties of a real vector space. The addi-
tion of two vectors, say ⃗u = (u1 , u2 ) and ⃗v = (v1 , v2 ), is defined
component-wise by the rule
⃗u + ⃗v = (u1 + v1 , u2 + v2 ).
This operation is both commutative and associative, ensuring that
the collection of vectors under addition forms an abelian group.
Scalar multiplication is equally fundamental. For any scalar
λ ∈ R and any vector ⃗v = (v1 , v2 ), the product is given by
λ⃗v = (λv1 , λv2 ).
The rules of scalar multiplication satisfy the distributive and asso-
ciative properties:
λ(⃗u + ⃗v ) = λ⃗u + λ⃗v and (λ + µ)⃗v = λ⃗v + µ⃗v ,
for all λ, µ ∈ R, thereby reinforcing the vector space structure.
Another operation of significant importance is the dot product.
For vectors ⃗u = (u1 , u2 ) and ⃗v = (v1 , v2 ), the dot product is defined
as
⃗u · ⃗v = u1 v1 + u2 v2 .
This operation yields a scalar and is instrumental in quantifying
the angle θ between ⃗u and ⃗v via the relation
⃗u · ⃗v = ∥⃗u∥ ∥⃗v ∥ cos θ,
where ∥⃗v ∥ denotes the magnitude of ⃗v .
Magnitude and Direction
The magnitude (or norm) of a vector ⃗v = (v1 , v2 ) is a measure of
its length in the plane and is calculated by
q
∥⃗v ∥ = v12 + v22 .
This expression is derived from the Euclidean distance formula and
quantifies the displacement from the origin to the terminal point
of the vector.
331
The direction of a vector is characterized by the angle that the
vector makes with the positive x-axis. For a given vector ⃗v =
(v1 , v2 ), the angle θ is determined through the relation
v2
θ = arctan ,
v1
with appropriate adjustments to account for the quadrant in which
the vector lies. Expressing a vector in polar form emphasizes its
magnitude and direction simultaneously:
⃗v = ∥⃗v ∥(cos θ, sin θ).
This formulation highlights the intrinsic geometric nature of vec-
tors, facilitating a clear interpretation of their role in representing
both the extent of displacement and its orientation within the two-
dimensional plane.
Python Code Snippet
import math
class Vector:
def __init__(self, x, y):
"""Initialize a vector in 2D space."""
self.x = x
self.y = y
def __add__(self, other):
"""Add two vectors component-wise."""
return Vector(self.x + other.x, self.y + other.y)
def __sub__(self, other):
"""Subtract two vectors component-wise."""
return Vector(self.x - other.x, self.y - other.y)
def scalar_multiply(self, scalar):
"""Multiply the vector by a scalar."""
return Vector(scalar * self.x, scalar * self.y)
def dot(self, other):
"""Calculate the dot product of two vectors."""
return self.x * other.x + self.y * other.y
def magnitude(self):
"""Compute the magnitude (norm) of the vector."""
return [Link](self.x**2 + self.y**2)
332
def angle(self):
"""Determine the angle (in radians) between the vector and
,→ the positive x-axis."""
return math.atan2(self.y, self.x)
def to_polar(self):
"""Return the vector's polar representation as (magnitude,
,→ angle_in_radians)."""
return ([Link](), [Link]())
def __repr__(self):
return f"Vector({self.x}, {self.y})"
def rad_to_deg(rad):
"""Convert an angle from radians to degrees."""
return [Link](rad)
def main():
# Create two example vectors in R^2
v1 = Vector(3, 4) # Vector represented as (3, 4)
v2 = Vector(1, 2) # Vector represented as (1, 2)
# Vector addition: v1 + v2
sum_vector = v1 + v2
# Scalar multiplication: 2 * v1
scalar = 2
scaled_vector = v1.scalar_multiply(scalar)
# Dot product: v1 . v2
dot_product = [Link](v2)
# Magnitude (norm) of v1
mag_v1 = [Link]()
# Angle of v1 with respect to the positive x-axis (in radians
,→ and degrees)
angle_v1_rad = [Link]()
angle_v1_deg = rad_to_deg(angle_v1_rad)
# Polar representation of v1 (magnitude and angle in radians)
polar_v1 = v1.to_polar()
# Displaying the computed results
print("Vector v1:", v1)
print("Vector v2:", v2)
print("v1 + v2 =", sum_vector)
print("2 * v1 =", scaled_vector)
print("Dot product (v1 · v2) =", dot_product)
print("Magnitude of v1 =", mag_v1)
print("Angle of v1 (radians) =", angle_v1_rad)
print("Angle of v1 (degrees) =", angle_v1_deg)
333
print("Polar representation of v1 (magnitude, angle in radians)
,→ =", polar_v1)
if __name__ == "__main__":
main()
334
Chapter 57
Analytic Geometry in
the Plane
Coordinate Representations and Vectors
in R2
The Euclidean plane is identified with the set of all ordered pairs
(x, y) where x, y ∈ R. In this setting, every point is naturally
associated with a position vector, denoted by p = (x, y), which
encapsulates both the notion of displacement and direction rela-
tive to a fixed origin. The vectorial approach provides an algebraic
structure that facilitates operations such as addition, scalar mul-
tiplication, and computation of inner products. These operations,
defined respectively by
u + v = (u1 + v1 , u2 + v2 ) and λv = (λv1 , λv2 ),
for vectors u = (u1 , u2 ), v = (v1 , v2 ) and scalar λ ∈ R, underpin the
transition from geometric intuition to analytic formulation. The
dot product, given by
u · v = u1 v1 + u2 v2 ,
allows for the measurement of angles between vectors and plays
a central role in establishing orthogonality and projections that
further the study of geometric configurations in the plane.
335
Lines in the Plane
A line in R2 admits multiple equivalent representations, each of
which reveals distinct geometric properties. One common formu-
lation is the parametric representation expressed as
r(t) = r0 + t d, t ∈ R,
where r0 is a fixed point on the line and d is a nonzero direction
vector. This vector equation emphasizes the role of translation and
scalar multiplication in defining the locus of points constituting the
line. Another prevalent representation is the Cartesian form
Ax + By + C = 0,
which provides an algebraic criterion for point inclusion based on
the linear combination of the coordinates. The equivalence be-
tween these forms is elucidated by relating the direction vector d
to the coefficients A and B, since the condition of orthogonality to
the normal vector (A, B) implies that d satisfies Ad1 + Bd2 = 0.
These dual perspectives enable rigorous computations of distances,
intersections, and angles between lines through techniques such as
the projection formula and the application of the dot product.
Circles and Their Algebraic Characteri-
zations
Circles occupy a central place in analytic geometry due to their
inherent symmetry and uniform curvature. A circle is defined as
the set of all points in the plane that are equidistant from a fixed
center c = (h, k). The standard form of the equation of a circle is
(x − h)2 + (y − k)2 = r2 ,
where r represents the radius. In vector notation, this relation is
elegantly expressed as
∥p − c∥2 = r2 ,
with p = (x, y) and ∥ · ∥ denoting the Euclidean norm. Such a
formulation not only underscores the geometric significance of dis-
tance but also facilitates transformations including rotations and
336
translations, which preserve the circular form. Algebraic manipula-
tions of the circle’s equation yield insights into tangency conditions,
chord lengths, and intersection points with other geometric entities
such as lines and conic sections.
Conic Sections: Classification and Alge-
braic Analysis
Conic sections emerge naturally as the intersection of a plane with
a double-napped cone, and their analytic study is grounded in the
general quadratic equation
Ax2 + Bxy + Cy 2 + Dx + Ey + F = 0.
The classification into parabolas, ellipses, and hyperbolas is gov-
erned by the discriminant B 2 − 4AC, which dictates the geometric
nature of the conic.
1 Parabolas
Parabolas are defined as the locus of points that are equidistant
from a fixed point, the focus, and a fixed line, the directrix. When
the axis of symmetry is aligned with one of the coordinate axes, a
parabola is typically brought to the form
y 2 = 4ax or x2 = 4ay,
depending on its orientation. The derivation of these forms involves
equating the Euclidean distance from a point (x, y) to the focus f
and its perpendicular distance to the directrix. In vector terms,
this condition is expressed as
∥p − f ∥ = dist(p, ℓ),
where ℓ denotes the line corresponding to the directrix. Such an
approach not only yields the canonical equation but also provides
a framework for investigating properties such as the focal length,
axis of symmetry, and tangent lines at any point on the parabola.
2 Ellipses and Hyperbolas
Ellipses and hyperbolas are characterized by their dependence on
two fixed points known as foci. An ellipse is defined as the set of
337
points for which the sum of the distances to the two foci is constant.
In a coordinate system where the ellipse is centered at (h, k) and
aligned with the coordinate axes, its equation takes the form
(x − h)2 (y − k)2
+ = 1,
a2 b2
with a and b being the semi-major and semi-minor axes, respec-
tively. In contrast, a hyperbola is defined by the condition that the
absolute difference of the distances from any point on it to the foci
remains constant, yielding the standard form
(x − h)2 (y − k)2
− = 1.
a2 b2
The derivation of these equations benefits from a vectorial inter-
pretation; the distance functions involved are naturally represented
as norms of differences between position vectors. Furthermore, the
discriminant B 2 − 4AC from the general quadratic equation serves
as an invariant that distinguishes ellipses (when B 2 − 4AC < 0)
from hyperbolas (when B 2 − 4AC > 0). This algebraic crite-
rion, coupled with coordinate transformations, provides a rigorous
method for classifying conic sections and analyzing their intrinsic
geometric properties.
Python Code Snippet
import math
from dataclasses import dataclass
# Vector operations in R^2
@dataclass
class Vector2D:
x: float
y: float
def __add__(self, other):
return Vector2D(self.x + other.x, self.y + other.y)
def __sub__(self, other):
return Vector2D(self.x - other.x, self.y - other.y)
def __mul__(self, scalar: float):
return Vector2D(self.x * scalar, self.y * scalar)
def dot(self, other):
338
return self.x * other.x + self.y * other.y
def norm(self):
return [Link](self.x ** 2 + self.y ** 2)
def __str__(self):
return f"({self.x}, {self.y})"
# Line representation: both parametric and Cartesian forms
@dataclass
class Line:
# Cartesian form: Ax + By + C = 0
A: float
B: float
C: float
@classmethod
def from_point_direction(cls, point: Vector2D, direction:
,→ Vector2D):
# A direction vector d is given; the normal vector n
# can be chosen as (-d.y, d.x) to satisfy d n.
A = -direction.y
B = direction.x
C = -(A * point.x + B * point.y)
return cls(A, B, C)
def point_on_line(self, point: Vector2D, tol: float = 1e-6):
# Check if a point satisfies the line equation
return abs(self.A * point.x + self.B * point.y + self.C) <
,→ tol
def parametric_form(self):
# Convert Cartesian form to parametric form: r = r0 + t * d
# Find one point on the line.
if abs(self.B) > 1e-6:
x0 = 0
y0 = -self.C / self.B
else:
y0 = 0
x0 = -self.C / self.A
r0 = Vector2D(x0, y0)
# Direction vector is perpendicular to the normal (A, B);
,→ use d = (-B, A)
d = Vector2D(-self.B, self.A)
return r0, d
# Circle representation and operations
@dataclass
class Circle:
center: Vector2D
radius: float
def contains_point(self, point: Vector2D, tol: float = 1e-6):
339
# Check if the distance from the point to the center equals
,→ the radius
return abs((point - [Link]).norm() - [Link]) < tol
def equation(self, x: float, y: float):
# Returns the value of (x-h)^2+(y-k)^2 - r^2; zero indicates
,→ the point is on the circle
return (x - [Link].x) ** 2 + (y - [Link].y) ** 2 -
,→ [Link] ** 2
# Conic Sections: classification using the discriminant from the
,→ general quadratic form
def classify_conic(A: float, B: float, C: float, D: float, E: float,
,→ F: float) -> str:
# General quadratic: Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0
# Discriminant: B^2 - 4AC
discriminant = B ** 2 - 4 * A * C
if discriminant < 0:
# It is an ellipse, and if additionally A == C and B == 0,
,→ it's a circle.
if abs(A - C) < 1e-6 and abs(B) < 1e-6:
return "Circle"
return "Ellipse"
elif abs(discriminant) < 1e-6:
return "Parabola"
else:
return "Hyperbola"
# Main function demonstrating the implementation of formulas and
,→ algorithms
def main():
# --------------------------
# Vector Operations in R^2
# --------------------------
v1 = Vector2D(3, 4)
v2 = Vector2D(1, 2)
print("Vector v1:", v1)
print("Vector v2:", v2)
v_sum = v1 + v2
print("v1 + v2 =", v_sum)
print("Dot product v1 . v2 =", [Link](v2))
print("Norm of v1 =", [Link]())
# --------------------------
# Line Representations
# --------------------------
point = Vector2D(0, 0)
direction = Vector2D(2, 3)
line = Line.from_point_direction(point, direction)
print("\nLine in Cartesian form: {}x + {}y + {} =
,→ 0".format(line.A, line.B, line.C))
test_point = Vector2D(4, 6)
340
print("Is point {} on the line? {}".format(test_point,
,→ line.point_on_line(test_point)))
r0, d = line.parametric_form()
print("Parametric form: Point =", r0, "Direction =", d)
# --------------------------
# Circle Operations
# --------------------------
circle = Circle(center=Vector2D(1, 1), radius=5)
print("\nCircle: Center =", [Link], "Radius =",
,→ [Link])
test_point_circle = Vector2D(4, 5)
print("Is point {} on the circle? {}".format(test_point_circle,
,→ circle.contains_point(test_point_circle)))
# Evaluate circle equation at a sample point
x_val, y_val = 4, 5
print("Circle equation value at (4, 5):", [Link](x_val,
,→ y_val))
# --------------------------
# Conic Sections Classification
# --------------------------
# Example for an ellipse: 9x^2 + 4y^2 - 36 = 0
A, B, C, D, E, F = 9, 0, 4, 0, 0, -36
conic_type = classify_conic(A, B, C, D, E, F)
print("\nConic classification for 9x^2 + 4y^2 - 36 = 0:",
,→ conic_type)
if __name__ == '__main__':
main()
341
Chapter 58
Functions of Several
Variables: Introduction
Definition of Multivariable Functions
Consider a set U ⊂ Rn , where n ≥ 2, and a codomain V ⊂ Rm ,
with m ≥ 1. A function of several variables is a mapping
f : U −→ V,
which assigns to every point x = (x1 , x2 , . . . , xn ) in U a unique
element f (x) ∈ V . In many classical settings, the focus is placed
on functions with the form
f (x1 , x2 , . . . , xn ),
which extend the familiar notion of a single-variable function to
a situation where the input is a tuple of real numbers. Here, the
independent variables carry an intrinsic geometric interpretation,
since they pinpoint locations in the n-dimensional Euclidean space.
The function itself encapsulates a rule that associates to each point
a value, and this rule frequently embodies both algebraic and geo-
metric features.
In the special case where V = R, the function is said to be a
scalar field defined on U . It is often instructive to emphasize that
the definition of a function in this context not only relies on the
specification of a formula or an algorithm but also on a rigorous
assignment of output values to inputs, ensuring that the mapping is
342
well-defined. The notation f (x) may be employed interchangeably
with f (x1 , x2 , . . . , xn ), thereby highlighting the multidimensional
nature of the domain.
Domains of Multivariable Functions
The domain U of a multivariable function f : U −→ R is, in general,
a subset of Rn that may exhibit intricate geometric structures.
Unlike functions of a single variable where the domain is typically
an interval in R, in the multivariable setting the domain can be
any set defined by algebraic, analytic, or topological constraints.
For instance, the function
p
f (x, y) = 1 − x2 − y 2
must be restricted to the set
U = {(x, y) ∈ R2 : x2 + y 2 ≤ 1},
which represents the closed unit disk in the plane. The inher-
ent geometric nature of U plays a critical role in determining the
properties of the function, such as continuity, differentiability, and
integrability.
A precise description of the domain is imperative for the rig-
orous analysis of any function of several variables. Typically, U is
defined by one or more inequalities or equations that impose neces-
sary restrictions on the variables. More generally, the domain may
be presented as
U = {(x1 , x2 , . . . , xn ) ∈ Rn : φ(x1 , x2 , . . . , xn ) ≥ 0},
where φ is a suitable real-valued function. Special attention is given
to the boundary of U , since the behavior of f near these points
often reveals significant analytical and geometrical characteristics.
The interplay between the algebraic definition of the function and
the topological properties of its domain is a fundamental aspect of
multivariable calculus.
The study of domains in higher dimensions involves concepts
from topology and real analysis, including open and closed sets,
interior and boundary points, and connectedness. These notions
not only contribute to a rigorous understanding of the function
itself but also lay the foundation for subsequent investigations into
limits, continuity, and differentiability in the multivariable context.
343
Python Code Snippet
# Comprehensive Python Code Snippet for Multivariable Functions and
,→ Domains
import numpy as np
import [Link] as plt
from mpl_toolkits.mplot3d import Axes3D # for 3D plotting
import math
import sympy as sp
# -----------------------------------------------------------
# 1. Define the Domain Check and the Multivariable Function f(x, y)
# Example Function: f(x, y) = sqrt(1 - x^2 - y^2)
# Domain: U = { (x,y) in 2 : x^2 + y^2 1 }
# -----------------------------------------------------------
def is_in_domain(x, y):
"""
Check if the point (x, y) lies within the domain U: x^2 + y^2 <=
,→ 1.
Parameters:
x (float): x-coordinate.
y (float): y-coordinate.
Returns:
bool: True if (x, y) is within the closed unit disk, False
,→ otherwise.
"""
return (x**2 + y**2) <= 1
def f(x, y):
"""
Evaluate the function f(x, y) = sqrt(1 - x^2 - y^2) if (x,y) is
,→ in the domain U.
Parameters:
x (float): x-coordinate.
y (float): y-coordinate.
Returns:
float: Value of f(x, y) if the point is in the domain,
otherwise returns [Link] to indicate an undefined
,→ value.
"""
if is_in_domain(x, y):
return [Link](1 - x**2 - y**2)
else:
return [Link]
# -----------------------------------------------------------
344
# 2. Generate a Grid and Compute Function Values on the Domain U
# -----------------------------------------------------------
# Create a grid of points over a region slightly larger than the
,→ unit disk for visualization.
num_points = 100
x_vals = [Link](-1.2, 1.2, num_points)
y_vals = [Link](-1.2, 1.2, num_points)
X, Y = [Link](x_vals, y_vals)
# Compute the function values over the grid by iterating over rows.
Z = [Link]([
[f(x, y) for x, y in zip(row_x, row_y)]
for row_x, row_y in zip(X, Y)
])
# -----------------------------------------------------------
# 3. Plot the Surface of f(x, y) = sqrt(1 - x^2 - y^2)
# -----------------------------------------------------------
fig = [Link](figsize=(8, 6))
ax = fig.add_subplot(111, projection='3d')
surface = ax.plot_surface(X, Y, Z, cmap='viridis', edgecolor='none',
,→ alpha=0.9)
ax.set_title('Surface Plot of f(x,y) = sqrt(1 - x^2 - y^2)')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('f(x,y)')
[Link](surface, shrink=0.5, aspect=5)
[Link]()
# -----------------------------------------------------------
# 4. Symbolic Representation and Verification using sympy
# -----------------------------------------------------------
# Define symbolic variables and the function f(x,y)
x_sym, y_sym = [Link]('x y')
f_sym = [Link](1 - x_sym**2 - y_sym**2)
phi_sym = 1 - x_sym**2 - y_sym**2 # The expression defining the
,→ domain condition
print("Symbolic representation of f(x, y):", f_sym)
print("Domain condition (x, y) = 1 - x^2 - y^2 (must be >= 0)")
# -----------------------------------------------------------
# 5. Generic Evaluation of a Multivariable Function
# -----------------------------------------------------------
def evaluate_multivariable_function(func, point):
"""
Evaluate a multivariable function 'func' at a given point.
Parameters:
func (callable): A function accepting multiple arguments.
345
point (tuple): A tuple of coordinates (x1, x2, ..., xn).
Returns:
float: The computed value of func at the given point.
"""
return func(*point)
# Example: Define a function g(x, y, z) = x + y + z and evaluate it.
g = lambda x, y, z: x + y + z
point = (1, 2, 3)
print("Evaluation of g(1, 2, 3):",
,→ evaluate_multivariable_function(g, point))
346
Chapter 59
Partial Derivatives and
Their Computation
Definition and Notation
Let f be a real-valued function defined on an open subset of Rn ,
that is,
f : U ⊂ Rn → R.
The partial derivative of f with respect to its ith variable at a point
a = (a1 , a2 , . . . , an ) is defined by considering the one-dimensional
slice obtained by varying only the ith coordinate while keeping
the remaining coordinates fixed. Formally, if the limit exists, the
partial derivative with respect to xi is given by
∂f f (a1 , . . . , ai + h, . . . , an ) − f (a1 , . . . , ai , . . . , an )
(a) = lim .
∂xi h→0 h
Standard notations include fxi (a) and ∂i f (a). This definition en-
capsulates the notion of the rate of change of the function in the
coordinate direction of xi , with the function evaluated at points
where all other variables remain constant.
Computational Techniques
1 Direct Computation via the Limit Definition
The most fundamental approach to computing a partial deriva-
tive involves an application of the limit definition. For a function
347
f (x1 , x2 , . . . , xn ), the evaluation of
∂f f (a1 , . . . , ai + h, . . . , an ) − f (a1 , . . . , an )
(a) = lim
∂xi h→0 h
requires one to increment the ith coordinate and observe the incre-
ment in the function value. In many instances, algebraic manipu-
lation and limit properties simplify the computation and provide
an exact expression for the derivative.
2 Utilization of Differentiation Rules
In practical computations, direct use of the limit definition is of-
ten superseded by the application of familiar differentiation rules.
When all but one variable are held constant, differentiation rules
analogous to those for single-variable functions are applicable. For
instance, if
f (x1 , x2 ) = u(x1 , x2 ) v(x1 , x2 ),
then the product rule implies that
∂f ∂u ∂v
= v+u .
∂x1 ∂x1 ∂x1
Similarly, if f (x1 , x2 ) is expressed as a quotient of two functions,
the quotient rule may be employed. Furthermore, the chain rule
extends naturally to functions of several variables: if a function f
depends on an intermediate variable g, which in turn is a function
of x1 , x2 , . . . , xn , then
∂f df ∂g
= · .
∂xi dg ∂xi
These rules facilitate the computation of partial derivatives by re-
ducing them to operations on functions of one variable in the di-
rection under consideration.
Higher Order Partial Derivatives
1 Second and Mixed Partial Derivatives
Once the first partial derivatives have been computed, the exami-
nation of second order derivatives is instrumental in understanding
348
the local behavior of multivariable functions. The second partial
derivatives include pure derivatives such as
∂2f
,
∂x2i
and mixed derivatives such as
∂2f
.
∂xi ∂xj
The evaluation of these derivatives is accomplished by differen-
tiating the first order partial derivatives with respect to one of
the variables. The existence and continuity of these higher order
derivatives plays a pivotal role in the analysis of local extrema and
in the study of the function’s curvature.
2 Clairaut’s Theorem on Mixed Partial Deriva-
tives
Provided that the mixed partial derivatives are continuous in a
neighborhood of a given point, Clairaut’s theorem dictates that
the order of differentiation is immaterial. More precisely, if the
mixed partial derivatives
∂2f ∂2f
and
∂xi ∂xj ∂xj ∂xi
are continuous on an open set containing a point a, then one has
∂2f ∂2f
(a) = (a).
∂xi ∂xj ∂xj ∂xi
This symmetry is not only of theoretical interest but also simplifies
computational procedures in higher dimensions.
Geometric and Analytic Significance
Partial derivatives provide a framework for understanding the lo-
cal behavior of functions of several variables. Geometrically, the
partial derivative ∂x
∂f
i
(a) represents the slope of the tangent line to
the curve obtained by intersecting the graph of f with the plane
defined by holding xj = aj for all j ̸= i. The collection of all first
349
order partial derivatives at a point forms the basis for the gradient
vector,
∂f ∂f ∂f
∇f (a) = (a), (a), . . . , (a) ,
∂x1 ∂x2 ∂xn
which encapsulates the direction of steepest ascent. Analytically,
these derivatives serve as the coefficients in the linear approxima-
tion of the function via the first order Taylor expansion,
f (a + h) = f (a) + ∇f (a) · h + o(∥h∥),
where h ∈ Rn and o(∥h∥) represents terms that tend to zero faster
than ∥h∥. Such an approximation is fundamental in optimization
theory, stability analysis, and numerical methods.
The meticulous computation of partial derivatives is therefore
not only a tool for determining instantaneous rates of change along
specific axes but also serves as a gateway to more advanced topics
in multivariable analysis. Their central role in establishing local
linearity and in exploring the curvature of surfaces underscores
their significance in both theoretical investigations and practical
applications within mathematics.
Python Code Snippet
import sympy as sp
import numpy as np
# Define symbols for variables
x, y, u = [Link]('x y u')
# Define a multivariable function f(x, y)
# Example: f(x, y) = x^2 * sin(y) + exp(x*y)
f = x**2 * [Link](y) + [Link](x*y)
print("Function f(x, y):", f)
# Compute first order partial derivatives symbolically
f_x = [Link](f, x)
f_y = [Link](f, y)
print("\nSymbolic Partial Derivatives:")
print("f/x =", [Link](f_x))
print("f/y =", [Link](f_y))
# Compute the gradient of f
gradient_f = [[Link](f_x), [Link](f_y)]
print("\nGradient of f:")
print("f =", gradient_f)
350
# Compute second order partial derivatives (pure and mixed)
f_xx = [Link](f, x, 2)
f_xy = [Link](f, x, y)
f_yx = [Link](f, y, x)
f_yy = [Link](f, y, 2)
print("\nSecond Order Partial Derivatives:")
print("2f/x2 =", [Link](f_xx))
print("2f/xy =", [Link](f_xy))
print("2f/yx =", [Link](f_yx))
print("2f/y2 =", [Link](f_yy))
# Verify Clairaut's Theorem (mixed partial derivatives equality)
claireaut_check = [Link](f_xy - f_yx)
print("\nClairaut's Theorem Check (should be 0):", claireaut_check)
# Convert the symbolic function and derivatives to callable
,→ functions for numerical evaluation
f_np = [Link]((x, y), f, "numpy")
f_x_np = [Link]((x, y), f_x, "numpy")
f_y_np = [Link]((x, y), f_y, "numpy")
# Define a numerical approximation function for partial derivatives
,→ using the central difference method
def numerical_partial(f_func, point, var_index, h=1e-5):
"""
Numerically approximate the partial derivative of f_func at a
,→ given point using the central difference formula.
Parameters:
f_func : function
A function of several variables.
point : tuple
The evaluation point (e.g., (x, y)).
var_index : int
The index of the variable for differentiation (0 for the
,→ first variable, 1 for the second, etc.).
h : float, optional
A small increment for the finite difference (default is
,→ 1e-5).
Returns:
derivative : float
The numerical approximation of the partial derivative.
"""
point = list(point)
point_forward = [Link]()
point_backward = [Link]()
point_forward[var_index] += h
point_backward[var_index] -= h
derivative = (f_func(*point_forward) - f_func(*point_backward))
,→ / (2 * h)
351
return derivative
# Test the numerical approximation at a specific point, for instance
,→ (1.0, 0.5)
test_point = (1.0, 0.5)
num_f_x = numerical_partial(f_np, test_point, 0)
num_f_y = numerical_partial(f_np, test_point, 1)
print("\nNumerical Approximation of Partial Derivatives at (1.0,
,→ 0.5):")
print("Numerical f/x =", num_f_x)
print("Symbolic f/x =", f_x_np(1.0, 0.5))
print("Numerical f/y =", num_f_y)
print("Symbolic f/y =", f_y_np(1.0, 0.5))
# Demonstrate the Chain Rule with a composite function
# Let g(x, y) = x * y and h(u) = sin(u)
# Then the composite function k(x, y) = sin(x * y)
k = [Link](x * y)
k_x = [Link](k, x) # Partial derivative of k with respect to x
print("\nChain Rule Demonstration:")
print("For k(x, y) = sin(x * y), the partial derivative with respect
,→ to x is:")
print("k/x =", [Link](k_x))
# Expected derivative: cos(x * y) * y
# Linear approximation (first order Taylor expansion) using the
,→ gradient
def linear_approximation(f_val, grad, h_vec):
"""
Compute the linear approximation of a function at a nearby point
,→ using its gradient.
Parameters:
f_val : float
The value of the function at the base point.
grad : list or tuple of floats
The gradient vector of the function at the base point.
h_vec : list or tuple of floats
The change (perturbation) in the input variables.
Returns:
approx : float
The approximated value of the function at the new point.
"""
approx = f_val + sum(g * h for g, h in zip(grad, h_vec))
return approx
# Evaluate the linear approximation at a nearby point.
base_point = (1.0, 0.5)
f_base = f_np(*base_point)
grad_base = [f_x_np(*base_point), f_y_np(*base_point)]
perturbation = (0.01, -0.02) # Small changes in x and y
352
approx_value = linear_approximation(f_base, grad_base, perturbation)
actual_value = f_np(base_point[0] + perturbation[0], base_point[1] +
,→ perturbation[1])
print("\nLinear Approximation Using Gradient:")
print("Approximated f at (1.01, 0.48):", approx_value)
print("Actual f at (1.01, 0.48):", actual_value)
353
Chapter 60
Tangent Planes and
Linear Approximations
Tangent Planes to Surfaces
Let f : R2 → R be a function that is differentiable in an open
neighborhood of a point (x0 , y0 ). The graph of f , given by
{(x, y, z) ∈ R3 : z = f (x, y)},
can be locally approximated by a plane that best captures the be-
havior of the surface at (x0 , y0 , f (x0 , y0 )). This plane, known as the
tangent plane, is defined by the first order variation of f about the
point. Assuming the existence of the partial derivatives fx (x0 , y0 )
and fy (x0 , y0 ), the equation of the tangent plane is expressed as
z = f (x0 , y0 ) + fx (x0 , y0 )(x − x0 ) + fy (x0 , y0 )(y − y0 ).
This formulation arises from the linearization of f , in which the
increment f (x, y) − f (x0 , y0 ) is approximated by the linear form
f (x, y)−f (x0 , y0 ) = fx (x0 , y0 )(x−x0 )+fy (x0 , y0 )(y −y0 )+E(x, y),
where the error term E(x, y) satisfies
E(x, y)
lim = 0.
(x − x0 )2 + (y − y0 )2
p
(x,y)→(x0 ,y0 )
The negligible magnitude of this error relative to the distance from
(x, y) to (x0 , y0 ) validates the use of the tangent plane as the opti-
mal linear approximation to the surface at the given point.
354
1 Derivation of the Tangent Plane Equation
Consider the differentiability of f at (x0 , y0 ). By definition, there
exists a function E(x, y) such that
f (x, y) = f (x0 , y0 )+fx (x0 , y0 )(x−x0 )+fy (x0 , y0 )(y −y0 )+E(x, y)
with
E(x, y)
lim = 0.
(x − x0 )2 + (y − y0 )2
p
(x,y)→(x0 ,y0 )
The linear part,
L(x, y) = f (x0 , y0 ) + fx (x0 , y0 )(x − x0 ) + fy (x0 , y0 )(y − y0 ),
captures the instantaneous rate of change of f in the x and y di-
rections at (x0 , y0 ). Since the remainder E(x, y) diminishes faster
than the distance (x, y) departs from (x0 , y0 ), the graph of f is well
approximated by the plane
z = L(x, y)
in a sufficiently small neighborhood of (x0 , y0 , f (x0 , y0 )). This
derivation provides a rigorous foundation for interpreting the tan-
gent plane as the first order approximation of the surface defined
by f .
Linear Approximations of Multivariable
Functions
For a function f : Rn → R that is differentiable at a point a =
(a1 , a2 , . . . , an ), the behavior of f near a can be captured by its
linear approximation. The differential of f at a is a linear map
df (a) : Rn → R defined by
df (a)(h) = ∇f (a) · h,
where h = (h1 , h2 , . . . , hn ) is a small perturbation and the gradient
is given by
∂f ∂f ∂f
∇f (a) = (a), (a), . . . , (a) .
∂x1 ∂x2 ∂xn
Thus, the first order Taylor expansion about a takes the form
f (a + h) = f (a) + ∇f (a) · h + o(∥h∥),
with the term o(∥h∥) representing higher order contributions that
vanish faster than ∥h∥ as h approaches the zero vector.
355
1 The Differential and First Order Taylor Ex-
pansion
The mapping df (a) encapsulates the best linear approximation to
f at a. In analytic terms, the function f is approximated near a
by
L(x) = f (a) + ∇f (a) · (x − a),
so that
f (x) = L(x) + R(x),
where the remainder R(x) exhibits the property
R(x)
lim = 0.
x→a ∥x − a∥
This formulation not only provides an effective mechanism for lo-
cal approximation but also underpins many applications in both
theoretical and applied analysis.
2 Geometric Interpretation of Linear Approxi-
mations
Geometrically, the graph of f : Rn → R is a hypersurface in Rn+1 .
At any point (a, f (a)), the hyperplane defined by
z = f (a) + ∇f (a) · (x − a)
serves as the tangent hyperplane, providing the closest linear repre-
sentation of the hypersurface in the vicinity of a. The accuracy of
this local linear model is directly tied to the smoothness of f ; in re-
gions where f is continuously differentiable, the deviation between
f (x) and its linear approximation diminishes proportionately with
∥x − a∥.
3 Application of Linear Approximations in Anal-
ysis
The linear approximation plays a critical role in multivariable anal-
ysis, particularly in the study of local extrema and stability anal-
ysis. For instance, in optimization problems, the differential of f
is used to determine the necessary conditions for a critical point,
while in numerical methods, the approximation informs iterative
procedures for solving equations in high-dimensional spaces. The
356
intrinsic link between differentiability and the validity of the lin-
ear model reinforces the importance of verifying the smoothness
conditions prior to invoking these techniques.
By capturing the essence of the behavior of multivariable func-
tions near a point, tangent planes and linear approximations form
a foundational tool in the analysis and practical computation of
local properties in higher dimensions.
Python Code Snippet
# Import necessary libraries
import numpy as np
import sympy as sp
import [Link] as plt
from mpl_toolkits.mplot3d import Axes3D # for 3D plotting
# Define symbolic variables for a function of two variables
x, y = [Link]('x y')
# Define the function f: R^2 -> R.
# Here we choose an example function: f(x, y) = x^2 + y^2.
f_expr = x**2 + y**2
# Compute the partial derivatives with respect to x and y.
f_x_expr = [Link](f_expr, x)
f_y_expr = [Link](f_expr, y)
# Choose a base point (x0, y0) for the tangent plane and linear
,→ approximation.
x0, y0 = 1, 2
# Evaluate the function and its partial derivatives at the point
,→ (x0, y0).
f_val = f_expr.subs({x: x0, y: y0})
f_x_val = f_x_expr.subs({x: x0, y: y0})
f_y_val = f_y_expr.subs({x: x0, y: y0})
# Print the evaluated base values.
print("At the point (x0, y0) = ({}, {}):".format(x0, y0))
print(" f(x0, y0) =", f_val)
print(" f_x(x0, y0) =", f_x_val)
print(" f_y(x0, y0) =", f_y_val)
# Formulate the equation of the tangent plane.
# The tangent plane is given by:
# z = f(x0, y0) + f_x(x0, y0)*(x - x0) + f_y(x0, y0)*(y - y0)
tangent_plane_expr = f_val + f_x_val*(x - x0) + f_y_val*(y - y0)
tangent_plane_expr_simpl = [Link](tangent_plane_expr)
357
print("\nTangent Plane Equation at (x0, y0):")
sp.pretty_print(tangent_plane_expr_simpl)
# Create lambda functions for numerical evaluations from the
,→ symbolic expressions.
f_numeric = [Link]((x, y), f_expr, 'numpy')
tangent_plane_numeric = [Link]((x, y),
,→ tangent_plane_expr_simpl, 'numpy')
# Define a function to compute the linear approximation (first order
,→ Taylor expansion)
def linear_approximation(x_input, y_input):
"""
Computes the linear (first order Taylor) approximation of f at
,→ the point (x0, y0)
for any given (x_input, y_input) using the tangent plane
,→ formula.
"""
return f_val + f_x_val*(x_input - x0) + f_y_val*(y_input - y0)
# Demonstrate the linear approximation at a nearby test point.
x_test, y_test = 1.05, 2.03
approx_value = linear_approximation(x_test, y_test)
actual_value = f_numeric(x_test, y_test)
error = abs(actual_value - approx_value)
print("\nLinear Approximation at point ({}, {}):".format(x_test,
,→ y_test))
print(" Approximated value =", approx_value)
print(" Actual value =", actual_value)
print(" Absolute error =", error)
# Demonstrate the concept of the differential.
# For a small perturbation vector h = (dx, dy), the differential is
,→ given by:
# df = f_x(x0, y0)*dx + f_y(x0, y0)*dy
dx, dy = 0.001, -0.002
differential = float(f_x_val)*dx + float(f_y_val)*dy
actual_change = f_numeric(x0+dx, y0+dy) - f_numeric(x0, y0)
print("\nDifferential Approximation for a perturbation (dx, dy) =
,→ ({}, {}):".format(dx, dy))
print(" Differential (df) =", differential)
print(" Actual change =", actual_change)
# Visualization: Plot the original surface and the tangent plane.
fig = [Link](figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
# Create a grid around the point (x0, y0) for plotting.
x_range = [Link](x0 - 1, x0 + 1, 50)
y_range = [Link](y0 - 1, y0 + 1, 50)
X, Y = [Link](x_range, y_range)
358
Z = f_numeric(X, Y) # The actual surface
Z_tangent = tangent_plane_numeric(X, Y) # The tangent plane
# Plot the surface f(x, y).
ax.plot_surface(X, Y, Z, cmap='viridis', alpha=0.7,
,→ edgecolor='none')
# Plot the tangent plane.
ax.plot_surface(X, Y, Z_tangent, cmap='coolwarm', alpha=0.5,
,→ edgecolor='none')
# Highlight the point of tangency.
[Link](x0, y0, f_numeric(x0, y0), color='red', s=50,
,→ label='Point of Tangency')
# Labeling the plot.
ax.set_title('Surface and Tangent Plane at ({}, {})'.format(x0, y0))
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
[Link]()
[Link]()
359
Chapter 61
The Chain Rule in
Several Variables
Preliminaries
Let U ⊂ Rm and V ⊂ Rn be open subsets. Consider a mapping
g : U → V that is differentiable at a point t ∈ U , and let f : V → Rp
be differentiable at the point x = g(t). The composition F =
f ◦ g : U → Rp is defined by F (t) = f (g(t)). Differentiability of the
mappings g and f guarantees the existence of linear approximations
at the respective points, with the derivatives represented by the
appropriate Jacobian matrices. In this setting, the derivative of g
at t is given by the n×m Jacobian matrix Dg(t), and the derivative
of f at x is represented by the p × n Jacobian matrix Df (x).
General Formulation of the Chain Rule
For the composite function F = f ◦ g, the chain rule asserts that
the derivative DF (t) is obtained by the matrix product of the
derivatives of f and g. That is,
D(f ◦ g)(t) = Df (g(t)) · Dg(t).
In coordinate form, suppose that
f (x1 , x2 , . . . , xn ) = f1 (x1 , . . . , xn ), . . . , fp (x1 , . . . , xn )
360
and that
g(t1 , t2 , . . . , tm ) = g1 (t1 , . . . , tm ), . . . , gn (t1 , . . . , tm ) .
Then, for each j = 1, . . . , m, the derivative of the composed func-
tion is expressed as
n
∂(f ◦ g) X ∂f ∂gi
(t) = g(t) (t).
∂tj i=1
∂xi ∂tj
This formula succinctly captures the manner in which the rate of
change of each intermediate variable xi contributes to the overall
rate of change of the composite function along the parameter tj .
Proof of the Multivariable Chain Rule
Assume that g is differentiable at t and that f is differentiable at
x = g(t). The differentiability of g implies that for any increment
h ∈ Rm there exists a function ϵ1 : Rm → Rn satisfying
g(t + h) = g(t) + Dg(t) h + ϵ1 (h),
with
∥ϵ1 (h)∥
lim = 0.
h→0 ∥h∥
Similarly, the differentiability of f at x allows for the representation
f (x + k) = f (x) + Df (x) k + ϵ2 (k),
for any increment k ∈ Rn , where
∥ϵ2 (k)∥
lim = 0.
k→0 ∥k∥
By setting k = Dg(t) h + ϵ1 (h), one obtains
(f ◦ g)(t + h) = f g(t) + Dg(t) h + ϵ1 (h)
= f g(t) + Df g(t) Dg(t) h + ϵ1 (h) +
ϵ2 Dg(t) h + ϵ1 (h) .
Rearrangement yields
(f ◦ g)(t + h) − (f ◦ g)(t) =
361
Df (g(t)) · Dg(t) h + Df (g(t)) ϵ1 (h) + ϵ2 Dg(t) h + ϵ1 (h) .
The properties of the remainder functions ϵ1 and ϵ2 ensure that
the terms
Df (g(t)) ϵ1 (h) and ϵ2 Dg(t) h + ϵ1 (h)
are of order o(∥h∥). Consequently, the increment of the composite
function can be written as
(f ◦ g)(t + h) = (f ◦ g)(t) + Df (g(t)) · Dg(t) h + o(∥h∥),
thereby establishing that the derivative of f ◦ g at t is given by the
product Df (g(t)) · Dg(t).
Coordinate Formulation and Further Im-
plications
Consider a real-valued function z = f (x1 , x2 , . . . , xn ) where each
variable xi is itself a function of auxiliary parameters t1 , t2 , . . . , tm .
Writing
xi = xi (t1 , t2 , . . . , tm ) for i = 1, 2, . . . , n,
the composite function is expressed as
z = f x1 (t1 , . . . , tm ), x2 (t1 , . . . , tm ), . . . , xn (t1 , . . . , tm ) .
The chain rule in this context implies that for any index j =
1, . . . , m the partial derivative of z with respect to tj may be com-
puted as
n
∂z X ∂f ∂xi
= (x1 , . . . , xn ) .
∂tj i=1
∂xi ∂tj
This coordinate formulation clearly demonstrates the additive ef-
fect of the variations of each intermediate variable xi on the overall
variation of z. The chain rule thus provides a systematic framework
for differentiating composite functions across multiple variables by
harmoniously combining the sensitivity of the outer function with
the dependence structure of the inner functions.
The formulation and proof of the multivariable chain rule, as
presented above, are fundamental to the local analysis of composite
functions and have extensive significance in the study of variable
transformations, differential geometry, and applied mathematical
analysis.
362
Python Code Snippet
import sympy as sp
def main():
# Define symbols for the independent variables (t1, t2)
t1, t2 = [Link]('t1 t2')
# Define the mapping g: R^2 -> R^2.
# Let g1(t1, t2) = t1**2 + sin(t2) and g2(t1, t2) = exp(t1)*t2.
g1 = t1**2 + [Link](t2)
g2 = [Link](t1) * t2
g = [Link]([g1, g2])
# Define symbols for the intermediate variables (x1, x2) for the
,→ function f.
x1, x2 = [Link]('x1 x2')
# Define the outer function f: R^2 -> R^2.
# Here we choose f1(x1, x2) = x1 + sin(x2) and f2(x1, x2) = x1 *
,→ x2.
f1 = x1 + [Link](x2)
f2 = x1 * x2
f = [Link]([f1, f2])
# Compute the Jacobian matrix Dg of the function g with respect
,→ to (t1, t2).
Dg = [Link]([t1, t2])
# Compute the Jacobian matrix Df of the function f with respect
,→ to (x1, x2).
Df = [Link]([x1, x2])
# Substitute the expressions for x1 and x2 from g into Df to
,→ obtain Df(g(t)).
Df_g = [Link]({x1: g1, x2: g2})
# Apply the multivariable chain rule:
# The derivative (Jacobian) of the composite function F = f g
,→ is DF = Df(g(t)) * Dg(t)
DF = [Link](Df_g * Dg)
# Print results
print("Jacobian matrix Dg (derivative of g):")
[Link](Dg)
print("\nJacobian matrix Df (derivative of f):")
[Link](Df)
print("\nJacobian Df evaluated at g(t), i.e., Df(g(t)):")
[Link](Df_g)
print("\nComposite derivative DF = Df(g(t)) * Dg(t) (chain rule
,→ result):")
[Link](DF)
363
# Demonstrate the coordinate form of the chain rule:
# For a given component, say the first component of f, the
,→ partial derivative
# with respect to t_j is given by:
# (f g)/t_j = sum_{i=1}^{2} (f/x_i)(g(t)) * (g_i/t_j)
partial_f1_t1 = [Link]([Link]([Link]({x1: g1, x2: g2}),
,→ t1))
partial_f1_t2 = [Link]([Link]([Link]({x1: g1, x2: g2}),
,→ t2))
print("\nCoordinate form: Partial derivative of f(g(t)) with
,→ respect to t1:")
[Link](partial_f1_t1)
print("\nCoordinate form: Partial derivative of f(g(t)) with
,→ respect to t2:")
[Link](partial_f1_t2)
# Evaluate the composite derivative at a specific point, for
,→ example t1 = 1 and t2 = 0.
point = {t1: 1, t2: 0}
DF_numeric = [Link](point)
print("\nComposite derivative DF evaluated at t1 = 1, t2 = 0:")
[Link](DF_numeric)
if __name__ == "__main__":
main()
364
Chapter 62
Optimization of
Functions of Several
Variables
Critical Points and Necessary Conditions
Let f : Rn → R denote a function that is continuously differentiable
in an open set Ω ⊂ Rn . A point a ∈ Ω is called a critical point of
f if the gradient of f vanishes at a, that is,
∂f ∂f ∂f
∇f (a) = (a), (a), . . . , (a) = 0.
∂x1 ∂x2 ∂xn
In explicit terms, the necessary condition for a to be a local ex-
tremum is that
∂f
(a) = 0 for all i = 1, 2, . . . , n.
∂xi
This collection of equations forms a nonlinear system whose so-
lutions yield the set of candidate points for local minima, local
maxima, or saddle points. The vanishing of the first-order partial
derivatives ensures that the linear (first-order) approximation of
f about a is trivial and that any nontrivial variation in f in the
neighborhood of a is of higher order. In many instances, these
critical points serve as the starting point for further quantitative
analysis, as the first-order condition is necessary but not sufficient
for establishing optimality.
365
Second-Order Analysis and the Hessian
Matrix
To ascertain the nature of a critical point a at which ∇f (a) = 0, it
is customary to examine the second-order behavior of f . Assuming
that f is twice continuously differentiable in a neighborhood of a,
the Taylor expansion of f about a may be written as
1 T
f (a + h) = f (a) + ∇f (a) · h + h Hf (a)h + o ∥h∥2 ,
2
where h ∈ Rn is an arbitrary perturbation and Hf (a) denotes the
Hessian matrix at a, defined by
2
∂ f
Hf (a) = (a) .
∂xi ∂xj 1≤i,j≤n
Since the first-order term vanishes for a critical point, the quadratic
form
Q(h) = hT Hf (a)h
becomes the dominant term in the local expansion of f . The sign of
Q(h) for nonzero h determines the local behavior of f . Specifically:
• If Hf (a) is positive definite, meaning that Q(h) > 0 for all
nonzero h, the function f attains a local minimum at a.
• If Hf (a) is negative definite, so that Q(h) < 0 for all nonzero
h, the function f attains a local maximum at a.
• If Hf (a) is indefinite, implying that Q(h) assumes both pos-
itive and negative values as h varies through Rn , then a is a
saddle point.
The determination of definiteness is often carried out via tech-
niques such as the examination of the eigenvalues of Hf (a) or by us-
ing Sylvester’s criterion, which involves the inspection of the lead-
ing principal minors of the Hessian matrix. In cases where Hf (a)
is only positive semidefinite or negative semidefinite, the quadratic
approximation may prove inconclusive, and further analysis, pos-
sibly involving higher-order derivatives, is required to resolve the
nature of the critical point.
The elegant interplay between the vanishing gradient and the
curvature encoded in the Hessian matrix encapsulates the fun-
damental principles underlying the optimization of multivariable
366
functions. Through the meticulous computation of partial deriva-
tives and the rigorous investigation of second-order behavior, one
obtains a complete characterization of the local extrema and saddle
points, providing deep insight into the geometry of the function f
in its domain.
Python Code Snippet
import sympy as sp
def main():
# Define the symbols for variables (here, for a function of two
,→ variables)
x, y = [Link]('x y', real=True)
# Define the function f(x, y)
# This example function demonstrates a non-linear function with
,→ multiple critical points:
# f(x, y) = x^3 + y^3 - 3*x*y
f = x**3 + y**3 - 3*x*y
print("Function f(x, y):")
sp.pretty_print(f)
# Compute the gradient vector of f (first partial derivatives)
grad_f = [[Link](f, var) for var in (x, y)]
print("\nGradient of f:")
sp.pretty_print(grad_f)
# Solve for the critical points by setting the gradient equal to
,→ zero
crit_points = [Link](grad_f, (x, y), dict=True)
print("\nCritical Points (solutions of grad f = 0):")
for cp in crit_points:
sp.pretty_print(cp)
# Compute the Hessian matrix of f (matrix of second partial
,→ derivatives)
H = [Link](f, (x, y))
print("\nHessian Matrix of f:")
sp.pretty_print(H)
# Function to classify a critical point using the eigenvalues of
,→ its Hessian matrix
def classify_critical_point(H_at_cp):
# Compute eigenvalues of the Hessian matrix at the critical
,→ point
eigen_dict = H_at_cp.eigenvals()
eigenvalues = list(eigen_dict.keys())
print("Eigenvalues of the Hessian:")
367
sp.pretty_print(eigenvalues)
# Determine definiteness based on the signs of the
,→ eigenvalues
# Convert eigenvalues to a numerical float for robust
,→ comparison if needed.
eigenvalues_numeric = [sp.N(ev) for ev in eigenvalues]
if all(ev > 0 for ev in eigenvalues_numeric):
return "Local Minimum"
elif all(ev < 0 for ev in eigenvalues_numeric):
return "Local Maximum"
elif any(ev == 0 for ev in eigenvalues_numeric):
return "Inconclusive (further analysis needed)"
else:
return "Saddle Point"
# Analyze and classify each critical point
print("\nClassification of Critical Points:")
for cp in crit_points:
print("\nAt Critical Point:")
sp.pretty_print(cp)
# Substitute the critical point coordinates into the Hessian
,→ matrix
H_cp = [Link](cp)
print("Hessian at this point:")
sp.pretty_print(H_cp)
# Classify the critical point based on the Hessian
,→ eigenvalues
classification = classify_critical_point(H_cp)
print("Conclusion:", classification)
if __name__ == "__main__":
main()
368
Chapter 63
Lagrange Multipliers
for Constrained
Optimization
Formulation of the Constrained Problem
Consider the problem of optimizing a real-valued function
f : Rn → R,
subject to one or more equality constraints given by
gi (x) = 0, i = 1, 2, . . . , m,
where x = (x1 , x2 , . . . , xn ) and each gi : Rn → R is continuously
differentiable on an open domain that contains the feasible set
M = {x ∈ Rn | gi (x) = 0, i = 1, 2, . . . , m}.
The objective is to locate points in M at which the function f
attains either a local maximum or minimum. The set M defines a
manifold whose tangent space at any regular point is determined by
the gradients of the constraint functions. The method of Lagrange
multipliers provides necessary conditions that a point x0 ∈ M must
satisfy to be a candidate for an extremum.
369
Derivation of the Lagrange Multiplier Con-
ditions
Assume that f as well as the constraint functions g1 , g2 , . . . , gm are
continuously differentiable in a neighborhood of a point x0 ∈ M,
and suppose that x0 is an extremum of f restricted to M. Let
Tx0 M denote the tangent space of the manifold M at x0 . For an
admissible perturbation h ∈ Tx0 M, the first-order variation of f
along h must vanish, that is,
Df (x0 ) · h = 0,
for every h satisfying
Dgi (x0 ) · h = 0, i = 1, 2, . . . , m.
Since the tangent space Tx0 M is the orthogonal complement of
the space spanned by the gradients ∇g1 (x0 ), ∇g2 (x0 ), . . . , ∇gm (x0 )
(provided these gradients are linearly independent), it follows by an
elementary result in linear algebra that there exist scalars λ1 , λ2 , . . . , λm ,
known as Lagrange multipliers, such that
∇f (x0 ) = λ1 ∇g1 (x0 ) + λ2 ∇g2 (x0 ) + · · · + λm ∇gm (x0 ).
Thus, the necessary conditions for x0 to be a candidate for a lo-
cal extremum under the given constraints are encapsulated in the
system: m
X
∇f (x0 ) −
λi ∇gi (x0 ) = 0,
i=1
gi (x0 ) = 0, i = 1, 2, . . . , m.
This set of equations establishes an interplay between the geome-
try of the constraint manifolds and the behavior of the objective
function.
Regularity Conditions and Constraint Qual-
ifications
The validity of the Lagrange multiplier method is contingent upon
certain regularity assumptions concerning the constraints. In par-
ticular, it is required that the gradients
∇g1 (x0 ), ∇g2 (x0 ), . . . , ∇gm (x0 )
370
are linearly independent at the point x0 . This condition, often re-
ferred to as the constraint qualification, ensures that the manifold
M is smooth at x0 and that its tangent space is well-defined. In
the absence of this condition, the span of the gradients may not
have the appropriate dimensionality, and the implicit characteriza-
tion of the tangent space becomes problematic. Consequently, the
derivation of the Lagrange multiplier conditions may fail, or addi-
tional techniques must be invoked to handle degenerate cases. The
linear independence of the constraint gradients also facilitates the
uniqueness, up to scaling, of the multipliers in the neighborhood of
a regular point.
Interpretation of the Lagrange Multiplier
Equations
The equation
m
X
∇f (x0 ) = λi ∇gi (x0 )
i=1
admits a compelling geometric interpretation. It asserts that at
a point x0 of constrained extremum, the gradient ∇f (x0 ), which
indicates the direction of steepest ascent of f , is confined to the
subspace spanned by the normals to the constraint surfaces. In
effect, no infinitesimal displacement along the tangent space of the
constraint manifold can result in a first-order change in the value of
f . The multipliers λi serve to balance the contributions of the indi-
vidual constraints, and under further theoretical scrutiny, they may
be interpreted as measures of sensitivity of the extremal value of
f with respect to perturbations in the constraint equations. This
sensitivity analysis is of considerable interest in various applica-
tions, as it quantifies the trade-offs between the objective function
and the adherence to the constraints.
Solving the System of Lagrange Multi-
plier Equations
The practical resolution of a constrained optimization problem via
the Lagrange multiplier method entails the computation of both the
candidate point x and the corresponding multipliers λ1 , λ2 , . . . , λm
371
from the nonlinear system
m
X
∇f (x) − λi ∇gi (x) = 0,
i=1
gi (x) = 0, i = 1, 2, . . . , m.
The system is typically solved by methods of nonlinear analysis,
algebraic elimination, or numerical approximation, depending on
the structure of f and the constraint functions gi . In many situ-
ations, the system admits multiple solutions, each corresponding
to a candidate equilibrium point. Subsequent analyses, which may
involve second-order conditions such as the examination of the bor-
dered Hessian matrix, are then employed to classify the nature of
the constrained critical points. The transformation of the original
constrained problem into a system of equations via the Lagrange
multiplier framework provides a systematic and elegant approach
to reconcile the influence of the objective function and the restric-
tive conditions imposed by the constraints.
Python Code Snippet
# Python code demonstrating the Lagrange multiplier method for a
,→ constrained optimization problem.
#
# Example Problem:
# Minimize f(x, y) = x**2 + y**2
# Subject to the constraint: g(x, y) = x + y - 1 = 0
#
# The necessary conditions for a constrained extremum are:
# f(x, y) - g(x, y) = [0, 0]
# g(x, y) = 0
#
# This code uses both a symbolic approach (with sympy) and a
,→ numerical approach (with [Link])
# to solve the system of equations defined by the Lagrange
,→ multiplier method.
#
# Additionally, the code generates a contour plot of the objective
,→ function f(x, y) and visualizes the constraint.
import sympy as sp
import numpy as np
from [Link] import fsolve
import [Link] as plt
372
# ---------------------------
# Symbolic Computation using sympy
# Define the symbols for the decision variables and the Lagrange
,→ multiplier
x, y, lam = [Link]('x y lam', real=True)
# Define the objective function f(x, y) and the constraint g(x, y)
f = x**2 + y**2
g = x + y - 1
# Compute the gradients of f and g with respect to x and y
grad_f = [[Link](f, var) for var in (x, y)] # [2*x, 2*y]
grad_g = [[Link](g, var) for var in (x, y)] # [1, 1]
# Form the system of equations for the Lagrange multiplier method:
# 1) f/x - lam * g/x = 0 -> 2*x - lam = 0
# 2) f/y - lam * g/y = 0 -> 2*y - lam = 0
# 3) The constraint: x + y - 1 = 0
eq1 = [Link](grad_f[0] - lam * grad_g[0], 0)
eq2 = [Link](grad_f[1] - lam * grad_g[1], 0)
eq3 = [Link](g, 0)
# Solve the system of equations symbolically
symbolic_solution = [Link]((eq1, eq2, eq3), (x, y, lam),
,→ dict=True)
# Display the symbolic solution(s)
print("Symbolic Solution for the constrained optimization problem:")
for sol in symbolic_solution:
print(sol)
# ---------------------------
# Numerical Solution using [Link]
# Define the system of equations as functions to be solved
,→ numerically.
def equations(vars):
x_val, y_val, lam_val = vars
eq1_val = 2 * x_val - lam_val # Equation from derivative
,→ with respect to x
eq2_val = 2 * y_val - lam_val # Equation from derivative
,→ with respect to y
eq3_val = x_val + y_val - 1 # The constraint: x + y -
,→ 1 = 0
return [eq1_val, eq2_val, eq3_val]
# Provide an initial guess for [x, y, lam]
initial_guess = [0.0, 0.0, 0.0]
# Solve the system numerically using fsolve
numerical_solution = fsolve(equations, initial_guess)
373
# Display the numerical solution
print("\nNumerical Solution using fsolve:")
print("x =", numerical_solution[0], ", y =", numerical_solution[1],
,→ ", lambda =", numerical_solution[2])
# ---------------------------
# Visualization: Plotting the Objective Function and the Constraint
# Generate a grid of x and y values
x_vals = [Link](-1, 2, 400)
y_vals = [Link](-1, 2, 400)
X, Y = [Link](x_vals, y_vals)
# Compute the values of the objective function on the grid
Z = X**2 + Y**2
# Create the plot
[Link](figsize=(8, 6))
# Plot contour lines representing level sets of f(x,y)
contours = [Link](X, Y, Z, levels=20, cmap='viridis')
[Link](contours, inline=True, fontsize=8)
# Plot the constraint line: x + y - 1 = 0, i.e., y = 1 - x
[Link](x_vals, 1 - x_vals, 'r-', linewidth=2, label='Constraint: x
,→ + y = 1')
# Mark the optimal point obtained from the Lagrange multiplier
,→ method
[Link](numerical_solution[0], numerical_solution[1], 'ko',
,→ markersize=8, label='Optimal Point')
[Link]('x')
[Link]('y')
[Link]('Optimization of f(x,y) = x^2 + y^2 with Constraint x + y
,→ = 1')
[Link]()
[Link](True)
[Link]()
374
Chapter 64
Multiple Integrals:
Double Integrals and
Applications
Fundamental Concepts and Definitions
Let R ⊂ R2 denote a bounded region in the plane and let f : R → R
be a function defined on R. The double integral of f over R is
introduced as the limit of a double Riemann sum. More precisely, if
the region R is decomposed into a finite number of nonoverlapping
subregions {Rij } with areas ∆Aij , and if (x∗ij , yij
∗
) is an arbitrary
point in each subregion Rij , then the double integral is given in
the limit by
ZZ X
f (x, y) dA = lim f (x∗ij , yij
∗
)∆Aij .
R max ∆Aij →0
i,j
When f is continuous on R, the existence of this limit is guaranteed.
The notation dA represents an infinitesimal area element in the xy-
plane.
A region R is often characterized as either Type I or Type II.
A region is of Type I if it can be written in the form
R = {(x, y) ∈ R2 | a ≤ x ≤ b, c(x) ≤ y ≤ d(x)},
and of Type II if it admits the description
R = {(x, y) ∈ R2 | c ≤ y ≤ d, a(y) ≤ x ≤ b(y)}.
375
These classifications facilitate the conversion of the double integral
into an iterated integral, which is central to its evaluation.
Iterated Integrals and Fubini’s Theorem
Under the assumption that the function f is continuous or, more
generally, Riemann integrable on a rectangular region, Fubini’s
theorem provides the foundational result that permits the eval-
uation of the double integral as an iterated integral. That is, if
R = [a, b] × [c, d], then one has
! !
ZZ Z b
Z d Z Z d b
f (x, y) dA = f (x, y) dy dx = f (x, y) dx dy.
R a c c a
In the case of more general regions that are of either Type I or
Type II, the iterated integrals are defined accordingly by replacing
the constant limits by functions that describe the boundary of the
region. The process of rewriting the double integral as an iterated
integral allows one to leverage techniques from single-variable cal-
culus for its computation, ensuring that the integration over one
variable is performed at a time.
Applications to Areas and Volumes
Double integrals exhibit deep connections with geometric quanti-
ties. For instance, the area of a region R in the plane is computed
by setting ZZ
Area(R) = 1 dA.
R
Such a formulation directly follows from the definition of the Rie-
mann integral and provides an exact measure of the planar region.
In addition, when a surface is described by the height function
z = f (x, y) defined over a region R, the double integral
ZZ
V = f (x, y) dA
R
represents the volume of the solid bounded below by R in the xy-
plane and above by the surface z = f (x, y), assuming that f (x, y)
is nonnegative on R. This formulation offers a natural extension of
376
single-variable integration to capture three-dimensional geometric
properties.
In many practical situations, the region R may possess a compli-
cated or curvilinear boundary. In such cases, partitioning R into
simpler subregions or performing an appropriate change of vari-
ables can simplify the evaluation of the integral. Transformations
to alternate coordinate systems may also prove advantageous when
the geometry of the region suggests symmetry or other exploitable
features.
Additional Applications and Computations
Beyond the computation of areas and volumes, double integrals
facilitate the evaluation of various quantities defined over planar
regions. For example, if the function δ(x, y) represents a density
distribution over the region R, then the total mass M of the region
is determined by ZZ
M= δ(x, y) dA.
R
Similarly, moments and centroids of a lamina can be computed by
incorporating weight factors into the integrals. The first moments
about the x- and y-axes are given by
ZZ ZZ
Mx = yδ(x, y) dA and My = xδ(x, y) dA,
R R
while the coordinates of the center of mass are found by the ratios
xcm = My /M and ycm = Mx /M .
Additional physical quantities, such as the moment of inertia
about a specified axis, are likewise expressed in terms of double
integrals. The formulation of these integrals underscores the ver-
satility and power of double integration in addressing a wide array
of problems in physics and engineering, where coupling the geom-
etry of the region with an appropriate integrand yields significant
insights into the distribution of various physical properties across
the plane.
The precise execution of double integration, through the method
of iterated integrals and the application of Fubini’s theorem, creates
a robust framework for analyzing geometric and physical phenom-
ena defined over two-dimensional regions.
377
Python Code Snippet
import numpy as np
from [Link] import dblquad
import [Link] as plt
# Define the function f(x, y) whose double integral we wish to
,→ compute.
def f(x, y):
return x**2 + y**2
# Define the integration limits for the region R.
# In this example, R is the unit square: [0, 1] x [0, 1].
a, b = 0, 1 # x-limits
c, d = 0, 1 # y-limits
# Approximate the double integral using a Riemann sum.
def double_integral_riemann(func, a, b, c, d, N):
"""
Approximate the double integral of func over the rectangular
,→ region R = [a,b] x [c,d]
using an N x N grid (i.e. a double Riemann sum).
"""
x = [Link](a, b, N)
y = [Link](c, d, N)
dx = (b - a) / (N - 1)
dy = (d - c) / (N - 1)
X, Y = [Link](x, y)
# Evaluate the function on the grid.
f_vals = func(X, Y)
# Sum over all subregions weighted by the area element dx*dy.
integral_approx = [Link](f_vals) * dx * dy
return integral_approx
# Number of subdivisions for the Riemann sum approximation.
N = 100
integral_riemann = double_integral_riemann(f, a, b, c, d, N)
# Compute the double integral using iterated integration via SciPy's
,→ dblquad.
# Note that dblquad integrates with respect to y first (inner) then
,→ x (outer).
integral_dblquad, error = dblquad(lambda y, x: f(x, y), a, b,
lambda x: c, lambda x: d)
# Compute the area of region R by integrating 1 over R.
area, _ = dblquad(lambda y, x: 1, a, b, lambda x: c, lambda x: d)
# Compute additional physical quantities: total mass and centroid
,→ for a uniform density.
density = lambda x, y: 1 # uniform density function
378
mass, _ = dblquad(lambda y, x: density(x, y), a, b, lambda x: c,
,→ lambda x: d)
# First moments about the y-axis and x-axis respectively.
moment_y, _ = dblquad(lambda y, x: x * density(x, y), a, b, lambda
,→ x: c, lambda x: d)
moment_x, _ = dblquad(lambda y, x: y * density(x, y), a, b, lambda
,→ x: c, lambda x: d)
centroid_x = moment_y / mass
centroid_y = moment_x / mass
# Print the computed results.
print("Double Integral of f(x, y) = x^2 + y^2 over R (Riemann sum
,→ approximation):", integral_riemann)
print("Double Integral of f(x, y) = x^2 + y^2 over R (using
,→ dblquad):", integral_dblquad)
print("Estimated error from dblquad:", error)
print("Area of region R:", area)
print("Mass of region R (with uniform density):", mass)
print("Centroid of region R: (", centroid_x, ",", centroid_y, ")")
# Visualize the function f(x, y) over the region R using a contour
,→ plot.
x_plot = [Link](a, b, 100)
y_plot = [Link](c, d, 100)
X_plot, Y_plot = [Link](x_plot, y_plot)
Z = f(X_plot, Y_plot)
[Link](figsize=(8, 6))
contour = [Link](X_plot, Y_plot, Z, cmap='viridis')
[Link](contour)
[Link]('Contour Plot of f(x, y) = x^2 + y^2')
[Link]('x')
[Link]('y')
[Link]()
379
Chapter 65
Multiple Integrals:
Triple Integrals in
Rectangular
Coordinates
Preliminaries and Notation
Let R denote a rectangular parallelepiped in three-dimensional Eu-
clidean space, that is,
R = {(x, y, z) ∈ R3 | a ≤ x ≤ b, c ≤ y ≤ d, e ≤ z ≤ f }.
A function f : R → R defined on this region is integrated by first
partitioning R into a finite collection of subrectangular boxes. Each
box is of the form
∆Rijk = [xi−1 , xi ] × [yj−1 , yj ] × [zk−1 , zk ],
with corresponding volume
∆Vijk = ∆x ∆y ∆z,
where ∆x = xi − xi−1 , ∆y = yj − yj−1 , and ∆z = zk − zk−1 . The
norm ∥P ∥ of the partition P is defined as the maximum length
of the diagonals of these subrectangles. The aim is to consider the
limit of the discrete sum associated with the partition as ∥P ∥ tends
to zero.
380
Definition of the Triple Integral
For a function f defined on the region R, the triple integral is
defined as the limit of a triple Riemann sum. More precisely, if
(x∗ijk , yijk
∗ ∗
, zijk ) is any sample point in ∆Rijk , then the triple inte-
gral is given by
ZZZ X
f (x, y, z) dV = lim f (x∗ijk , yijk
∗ ∗
, zijk ) ∆Vijk ,
R ∥P ∥→0
i,j,k
provided the limit exists. In this context, the differential volume
element dV is represented by dx dy dz. When f is continuous on
the compact region R, the existence of the triple integral is ensured
by the standard theory of Riemann integration.
Iterated Integrals and the Fubini Theo-
rem
Assuming that the function f is integrable over R, Fubini’s theorem
permits the evaluation of the triple integral as an iterated integral.
For a rectangular region, the following representation holds:
ZZZ Z bZ dZ f
f (x, y, z) dV = f (x, y, z) dz dy dx.
R a c e
The theorem guarantees that, under the appropriate conditions of
continuity or measurability, the order of integration may be in-
terchanged without affecting the final value. This iterative process
reduces the triple integral to a sequence of single-variable integrals,
each of which can be handled by techniques from elementary cal-
culus. The equivalence of different orders of integration provides
a powerful tool in simplifying the evaluation of complex integrals
when the integrand or the region of integration exhibits certain
symmetries.
Evaluation Techniques
The computation of a triple integral over a rectangular region gen-
erally proceeds by first evaluating the innermost integral. Suppose
that the integrand is such that the innermost integration with re-
spect to a variable (say, z) can be performed analytically, yielding
381
a function of the remaining variables x and y. The subsequent
outer integration with respect to y is then executed, and finally,
the last integration with respect to x is carried out. Symbolically,
one writes
ZZZ Z b Z d Z f ! !
f (x, y, z) dV = f (x, y, z) dz dy dx.
R x=a y=c z=e
In many problems, the integrand factors into functions of the in-
dividual variables, in which case separation of variables becomes
applicable. Even when the variables are not entirely separable, the
method of successive integration often considerably simplifies the
evaluation by reducing a three-dimensional problem to a sequence
of one-dimensional integrations. Techniques such as substitution
and application of standard antiderivative formulas are employed
at each stage of the iterative process.
Applications to Volume and Geometric
Measures
A common application of triple integrals in rectangular coordinates
is the determination of the volume of a region in three-dimensional
space. When the integrand is identically equal to unity, the triple
integral gives the volume of the region R, that is,
ZZZ
1 dV = (b − a)(d − c)(f − e).
R
Beyond volumetric calculations, triple integrals are instrumental in
computing other geometric and physical quantities. For instance,
when a density function ρ : R → R is defined over the region, the
total mass is given by
ZZZ
M= ρ(x, y, z) dV.
R
Similarly, moments about the coordinate planes, centers of mass,
and moments of inertia are all expressed in terms of triple integrals
that incorporate the appropriate weight factors. In problems where
the integrand reflects a spatially varying property, the triple inte-
gration process accounts for variations along the x-, y-, and z-axes
simultaneously, thereby providing a comprehensive measure of the
quantity studied over the entire region.
382
Each of these applications illustrates the deep interconnection
between the analytic properties of the function under integration
and the geometric features of the region of integration. The frame-
work provided by triple integrals in rectangular coordinates thus
serves as a fundamental tool for the quantitative analysis of three-
dimensional spaces.
Python Code Snippet
import numpy as np
from [Link] import tplquad
def integrand(x, y, z):
"""
Define the integrand function f(x,y,z) for the triple integral.
For demonstration purposes, we use:
f(x, y, z) = x * y + z
This function can represent a density or any physical quantity
,→ whose
total is computed over a three-dimensional region.
"""
return x * y + z
def triple_integral_scipy(a, b, c, d, e, f_val):
"""
Compute the triple integral over a rectangular region R defined
,→ by:
R = { (x,y,z) | a x b, c y d, e z f_val }
The triple integral is given by:
[x=a to b] [y=c to d] [z=e to f_val] f(x, y, z) dz dy dx
This function utilizes [Link] to perform the
,→ integration.
"""
# For a rectangular region the y- and z-limits are constant
,→ functions.
integral_value, error = tplquad(
integrand,
a, b, # x-limits
lambda x: c, lambda x: d, # y-limits (independent of
,→ x)
lambda x, y: e, lambda x, y: f_val # z-limits (independent
,→ of x and y)
)
return integral_value, error
def triple_integral_riemann(a, b, c, d, e, f_val, Nx, Ny, Nz):
383
"""
Approximate the triple integral using a Riemann sum over a
,→ uniformly
partitioned grid on the rectangular region R.
Steps involved:
1. Partition the intervals [a,b], [c,d], and [e,f_val] into
,→ Nx, Ny, Nz subintervals, respectively.
2. Compute the midpoints of these subintervals.
3. Sum f(x_mid, y_mid, z_mid) multiplied by the differential
,→ volume element dV = dx * dy * dz.
Returns:
Approximate value of the triple integral.
"""
# Create partition points for each variable.
x = [Link](a, b, Nx + 1)
y = [Link](c, d, Ny + 1)
z = [Link](e, f_val, Nz + 1)
# Compute the lengths of the subintervals.
dx = (b - a) / Nx
dy = (d - c) / Ny
dz = (f_val - e) / Nz
# Calculate midpoints for improved Riemann sum accuracy.
x_mid = (x[:-1] + x[1:]) / 2
y_mid = (y[:-1] + y[1:]) / 2
z_mid = (z[:-1] + z[1:]) / 2
total_sum = 0.0
# Compute the Riemann sum over the 3D grid.
for xi in x_mid:
for yj in y_mid:
for zk in z_mid:
total_sum += integrand(xi, yj, zk)
volume_element = dx * dy * dz
return total_sum * volume_element
def volume_of_region(a, b, c, d, e, f_val):
"""
Compute the volume of a rectangular region R.
When the integrand is identically 1:
[R] 1 dV = (b - a) * (d - c) * (f_val - e)
This function returns the volume of the region.
"""
return (b - a) * (d - c) * (f_val - e)
if __name__ == "__main__":
# Define the limits of integration for the rectangular region R.
384
a, b = 0, 1 # x-limits
c, d = 0, 2 # y-limits
e, f_val = 0, 3 # z-limits
# Compute the triple integral using SciPy's built-in function.
integral_value, error = triple_integral_scipy(a, b, c, d, e,
,→ f_val)
print("Triple integral using [Link]:")
print("Integral value =", integral_value)
print("Estimated error =", error)
# Compute the triple integral using a Riemann sum approximation.
# Increase Nx, Ny, Nz to improve the approximation accuracy.
Nx, Ny, Nz = 50, 50, 50
integral_approx = triple_integral_riemann(a, b, c, d, e, f_val,
,→ Nx, Ny, Nz)
print("\nTriple integral using Riemann sum approximation:")
print("Approximate integral value =", integral_approx)
# Compute the volume of the region R.
volume = volume_of_region(a, b, c, d, e, f_val)
print("\nVolume of the rectangular region R:")
print("Volume =", volume)
385
Chapter 66
Change of Variables in
Multiple Integrals
General Framework of Coordinate Trans-
formations
Consider a region in n-dimensional Euclidean space where integra-
tion is performed with respect to coordinates (x1 , x2 , . . . , xn ). A
transformation to a new coordinate system (u1 , u2 , . . . , un ) is es-
tablished by a continuously differentiable bijection
T : U ⊂ Rn → V ⊂ Rn ,
which is assumed to have a nonvanishing Jacobian determinant
throughout the region of interest. Under this transformation, the
differential element transforms according to
∂(x1 , x2 , . . . , xn )
dx1 dx2 · · · dxn = du1 du2 · · · dun ,
∂(u1 , u2 , . . . , un )
where the Jacobian determinant
∂(x1 , . . . , xn )
J(u1 , . . . , un ) =
∂(u1 , . . . , un )
quantifies the local scaling induced by the coordinate transforma-
tion. This fundamental relationship permits the reexpression of
multiple integrals in the new coordinate system, thereby often lead-
ing to significant simplifications in both the integrand and the re-
gion of integration.
386
1 Polar Coordinates in Two Dimensions
In the special case of two-dimensional integrals, the transforma-
tion from Cartesian coordinates (x, y) to polar coordinates (r, θ) is
defined by
x = r cos θ, y = r sin θ,
with the constraints r ≥ 0 and θ ∈ [0, 2π). The Jacobian matrix
for this transformation is computed as
! !
∂x ∂x
cos θ −r sin θ
∂r ∂θ
= ,
∂y
∂r
∂y
∂θ
sin θ r cos θ
so that the absolute value of its determinant is
J(r, θ) = |cos θ · r cos θ − (−r sin θ) · sin θ| = r(cos2 θ + sin2 θ) = r.
Accordingly, the differential area element transforms as
dx dy = r dr dθ.
This formulation is particularly effective when the region of inte-
gration or the integrand exhibits circular or radial symmetry.
2 Cylindrical Coordinates in Three Dimensions
When addressing integrals in three-dimensional space, cylindrical
coordinates provide a natural extension of the polar coordinate
system to include a vertical component. The transformation from
Cartesian coordinates (x, y, z) to cylindrical coordinates (r, θ, z) is
given by
x = r cos θ, y = r sin θ, z = z.
Since the z-coordinate remains unchanged, the Jacobian determi-
nant is derived by considering the transformation in the xy-plane,
yielding
∂(x, y, z)
J(r, θ, z) = = r.
∂(r, θ, z)
Thus, the differential volume element in this coordinate system
becomes
dx dy dz = r dr dθ dz.
Such a transformation simplifies the evaluation of integrals over
regions that exhibit symmetry about an axis, particularly in cases
involving rotational invariance.
387
3 Spherical Coordinates in Three Dimensions
Spherical coordinates provide an effective means of addressing inte-
grals defined on regions with spherical symmetry. The transforma-
tion from Cartesian coordinates (x, y, z) to spherical coordinates
(ρ, ϕ, θ) is delineated by
x = ρ sin ϕ cos θ, y = ρ sin ϕ sin θ, z = ρ cos ϕ,
where ρ ≥ 0, ϕ ∈ [0, π] is the polar angle measured from the posi-
tive z-axis, and θ ∈ [0, 2π) is the azimuthal angle in the xy-plane.
The Jacobian determinant for this transformation is computed by
taking the determinant of the matrix formed by the partial deriva-
tives of (x, y, z) with respect to (ρ, ϕ, θ), leading to
J(ρ, ϕ, θ) = ρ2 sin ϕ.
Consequently, the volume element in spherical coordinates is ex-
pressed as
dx dy dz = ρ2 sin ϕ dρ dϕ dθ.
This coordinate system is especially advantageous when the inte-
grand or the spatial region possesses inherent spherical symmetry,
thereby facilitating the integration process by aligning the coordi-
nate lines with the geometry of the problem.
Python Code Snippet
# Python Code for Coordinate Transformations and Jacobian
,→ Determinants
import sympy as sp
# Initialize pretty printing for LaTeX output
sp.init_printing(use_latex='mathjax')
# ==============================
# Polar Coordinates in Two Dimensions
# ==============================
# Define symbols for polar coordinates
r, theta = [Link]('r theta')
# Define the transformation equations:
# x = r*cos(theta) and y = r*sin(theta)
x_polar = r * [Link](theta)
y_polar = r * [Link](theta)
388
# Create vectors for the transformation and the original coordinates
X_polar = [x_polar, y_polar]
U_polar = [r, theta]
# Compute the Jacobian matrix for the polar transformation
jacobian_polar = [Link](X_polar).jacobian(U_polar)
# Compute the determinant of the Jacobian matrix
det_jacobian_polar = [Link](jacobian_polar.det())
print("Polar Coordinates Transformation:")
print("x =", x_polar)
print("y =", y_polar)
print("Jacobian Matrix:")
[Link](jacobian_polar)
print("Determinant of Jacobian (should be r):")
[Link](det_jacobian_polar)
# ==============================
# Cylindrical Coordinates in Three Dimensions
# ==============================
# Define symbols: reusing r and theta, add z coordinate
r, theta, z = [Link]('r theta z')
# Define the transformation equations:
# x = r*cos(theta), y = r*sin(theta), and z = z
x_cyl = r * [Link](theta)
y_cyl = r * [Link](theta)
z_cyl = z
X_cyl = [x_cyl, y_cyl, z_cyl]
U_cyl = [r, theta, z]
# Compute the Jacobian matrix for the cylindrical transformation
jacobian_cyl = [Link](X_cyl).jacobian(U_cyl)
# Compute the determinant of the Jacobian matrix
det_jacobian_cyl = [Link](jacobian_cyl.det())
print("\nCylindrical Coordinates Transformation:")
print("x =", x_cyl)
print("y =", y_cyl)
print("z =", z_cyl)
print("Jacobian Matrix:")
[Link](jacobian_cyl)
print("Determinant of Jacobian (should be r):")
[Link](det_jacobian_cyl)
# ==============================
# Spherical Coordinates in Three Dimensions
# ==============================
# Define symbols for spherical coordinates
rho, phi, theta = [Link]('rho phi theta')
# Define the transformation equations:
389
# x = rho*sin(phi)*cos(theta),
# y = rho*sin(phi)*sin(theta),
# z = rho*cos(phi)
x_sph = rho * [Link](phi) * [Link](theta)
y_sph = rho * [Link](phi) * [Link](theta)
z_sph = rho * [Link](phi)
X_sph = [x_sph, y_sph, z_sph]
U_sph = [rho, phi, theta]
# Compute the Jacobian matrix for the spherical transformation
jacobian_sph = [Link](X_sph).jacobian(U_sph)
# Compute the determinant of the Jacobian matrix
det_jacobian_sph = [Link](jacobian_sph.det())
print("\nSpherical Coordinates Transformation:")
print("x =", x_sph)
print("y =", y_sph)
print("z =", z_sph)
print("Jacobian Matrix:")
[Link](jacobian_sph)
print("Determinant of Jacobian (should be rho^2*sin(phi)):")
[Link](det_jacobian_sph)
# ==============================
# General Jacobian Function
# ==============================
def compute_jacobian(transformations, variables):
"""
Compute the Jacobian matrix and its determinant for a given
,→ transformation.
Parameters:
transformations (list): A list of sympy expressions representing
,→ the transformed coordinates.
variables (list): A list of sympy symbols for the original
,→ coordinate variables.
Returns:
tuple: A tuple containing the Jacobian matrix and its
,→ determinant.
"""
matrix_j = [Link](transformations).jacobian(variables)
det_j = [Link](matrix_j.det())
return matrix_j, det_j
# Example usage of the general Jacobian function with polar
,→ coordinates
print("\nGeneral Jacobian Computation for Polar Coordinates:")
J_polar, det_J_polar = compute_jacobian([x_polar, y_polar], [r,
,→ theta])
[Link](J_polar)
print("Determinant:")
390
[Link](det_J_polar)
391