The provided code defines the data
list containing information about various activities and their dependencies. The calculate_critical_path
function then calculates the critical path for these activities and prints the result using json.dumps
.
When you run the script, the output will be a formatted JSON representation of the critical_path
data, including the earliest start (es), earliest finish (ef), latest start (ls), latest finish (lf), and slack time for each activity.
import json
data = [
{
'activity': 'a',
"duration": 3,
"predecessor": []
},
{
'activity': 'b',
"duration": 4,
"predecessor": ['a']
},
{
'activity': 'c',
"duration": 2,
"predecessor": ['a']
},
{
'activity': 'd',
"duration": 5,
"predecessor": ['b']
},
{
'activity': 'e',
"duration": 1,
"predecessor": ['c']
},
{
'activity': 'f',
"duration": 2,
"predecessor": ['c']
},
{
'activity': 'g',
"duration": 4,
"predecessor": ['d', 'e']
},
{
'activity': 'h',
"duration": 3,
"predecessor": ['f', 'g']
}
]
def calculate_critical_path(data):
for activity in data:
es = 0
predecessors = activity['predecessor']
if predecessors:
es = max(d['ef'] for d in data if d['activity'] in predecessors)
ef = es + activity['duration']
activity['es'] = es
activity['ef'] = ef
activity['ls'] = 0
activity['lf'] = 0
activity['slack'] = 0
# Calculate ls, lf, and slack in reverse order of activities
max_lf = data[-1]['ef'] # Initialize max_lf with the last activity's ef
for activity in reversed(data):
successors = [d for d in data if activity['activity'] in d['predecessor']]
lf = max_lf if not successors else min(d['ls'] for d in successors)
activity['lf'] = lf
activity['ls'] = lf - activity['duration']
activity['slack'] = activity['lf'] - activity['ef']
max_lf = activity['lf'] # Update max_lf for the next iteration
return data
critical_path = calculate_critical_path(data)
print(json.dumps(critical_path, indent=4, sort_keys=True))