Critical#

The critical path of a schedule, as the ids of its critical tasks and links. It isn't built by hand. Read it from Analytics::critical_path, which is Some when the run asked for it with AnalyticsOptions::critical_path. For when a task or link counts as critical, see Critical path and slack.

Declaration#

#[derive(Clone, Debug, PartialEq)]
pub struct Critical {
    pub tasks: Vec<Id>,
    pub links: Vec<Id>,
}

With the serde feature, it also implements Serialize and Deserialize.

Fields#

Name Type Description
tasks Vec<Id> Ids of the critical tasks, summaries included. Each task appears once. Empty when no task is critical.
links Vec<Id> Ids of the critical links. Each link appears once. Empty when no link is critical.

Serialization#

With the serde feature, a Critical serializes as:

{ "tasks": ["design", "build"], "links": ["l1"] }

Example#

Schedule two tasks in sequence and a shorter one in parallel, then print the critical path.

use plen_core::{
    schedule, AnalyticsOptions, DateTime, LinkData, LinkType, ProjectData, SolveOptions, TaskData,
};

fn task(id: &str, start: DateTime, duration: f64) -> TaskData {
    let mut task = TaskData::new(id);
    task.start_date = Some(start);
    task.duration = Some(duration);
    task
}

fn fs(id: &str, source: &str, target: &str) -> LinkData {
    LinkData {
        id: id.into(),
        source: source.into(),
        target: target.into(),
        link_type: LinkType::Fs,
        lag: 0.0,
        lag_unit: None,
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let monday = DateTime::from_ymd_hm(2026, 8, 10, 8, 0).ok_or("invalid date")?;
    let data = ProjectData {
        tasks: vec![
            task("design", monday, 2.0),
            task("build", monday, 3.0),
            task("docs", monday, 1.0),
        ],
        links: vec![fs("l1", "design", "build"), fs("l2", "design", "docs")],
        ..Default::default()
    };

    let options = SolveOptions {
        analytics: AnalyticsOptions {
            critical_path: true,
            ..Default::default()
        },
        ..Default::default()
    };
    let result = schedule(data, &options)?;

    let analytics = result.analytics.ok_or("analytics not requested")?;
    let critical = analytics.critical_path.ok_or("critical path not available")?;
    for id in &critical.tasks {
        println!("critical task: {id}"); // design, build
    }
    for id in &critical.links {
        println!("critical link: {id}"); // l1
    }
    Ok(())
}