Skip to content

[Bug]: durations list in the Quick Start example is misaligned — includes an extra value that causes silent calculation errors #79

Description

@prince-pokharna

Summary

The Quick Start example in the README contains a subtle but impactful bug in the activity data definition. The durations list has 5 values (including one for Origin), while activities has 4 entries and predecessors has 4 entries. The comment says "First duration is for Origin" — but add_activity('O', 0) is called separately, meaning durations[0] = 0 is passed to add_activities_relations and effectively misaligns all duration-to-activity mappings by one index.

Problem

activities = ['A', 'B', 'C', 'D']
durations = [0, 2, 5, 4, 2]   # 5 values — index 0 is "Origin" but Origin is already added separately
predecessors = ['-', 'A', 'B', 'B,C']  # 4 values, aligned to activities

cpm.add_activity('O', 0)  # Origin already added here
cpm.add_activities_relations(activities, durations, predecessors)
# This likely maps: A→0, B→2, C→5, D→4 — and ignores the last duration (2)
# Or raises an IndexError depending on how add_activities_relations zips/iterates

This means:

  • Activity A gets duration 0 instead of 2.
  • Activity D gets duration 4 instead of 2, or the last duration is silently dropped.
  • The CPM calculations (ES, EF, LS, LF, critical path) will be wrong for any network built using this example as a template.

Impact

  • Every new user who runs the Quick Start example gets incorrect CPM output without any error or warning.
  • The example is the primary onboarding path for the library — a silent data error here undermines confidence in the library's correctness.
  • Academic users (CPM/PERT is heavily taught in operations management courses) will get wrong critical path results for their coursework.

Proposed Solution

The fix is straightforward. The durations list should only contain values for the activities, not for Origin:

activities = ['A', 'B', 'C', 'D']
durations = [2, 5, 4, 2]  # 4 values, one per activity — Origin is handled separately
predecessors = ['-', 'A', 'B', 'B,C']

cpm.add_activity('O', 0)
cpm.add_activities_relations(activities, durations, predecessors)

Additionally, I would like to add a ValueError guard inside add_activities_relations to validate that len(activities) == len(durations) == len(predecessors) before processing, so future mismatches raise a clear error rather than producing silent calculation bugs.

I will fix the README example and add the validation guard. Please assign this to me.

Labels: bug, documentation, good first issue, help wanted, GSSoC 2026

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions