''' cylinder_surface_min.py
calculate the height to radius ratio of a minimum surface cylindrical
container (can)

r = radius
circle_area = pi * r**2
circle_circumference = 2 * pi * r

h = height
cylinder_volume = pi * r**2 * h

surface area of a closed cylinder:
the area of the top (pi * r**2) +
the area of the bottom (pi * r**2) +
the area of the side (2 * pi * r * h)
or
cylinder_surface = 2 * (pi * r**2) + (2 * pi * r * h)

let the cylinder_volume be a constant of 500 ml (cubiccentimeter)
cylinder_volume = 500
using the cylinder_volume formula express h in terms of r ...
h = 500/(pi * r**2)

now substitude h in the cylinder_surface formula
(this expresses the cylinder surface in terms of r)
cylinder_surface = 2 * (pi * r**2) + (2 * pi * r * 500/(pi * r**2))

tested with Python34  by  vegaseat  5apr2015
'''

from math import pi
import pprint

# rough calculation of the radius range to achieve a minimum surface
# create a list of (surface area, radius) tuples
mylist = []
for r in range(1, 11):
    cylinder_surface = 2 * (pi * r**2) + (2 * pi * r * 500/(pi * r**2))
    mylist.append((cylinder_surface, r))
    
#pprint.pprint(mylist)  # test

''' we see that the surface minimizes between r=3 and r=5
[(1006.2831853071795, 1),
 (525.1327412287183, 2),
 (389.88200109794957, 3),
 (350.5309649148734, 4),
 (357.0796326794897, 5),
 (392.86133772513176, 6),
 (450.7332229089426, 7),
 (527.1238596594935, 8),
 (620.0491209926575, 9),
 (728.3185307179587, 10)]
'''

# since range() takes only integers let's use a while loop
# then we can increment in smaller steps
r = 3
surface_list = []
while True:
    cylinder_surface = 2 * (pi * r**2) + (2 * pi * r * 500/(pi * r**2))
    surface_list.append((cylinder_surface, r)) 
    r += 0.1
    if r > 5:
        break

#print(min(surface_list))  # test

''' the minimum surface of a 500ml can is reached at r = 4.3
(348.7342358646343, 4.3)
'''

min_surface = min(surface_list)[0]
sf = "Minimum surface of a 500ml can = {:0.1f} square centimeters"
print(sf.format(min_surface))    
radius = min(surface_list)[1]
print("Radius of 500ml can = {:0.1f} centimeters".format(radius))
height = 500/(pi * radius**2)
print("Height of 500ml can = {:0.1f} centimeters".format(height))  
# true for any volume ...
sf = "Ratio of height to radius of a minimized surface can = {:0.1f}"
print(sf.format(height/radius))

''' result ...
Minimum surface of a 500ml can = 348.7 square centimeters
Radius of 500ml can = 4.3 centimeters
Height of 500ml can = 8.6 centimeters
Ratio of height to radius of a minimized surface can = 2.0
'''
2
Contributors
2
Replies
64
Views
2 Years
Discussion Span
Last Post by vegaseat
2

Your method can be called optimization by scanning. It has the advantage of requiring nothing but elementary python code to work. In applications, one would use an existing solver such as solvers found in scipy. For example

>>> from scipy import pi
>>> import scipy.optimize as opt
>>> 
>>> def objective(r, vol):
...     return 2 * (pi * r**2) + (2 * pi * r * vol/(pi * r**2))
... 
>>> result = opt.minimize_scalar(objective, args = (500,), bracket = (0.0001, 10000.0))
>>> print(result)
  fun: 348.73420545288792
 nfev: 27
  nit: 26
    x: 4.3012700752223054
>>> 

The scipy solvers contain powerful methods of numerical analysis. They can save a lot of programmer's time in many common math problems such as minimization or root finding.

Edited by Gribouillis

0

I guess the emphasis is on "a Python program that explains the steps to achieve this"

Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.