Project.Solve#

Schedules a Project and accepts the scheduled dates as its baseline. Pass a ProjectData to load a project, or null to reschedule after Apply. The other read-only calls (Preview, Evaluate, SuggestAssignments and the rest) need a solved project.

For a one-shot run that keeps no state, use Engine.Schedule.

Signature#

public ScheduleResult Solve(ProjectData? data, SolveOptions options)

Synchronous and CPU-only. Changes the project's state.

Parameters#

Name Type Description
data ProjectData? Replacement data, or null to schedule the current state
options SolveOptions Subtree, analytics and reporting switches

Behavior#

  • A non-null data is deep-copied, validated, installed, scheduled and accepted. The previous data is discarded. Later changes to the caller's ProjectData don't reach the project. ProjectOptions.Validation decides whether invalid data is rejected or repaired.
  • null schedules the current state when it has unsolved edits. When the project is already solved with equal options, it returns the same cached result object without scheduling again. The cache key is the whole SolveOptions value, compared by value.

Tasks touched by successful Apply calls since the last solve appear in Updates as direct updates, even when the planner leaves them where the edit put them. A cyclic project returns unchanged dates and keeps those tasks pending.

The result's BaselineId names the accepted baseline. It changes only when the data or the dates change, so solving an unchanged state keeps it.

Returns#

The ScheduleResult. The project keeps the result as its baseline and shares it with clones. A later call can return the same object. Treat it as read-only, or call DeepClone() before modifying it.

Errors#

Error When
InputException data fails validation, or options.Subtree names an unknown or unscheduled task (Path == "subtree.task"). The previous state and cached result are kept.
ProjectException NeedsResync data is null after an Apply rejected an operation and no Solve(data, …) followed
ArgumentNullException options is null

Example#

Load a project, commit an edit and reschedule it.

using Plen;

var monday = Moment.FromYmdHm(2026, 8, 10, 8, 0) ?? throw new InvalidOperationException("invalid date");
var data = new ProjectData
{
    Tasks = [new TaskData(1) { StartDate = monday, Duration = 2.0 }],
};

var options = new SolveOptions();
var project = new Project();
var loaded = project.Solve(data, options);

// Nothing changed: the cached result comes back with the same baseline.
var again = project.Solve(null, options);
Console.WriteLine(again.BaselineId == loaded.BaselineId); // True

var changes = new SchedulingChanges();
changes.Tasks.Update.Add(new TaskUpdate(1) { Duration = 3.0 });
project.Apply(changes);

var result = project.Solve(null, options);
foreach (var update in result.Updates)
    Console.WriteLine($"task {update.Id}: {update.StartDate} .. {update.EndDate}"); // task 1: 2026-08-10 08:00 .. 2026-08-13 08:00