Lambda function
Lambda functions in Python are small, anonymous functions defined with the lambda
keyword rather than with the standard def
statement. They allow you to write functions in a concise way when you don't need to reuse the function multiple times, making your code shorter and often more readable in context.
Key Characteristics of Lambda Functions
Anonymous: Lambda functions do not have a formal name. They are often used inline as an argument to other functions.
Single Expression: A lambda function is restricted to a single expression. The result of that expression is implicitly returned. You cannot include multiple statements or assignments within a lambda.
Usage Context: They are typically used in situations where a full function definition would be unnecessarily verbose, such as in functional programming constructs (e.g., when using
map()
,filter()
, orsorted()
), or for quick calculations.Syntax: The basic syntax for a lambda function is:
1
lambda arguments: expression
- arguments: A comma-separated list of parameters.
- expression: A single expression that is evaluated and returned.
Examples of Lambda Functions
1. Simple Arithmetic Operation
A basic example of a lambda function is adding 1 to a number: 1
2
3add_one = lambda x: x + 1
result = add_one(5)
print(result) # Output: 6
In this example: - lambda x: x + 1
defines a lambda function that takes one input x
and returns x + 1
. - The function is assigned to the variable add_one
, which can be used just like any other function.
2. Sorting with a Lambda Function
Lambda functions are commonly used to provide a key function for sorting: 1
2
3
4
5
6
7# List of tuples representing (name, age)
people = [("Alice", 30), ("Bob", 25), ("Charlie", 35)]
# Sort by age (the second element of each tuple)
people_sorted = sorted(people, key=lambda person: person[1])
print(people_sorted)
# Output: [('Bob', 25), ('Alice', 30), ('Charlie', 35)]
In this example: - The sorted()
function is used with the key
parameter, which expects a function that extracts a comparison key from each list element. - The lambda function lambda person: person[1]
picks the second element (age) from each tuple for sorting.
3. Using Lambda with map()
and filter()
Lambda functions are also useful for transforming lists: - Using map()
: 1
2
3
4numbers = [1, 2, 3, 4, 5]
# Double each number using a lambda function
doubled = list(map(lambda x: x * 2, numbers))
print(doubled) # Output: [2, 4, 6, 8, 10]
- Using
filter()
:1
2
3
4numbers = [1, 2, 3, 4, 5, 6]
# Filter out even numbers using a lambda function
odds = list(filter(lambda x: x % 2 != 0, numbers))
print(odds) # Output: [1, 3, 5]
In these examples: - map()
applies the lambda function to each element, returning a new list with the transformed values. - filter()
applies the lambda function as a condition. It returns a new list consisting only of elements for which the function returns True
.
4. Lambda in the Context of fsolve
In snippet: 1
beta_sol = fsolve(lambda beta: equation(beta, theta), 0.0)[0]
lambda beta: equation(beta, theta)
is used to create an anonymous function that takes only beta
as an argument. - This lambda “freezes” theta
(provided from the outer loop) so that fsolve
only needs to vary beta
to find a solution for which equation(beta, theta) = 0
. - fsolve
then returns an array of solutions. The [0]
index extracts the first (and only) solution.
Summary
Lambda functions are a concise way to define small functions on the fly without naming them. They are particularly useful when used as arguments to higher-order functions or in contexts where the functionality is short-lived and does not require a formal definition.
fsolve
function
The fsolve
function in Python is part of the scipy.optimize
module and is used to find the roots of a system of nonlinear equations. It employs numerical methods to solve equations of the form \(F(x) = 0\), where \(F\) can be a scalar or vector function. Below is a detailed explanation of its functionality and parameters.
Key Features of fsolve
- Purpose: Solve nonlinear equations (or systems of equations) numerically.
- Algorithm: Uses MINPACK’s
hybrd
algorithm (a modification of Powell’s method) for systems and scalar equations. - Input: Requires an initial guess (
x0
) for the solution. - Output: Returns the root (or roots) closest to the initial guess.
Function Syntax
1 | from scipy.optimize import fsolve |
Parameters Explained
1. func
(required)
Definition: The function \(F(x)\) whose root is to be found.
Input: A vector (for systems) or scalar (for single equations).
Output: A vector of residuals (for systems) or a scalar (for single equations).
Example
1
2
3
4
5
6
7
8
9
10# Single equation: x^2 - 4 = 0
def func(x):
return x**2 - 4
# System of equations:
# x + y = 3
# x - y = 1
def system_func(vars):
x, y = vars
return [x + y - 3, x - y - 1]
2. x0
(required)
Definition: Initial guess for the root(s). Critical for convergence!
Type: Array-like (even for scalar equations).
Example
1
2
3
4
5# For x^2 - 4 = 0, guess x=3
x0_single = [3]
# For the system, guess x=0, y=0
x0_system = [0, 0]
3. args
(optional)
Definition: Extra arguments to pass to
func
(e.g., constants).Type: Tuple.
Example
1
2
3
4
5# Solve f(x, a, b) = x^2 + a*x + b = 0
def func(x, a, b):
return x**2 + a*x + b
solution = fsolve(func, x0=[1], args=(2, 3)) # Solves x² + 2x + 3 = 0
4. fprime
(optional)
Definition: Jacobian matrix (derivatives) of
func
. If provided, improves efficiency.Type: Function returning the Jacobian.
Example
1
2
3
4
5
6
7
8# Jacobian for the system:
# F = [x + y - 3, x - y - 1]
def jacobian(vars):
x, y = vars
return [[1, 1], # dF1/dx, dF1/dy
[1, -1]] # dF2/dx, dF2/dy
solution = fsolve(system_func, x0=[0,0], fprime=jacobian)
5. xtol
(optional)
- Definition: Tolerance for termination. The solver stops when the relative error between iterations is below
xtol
. - Default: \(1.49 \times 10^{-8}\).
6. maxfev
(optional)
- Definition: Maximum number of function evaluations. If set to 0, the limit is \(100 \times (n+1)\), where \(n\) is the number of variables.
- Use Case: Prevents infinite loops for non-convergent problems.
7. full_output
(optional)
Definition: If
True
, returns additional metadata (e.g., convergence status).Example
1
2solution, infodict, ier, msg = fsolve(func, x0=[1], full_output=True)
print(infodict) # Shows function evaluations, Jacobian, etc.
Examples
Example 1: Solve \(x^2 - 4 = 0\)
1 | from scipy.optimize import fsolve |
Example 2: Solve a System of Equations
1 | def system_func(vars): |
Example 3: Using args
for Parameters
1 | def func(x, a, b): |
Common Issues & Tips
- Initial Guess (
x0
):- Poor guesses may lead to no convergence. Try different values!
- Use domain knowledge or plot the function to choose
x0
.
- Convergence Problems:
- Check if
func(x0)
is close to zero (e.g.,print(func(x0))
). - Increase
maxfev
or adjustxtol
.
- Check if
- Jacobian:
- Providing
fprime
speeds up convergence but requires manual derivative calculations.
- Providing
- Systems of Equations:
- Ensure
func
returns an array of residuals with the same length asx0
.
- Ensure
Output
Returns: A NumPy array containing the root(s).
If
full_output=True
, returns a tuple:1
(solution, infodict, ier, msg)
infodict
: Dictionary with details (e.g., number of function evaluations).ier
: Status (1 = success).msg
: Description of termination cause.
fsolve
is a powerful tool for solving nonlinear equations, but its success heavily depends on the initial guess (x0
) and the behavior of the function. For complex systems, consider using alternative methods (e.g., root
with method=lm
for least-squares minimization).
Compute the sum of two arrays
We can easily compute a new set of values by summing each \(\theta\) with its corresponding \(\beta\) only if \(\beta\) is a valid number (i.e. not nan
). One common approach is to filter out the pairs where \(\beta\) is nan
. Here are two approaches you can use:
Approach 1: List Comprehension
Convert your \(\theta\) values (which is already a NumPy array) and your beta_values
(a list) into a list of sums for the valid cases:
1 | import numpy as np |
This code uses Python's built-in zip
function to iterate over both lists in parallel and np.isnan(beta)
to check if beta
is not a number. It then only sums those pairs which have a valid \(\beta\).
zip
function
The original arrays, theta_values
and beta_values
, both have the same number of elements regardless of the presence of nan
values. The list comprehension with zip
pairs them element‐by‐element (by their index). However, the filtering condition (if not np.isnan(beta)
) means that if the beta
value is nan
, the corresponding pair (including the theta
value) is skipped when constructing the new list.
What This Means
Original Arrays: Both
theta_values
andbeta_values
have the same length, say \(N\). Each position \(i\) in both arrays corresponds to a single pair \((\theta_i, \beta_i)\).Filtered List Construction: With the list comprehension:
1
theta_beta_sum = [theta + beta for theta, beta in zip(theta_values, beta_values) if not np.isnan(beta)]
each pair is evaluated. If
beta
is a valid number (i.e., notnan
), the sum \(\theta_i + \beta_i\) is computed and appended totheta_beta_sum
. Ifbeta
isnan
, that pair is omitted. Consequently, the resulting listtheta_beta_sum
will only include sums wherebeta
is valid, and its length may be less than \(N\).
Example
Assume:
1 | theta_values = np.array([0, 0.5, 1.0, 1.5]) |
- The zipped pairs are:
- (0, 0.1) → valid, so include \(0 + 0.1 = 0.1\)
- (0.5, np.nan) →
beta
isnan
, so skip this pair. - (1.0, 0.3) → valid, so include \(1.0 + 0.3 = 1.3\)
- (1.5, 0.4) → valid, so include \(1.5 + 0.4 = 1.9\)
The final list becomes:
1 | theta_beta_sum = [0.1, 1.3, 1.9] |
Notice that the second element was omitted because beta
was nan
.
Summary
- Dimensions Remain Unchanged: The original
theta_values
andbeta_values
arrays keep their original dimensions. - Filtered Sum List: The list comprehension creates a new list that only contains sums from pairs where
beta
is a valid number, which might result in a list with fewer elements than the original arrays.
This approach ensures you're calculating sums only from the valid pairs while leaving the original data intact.
Approach 2: Using NumPy Arrays
Alternatively, we can convert your beta_values
list to a NumPy array and use boolean indexing:
1 | import numpy as np |
With boolean indexing, we first create an index (valid_idx
) where the \(\beta\) values are valid. Then we use that index to select the corresponding \(\theta\) values and \(\beta\) values before computing the sum.
Both methods will give the sum of \(\theta\) and \(\beta\) only where \(\beta\) is not nan
.
write data into csv file
1 | import csv |