Worked Examples: Advanced Loop Control#
These worked solutions correspond to the exercises on the Advanced Loop Control page.
How to use this notebook:
Try each exercise yourself first before looking at the solution
The code cells show both the code and its output
Download this notebook if you want to run and experiment with the code yourself
Your solution might look different - that’s fine as long as it gives the correct answer!
Exercise 1: Temperature-Dependent Reaction Rate Study#
Problem: You are investigating how reaction rate changes with temperature. Your automated system heats a reaction vessel from 20°C to 100°C in 8°C increments, taking a measurement at each temperature.
Write a while
loop that:
Starts with
temperature = 20
(°C)Takes a measurement (just print the temperature for now)
Increases temperature by 8°C
Continues until temperature reaches or exceeds 100°C
Print each measurement temperature and count the total number of measurements taken.
Solution:
temperature = 20 # Starting temperature in °C
increment = 8 # Temperature increase per step
measurement_count = 0 # Counter for measurements
while temperature <= 100:
measurement_count += 1
print(f"Measurement {measurement_count}: {temperature}°C")
temperature += increment
print(f"\nCompleted {measurement_count} measurements from 20°C to {temperature - increment}°C")
Measurement 1: 20°C
Measurement 2: 28°C
Measurement 3: 36°C
Measurement 4: 44°C
Measurement 5: 52°C
Measurement 6: 60°C
Measurement 7: 68°C
Measurement 8: 76°C
Measurement 9: 84°C
Measurement 10: 92°C
Measurement 11: 100°C
Completed 11 measurements from 20°C to 100°C
How this works:
The
while
loop continues as long astemperature <= 100
Each iteration:
We increment the measurement counter
Print the current temperature
Increase the temperature by 8°C
Note: The final print
statement shows the last measurement temperature (temperature - increment
) rather than the current value of temperature
, which is increased to 108°C in the final loop iteration.
print(temperature)
108
Exercise 2: Convergence with Iteration Limit#
Problem: The cooling simulation from the example converges relatively quickly because it loses 10% of the temperature difference each step. However, if the cooling rate is slower, convergence can take many iterations.
Modify the simulation to use a slower cooling rate (only 2% per step instead of 10%). This is more realistic for a well-insulated vessel. However, since convergence is now much slower, add an iteration limit of 100 steps. If equilibrium isn’t reached within 100 steps, stop and report that more time is needed.
Solution#
temperature = 100.0 # Starting temperature in °C
room_temperature = 20.0 # Ambient temperature in °C
threshold = 0.5 # Stop when within 0.5°C of room temp
cooling_rate = 0.02 # Cool by 2% per step
iteration = 0
max_iterations = 100
# Check if we're already at equilibrium before starting the loop
converged = temperature - room_temperature <= threshold
while not converged and iteration < max_iterations:
# Cool by 2% of the temperature difference each step
temperature_difference = temperature - room_temperature
temperature = temperature - cooling_rate * temperature_difference
iteration += 1
print(f"Step {iteration}: Temperature = {temperature:.2f}°C")
# Check if we've reached equilibrium
if temperature - room_temperature <= threshold:
converged = True
# Report results based on whether convergence was achieved
if converged:
print(f"\nThermal equilibrium reached after {iteration} steps")
print(f"Final temperature: {temperature:.2f}°C")
else:
print(f"\nIteration limit reached after {iteration} steps")
print(f"Current temperature: {temperature:.2f}°C (still {temperature - room_temperature:.2f}°C above room temperature)")
Step 1: Temperature = 98.40°C
Step 2: Temperature = 96.83°C
Step 3: Temperature = 95.30°C
Step 4: Temperature = 93.79°C
Step 5: Temperature = 92.31°C
Step 6: Temperature = 90.87°C
Step 7: Temperature = 89.45°C
Step 8: Temperature = 88.06°C
Step 9: Temperature = 86.70°C
Step 10: Temperature = 85.37°C
Step 11: Temperature = 84.06°C
Step 12: Temperature = 82.78°C
Step 13: Temperature = 81.52°C
Step 14: Temperature = 80.29°C
Step 15: Temperature = 79.09°C
Step 16: Temperature = 77.90°C
Step 17: Temperature = 76.75°C
Step 18: Temperature = 75.61°C
Step 19: Temperature = 74.50°C
Step 20: Temperature = 73.41°C
Step 21: Temperature = 72.34°C
Step 22: Temperature = 71.29°C
Step 23: Temperature = 70.27°C
Step 24: Temperature = 69.26°C
Step 25: Temperature = 68.28°C
Step 26: Temperature = 67.31°C
Step 27: Temperature = 66.37°C
Step 28: Temperature = 65.44°C
Step 29: Temperature = 64.53°C
Step 30: Temperature = 63.64°C
Step 31: Temperature = 62.77°C
Step 32: Temperature = 61.91°C
Step 33: Temperature = 61.07°C
Step 34: Temperature = 60.25°C
Step 35: Temperature = 59.45°C
Step 36: Temperature = 58.66°C
Step 37: Temperature = 57.88°C
Step 38: Temperature = 57.13°C
Step 39: Temperature = 56.38°C
Step 40: Temperature = 55.66°C
Step 41: Temperature = 54.94°C
Step 42: Temperature = 54.24°C
Step 43: Temperature = 53.56°C
Step 44: Temperature = 52.89°C
Step 45: Temperature = 52.23°C
Step 46: Temperature = 51.59°C
Step 47: Temperature = 50.95°C
Step 48: Temperature = 50.33°C
Step 49: Temperature = 49.73°C
Step 50: Temperature = 49.13°C
Step 51: Temperature = 48.55°C
Step 52: Temperature = 47.98°C
Step 53: Temperature = 47.42°C
Step 54: Temperature = 46.87°C
Step 55: Temperature = 46.33°C
Step 56: Temperature = 45.81°C
Step 57: Temperature = 45.29°C
Step 58: Temperature = 44.79°C
Step 59: Temperature = 44.29°C
Step 60: Temperature = 43.80°C
Step 61: Temperature = 43.33°C
Step 62: Temperature = 42.86°C
Step 63: Temperature = 42.40°C
Step 64: Temperature = 41.96°C
Step 65: Temperature = 41.52°C
Step 66: Temperature = 41.09°C
Step 67: Temperature = 40.67°C
Step 68: Temperature = 40.25°C
Step 69: Temperature = 39.85°C
Step 70: Temperature = 39.45°C
Step 71: Temperature = 39.06°C
Step 72: Temperature = 38.68°C
Step 73: Temperature = 38.31°C
Step 74: Temperature = 37.94°C
Step 75: Temperature = 37.58°C
Step 76: Temperature = 37.23°C
Step 77: Temperature = 36.88°C
Step 78: Temperature = 36.55°C
Step 79: Temperature = 36.22°C
Step 80: Temperature = 35.89°C
Step 81: Temperature = 35.57°C
Step 82: Temperature = 35.26°C
Step 83: Temperature = 34.96°C
Step 84: Temperature = 34.66°C
Step 85: Temperature = 34.37°C
Step 86: Temperature = 34.08°C
Step 87: Temperature = 33.80°C
Step 88: Temperature = 33.52°C
Step 89: Temperature = 33.25°C
Step 90: Temperature = 32.98°C
Step 91: Temperature = 32.73°C
Step 92: Temperature = 32.47°C
Step 93: Temperature = 32.22°C
Step 94: Temperature = 31.98°C
Step 95: Temperature = 31.74°C
Step 96: Temperature = 31.50°C
Step 97: Temperature = 31.27°C
Step 98: Temperature = 31.05°C
Step 99: Temperature = 30.83°C
Step 100: Temperature = 30.61°C
Iteration limit reached after 100 steps
Current temperature: 30.61°C (still 10.61°C above room temperature)
How this works:
1. The converged
flag:
Initialised before the loop by checking if we’re already at equilibrium
This handles the edge case where
temperature
might already be at room temperatureUpdated inside the loop when the threshold is reached
2. The while
loop has two conditions connected by and
:
not converged
- continue if we haven’t reached equilibriumiteration < max_iterations
- but stop if we exceed the iteration limitThe loop continues only while both conditions are
True
3. How the loop can exit:
Natural convergence: When
converged = True
is set inside the loop, the conditionnot converged
becomesFalse
, and the loop exitsIteration limit: When
iteration
reachesmax_iterations
, the conditioniteration < max_iterations
becomesFalse
, and the loop exits
4. After the loop:
The
converged
flag tells us definitively whether equilibrium was achievedIf
converged = True
: loop exited because threshold was met (success)If
converged = False
: loop exited because iteration limit was reached
Alternative Solution 1: Using break
#
An alternative approach uses break
to exit the loop early when the iteration limit is reached. This separates the two exit conditions rather than combining them in the while
statement.
temperature = 100.0 # Starting temperature in °C
room_temperature = 20.0 # Ambient temperature in °C
threshold = 0.5 # Stop when within 0.5°C of room temp
cooling_rate = 0.02 # Cool by 2% per step
iteration = 0
max_iterations = 100
# Assume we will converge.
# Set to False inside the loop if we reach the break condition.
converged = True
while temperature - room_temperature > threshold:
# Cool by 2% of the temperature difference each step
temperature_difference = temperature - room_temperature
temperature = temperature - cooling_rate * temperature_difference
iteration += 1
print(f"Step {iteration}: Temperature = {temperature:.2f}°C")
# Check if we've exceeded the iteration limit
if iteration >= max_iterations:
converged = False # We didn't converge in time
break # Exit the loop early
# code for reporting the results is the same as before
Alternative Solution 2: Using a Function to Test Convergence#
In the main solution, we test the convergence condition twice:
Before the loop:
converged = temperature - room_temperature <= threshold
Inside the loop:
if temperature - room_temperature <= threshold:
When the same code appears multiple times, it’s good practice to define a function. This approach demonstrates the DRY principle (Don’t Repeat Yourself). In this case, it ensures that we always use the same convergence criteria. And if we want to change how convergence is defined, we only need to make these changes in one place.
def is_converged(temperature, room_temperature, threshold):
"""
Check if the temperature has converged to within the threshold.
Args:
temperature (float): Current temperature (°C).
room_temperature (float): Ambient temperature (°C).
threshold (float): Convergence threshold (°C).
Returns:
bool: True if converged, False otherwise.
"""
return temperature - room_temperature <= threshold
temperature = 100.0 # Starting temperature in °C
room_temperature = 20.0 # Ambient temperature in °C
threshold = 0.5 # Stop when within 0.5°C of room temp
cooling_rate = 0.02 # Cool by 2% per step
iteration = 0
max_iterations = 100
# Check if we're already at equilibrium before starting the loop
converged = is_converged(temperature, room_temperature, threshold)
while not converged and iteration < max_iterations:
# Cool by 2% of the temperature difference each step
temperature_difference = temperature - room_temperature
temperature = temperature - cooling_rate * temperature_difference
iteration += 1
print(f"Step {iteration}: Temperature = {temperature:.2f}°C")
# Check if we've reached equilibrium using the same convergence testing function
converged = is_converged(temperature, room_temperature, threshold)
# code for reporting the results is the same as before
Why use a function for the convergence test?
1. DRY Principle (Don’t Repeat Yourself):
The convergence condition
temperature - room_temperature <= threshold
was written twice in the original codeWith a function, we define the logic once and reuse it
This reduces code duplication
2. Easier to modify:
If we want to change the convergence criterion (e.g., use absolute value, or a percentage-based threshold), we only need to update it in one place
Without a function, we’d need to find and update every occurrence
3. More readable:
is_converged(temperature, room_temperature, threshold)
reads naturally - it’s clear what we’re checkingThe calculation
temperature - room_temperature <= threshold
requires mental parsing to understand
4. Easier to test:
We can test the convergence function independently with different inputs
This is especially valuable for more complex convergence criteria
5. Reusability:
If we have multiple simulations with the same convergence criterion, we can reuse the function
Promotes consistent behaviour across different parts of the code
Example of when this matters:
Suppose we later realise the convergence criterion should check the absolute temperature difference (to handle cooling and heating):
def is_converged(temperature, room_temperature, threshold):
"""Check if temperature has converged to within threshold."""
return abs(temperature - room_temperature) <= threshold
With a function, this is a one-line change. Without it, we’d need to find and update both occurrences, risking bugs if we miss one.
Trade-off: For very simple conditions used only 2-3 times in short code, a function might be overkill. But as code grows in complexity, extracting repeated logic into functions becomes increasingly valuable.