EvaluateResult#
Every candidate of one Project.Evaluate or Project.EvaluateWith call, scored against one baseline. The call returns it; there's no other way to get one.
Declaration#
namespace Plen;
public sealed class EvaluateResult : IDeepCloneable<EvaluateResult>, IEquatable<EvaluateResult>
{
public required string BaselineId { get; set; }
public required Metrics Baseline { get; set; }
public List<CandidateResult> Candidates { get; set; } = [];
public EvaluateResult DeepClone();
public bool Equals(EvaluateResult? other);
}
Properties#
| Property | Type | Description |
|---|---|---|
BaselineId |
string |
Token of the accepted baseline the candidates were scored against. |
Baseline |
Metrics |
Metrics of the reference state. Every delta in it is 0. |
Candidates |
List<CandidateResult> |
One result per candidate, in input order. |
BaselineId#
public required string BaselineId { get; set; }
The project's accepted baseline token at the time of the call. It's always set, and it stays the accepted state's token when EvaluateOptions.ClearFirst is true. Pass it as BaselineId in the SchedulingChanges of the candidate you commit, so Project.Apply rejects the commit if the project changed in between.
Baseline#
public required Metrics Baseline { get; set; }
The reference every candidate is compared with: the accepted state, or its cleared copy when ClearFirst is true. Deltas are 0 by definition. Baseline.Cost is the baseline's own cost, so a candidate with a lower CandidateResult.Cost scores better than leaving the plan as it is.
Candidates#
public List<CandidateResult> Candidates { get; set; } = [];
One CandidateResult per input candidate, in the order of the candidates argument, with sequential and parallel execution alike. A failed candidate stays in the list with its Error set and no metrics; a call-level error throws instead (see Project.Evaluate).
Methods#
DeepClone#
public EvaluateResult DeepClone()
Returns a copy that shares no list or nested object with this one.
Equals#
public bool Equals(EvaluateResult? other)
public override bool Equals(object? obj)
Value equality: BaselineId and Baseline are equal and Candidates match element by element. GetHashCode is consistent with it.
ToString#
public override string ToString()
Returns a readable dump of all properties, for logging.
Example#
Score two staffing options for task 1, then commit the one with the lowest cost:
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 }],
Resources = [new ResourceData { Id = "dev1" }, new ResourceData { Id = "dev2" }],
};
var project = new Project();
project.Solve(data, new SolveOptions());
var candidates = new List<Candidate>();
foreach (var dev in new[] { "dev1", "dev2" })
{
var changes = new SchedulingChanges();
changes.Assignments.Add.Add(new AssignmentData { Task = 1, Resource = dev, Value = 1.0 });
candidates.Add(new Candidate { Id = dev, Changes = changes });
}
var result = project.Evaluate(candidates, new EvaluateOptions());
Console.WriteLine($"baseline cost: {result.Baseline.Cost}");
CandidateResult? best = null;
foreach (var c in result.Candidates)
{
if (c.Error is not null || c.Cost is null)
continue;
if (best is null || c.Cost < best.Cost)
best = c;
}
if (best is not null)
{
var chosen = candidates.First(c => c.Id.Equals(best.Id)).Changes;
chosen.BaselineId = result.BaselineId;
project.Apply(chosen);
project.Solve(null, new SolveOptions());
}
Related#
Project.Evaluate- the call that returns itCandidateResult- the score of one candidateMetrics- the baseline and stage metricsEvaluateOptions- the options of the call- Evaluating alternatives - comparing candidates and committing the winner