Skip to content

feat: implement PERTMethod class with three-point estimation (O, M, P) - #5 - #10

Open
rajesh-puripanda wants to merge 2 commits into
kathan-majithia:mainfrom
rajesh-puripanda:feat/pert-three-point-estimation
Open

feat: implement PERTMethod class with three-point estimation (O, M, P) - #5#10
rajesh-puripanda wants to merge 2 commits into
kathan-majithia:mainfrom
rajesh-puripanda:feat/pert-three-point-estimation

Conversation

@rajesh-puripanda

Copy link
Copy Markdown

Summary

Implements core PERT (Program Evaluation and Review Technique) three-point estimation as described in issue #5.

Changes

Core PERT Logic (networkdiagram/networkdiagram.py):

  • Extended Node class with optimistic, most_likely, pessimistic fields, plus computed expected_time, variance, and std_deviation properties
  • Created PERTMethod class extending CriticalPathMethod with:
    • add_activity(name, optimistic, most_likely, pessimistic) — automatically computes Expected Time TE = (O + 4M + P) / 6
    • add_activities_relations(activities, O_list, M_list, P_list, predecessors) — bulk add with three-point estimates
    • get_expected_time(), get_variance(), get_std_deviation() per activity
    • get_project_variance(), get_project_std_deviation() — summed along critical path
    • find_critical_path() — uses expected times for critical path determination
    • network_summary() — displays O/M/P/TE/Variance/StdDev for each activity
    • display_pert_distribution() — grouped bar chart comparing O, M, P, and TE estimates via matplotlib
  • Bug fix: corrected off-by-one error in CriticalPathMethod.add_activities_relations()durations[i+1]durations[i] (first duration was previously skipped)

Exports (__init__.py):

  • Added PERTMethod and Node to package exports

Tests (tests/):

  • test_pert.py — 20 unit tests covering PERT formulas, variance/stddev calculations, critical path finding, project variance aggregation, and backward compatibility
  • test_smoke.py — end-to-end integration tests

Other:

  • Added .gitignore for Python cache (__pycache__/) and build artifacts

Usage Example

from networkdiagram import PERTMethod

pert = PERTMethod()
pert.add_activity('O')
pert.add_activity('A', optimistic=2, most_likely=4, pessimistic=6)
pert.add_activity('B', optimistic=3, most_likely=5, pessimistic=7)
pert.add_relation('A', '-')
pert.add_relation('B', 'A')
pert.find_probable_paths()
pert.find_critical_path()
pert.network_summary()

Verification
All 20 unit tests pass:

python -m unittest tests/test_pert.py -v
Existing CriticalPathMethod API is fully backward-compatible.

Closes #5

- Add optimistic, most_likely, pessimistic fields to Node class
  with computed expected_time, variance, and std_deviation properties
- Create PERTMethod class extending CriticalPathMethod with:
  - add_activity(name, optimistic, most_likely, pessimistic)
  - add_activities_relations bulk method for three-point estimates
  - get_expected_time, get_variance, get_std_deviation per activity
  - get_project_variance, get_project_std_deviation for critical path
  - display_pert_distribution() for Beta-PERT bar chart visualization
  - Overridden network_summary with PERT details
- Fix off-by-one bug in CriticalPathMethod.add_activities_relations
  (durations[i+1] -> durations[i])
- Add 20 unit tests covering formulas, pathfinding, project stats
- Add smoke tests for end-to-end PERT workflow
- Update __init__.py exports
@kathan-majithia

Copy link
Copy Markdown
Owner

Great work on this implementation, Rajesh!

The visual distribution chart is fantastic, and the base Expected Time calculations are solid.

However, I ran this locally against a test network with multiple critical paths and caught a crashing bug in find_critical_path.

  • If there are multiple paths, the script appends a list to an existing list of strings, creating a nested array (e.g., ['A', 'B', ['A', 'C']]).
  • When network_summary() or get_project_variance() iterates over this, it throws a TypeError: unhashable type: 'list'.
  • Could you please update the logic to properly handle multiple critical paths (perhaps by ensuring self.critical_path is always a list of lists, e.g., [['A', 'B'], ['A', 'C']]) and update your loops in network_summary and variance calculations to flatten or target the specific paths?
  • Also, make sure you pull the latest main branch so this code integrates cleanly with the new forward_pass() and backward_pass() features. Let me know when you've pushed the fix!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Core PERT Logic (Three-Point Estimation)

2 participants