[Canonical page](<https://docs.dhtmlx.com/planning-engine/java/api/project-evaluate/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# Project#evaluate

Scores alternative change sets against the solved baseline of a [`Project`](<https://docs.dhtmlx.com/planning-engine/java/api/project/project.md>). Doesn't modify the project. Use it to compare options, such as which resource should take a task, before committing one with [`apply`](<https://docs.dhtmlx.com/planning-engine/java/api/project-apply.md>). Needs a solved project.

## Signature

```java
public EvaluateResult evaluate(Vec<Candidate> candidates, EvaluateOptions options)
public EvaluateResult evaluate(Collection<Candidate> candidates, EvaluateOptions options)
```

Synchronous and CPU-only. Read-only, but not synchronized: serialize calls on one instance. The `Collection` overload copies the candidates into a [`Vec`](<https://docs.dhtmlx.com/planning-engine/java/api/support/vec.md>), so `List.of(...)` works.

## Parameters

| Name | Type | Description |
|---|---|---|
| `candidates` | `Vec<`[`Candidate`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/candidate.md>)`>` | The change sets to score. Must not be `null` |
| `options` | [`EvaluateOptions`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/evaluate-options.md>) | Baseline check, leveling stage, focus tasks and `clearFirst`. Must not be `null` |

## Behavior

Each candidate runs on a disposable copy of the reference state (the baseline, or its cleared copy with `options.clearFirst`):

1. `apply` the candidate's changes.
2. `solve(null, …)` and measure the scheduled stage.
3. With `options.level` set, `level` with those options and measure the leveled stage.

Every candidate starts from the reference state, never from the previous candidate. A failure inside one candidate goes into that candidate's `error` and doesn't fail the call. The result has scores, not dates.

## Returns

An [`EvaluateResult`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/evaluate-result.md>) with the baseline metrics and one result per candidate, in input order.

## Errors

All exceptions are unchecked.

| Error | When |
|---|---|
| [`ProjectException`](<https://docs.dhtmlx.com/planning-engine/java/api/errors/project-exception.md>) with `code == ProjectError.NO_BASELINE` | The project is unsolved, including after `apply` |
| `ProjectException` with `code == ProjectError.STALE_BASELINE` | `options.baselineId` or any candidate's `changes.baselineId` doesn't name the current baseline |
| [`InputException`](<https://docs.dhtmlx.com/planning-engine/java/api/errors/input-exception.md>) | An unknown task in `focus` (path `focus[i]`); `options.level` is invalid for the baseline |
| `NullPointerException` | `candidates` or `options` is `null` |

## evaluateWith

```java
public EvaluateResult evaluateWith(
    Vec<Candidate> candidates, EvaluateOptions options, Execution execution)
public EvaluateResult evaluateWith(
    Collection<Candidate> candidates, EvaluateOptions options, Execution execution)
```

Same as `evaluate`, with a choice of [`Execution`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/execution.md>). `Execution.sequential()` is what `evaluate` uses. `Execution.parallel(threads)` scores candidates on a private fixed thread pool of `min(threads, candidates.size())` workers (`null` threads means `availableProcessors()`). With one worker or fewer, candidates run on the calling thread. The pool shuts down before the call returns, and the caller blocks until every candidate is done. Peak memory is one candidate copy per worker.

The results are identical to `evaluate` and keep input order. A call-level error is the first one in input order, and later candidates may already have run. Errors are the same as for `evaluate`, plus `NullPointerException` for a `null` `execution`.

## Example

Compare leaving the plan as it is with moving task `B` to an idle resource.

```java
import java.util.List;
import org.dhtmlx.plen.*;

public class EvaluateExample {
  public static void main(String[] args) throws Exception {
    Moment monday = Moment.fromYmdHm(2026, 8, 10, 8, 0);
    ProjectData data = new ProjectData()
        .withTasks(List.of(
            new TaskData(Id.str("A")).withStartDate(monday).withDuration(2.0),
            new TaskData(Id.str("B")).withStartDate(monday).withDuration(2.0)))
        .withResources(List.of(
            new ResourceData().withId(Id.str("dev1")),
            new ResourceData().withId(Id.str("dev2"))))
        .withAssignments(List.of(
            new AssignmentData().withId(Id.str("aA")).withTask(Id.str("A"))
                .withResource(Id.str("dev1")).withValue(1.0),
            new AssignmentData().withId(Id.str("aB")).withTask(Id.str("B"))
                .withResource(Id.str("dev1")).withValue(1.0)));

    Project project = new Project();
    project.solve(data, new SolveOptions());

    SchedulingChanges toDev2 = new SchedulingChanges();
    toDev2.assignments.update.add(
        new AssignmentUpdate(Id.str("aB")).withResource(Patch.of(Id.str("dev2"))));

    List<Candidate> candidates = List.of(
        new Candidate().withId(Id.str("stay")).withChanges(new SchedulingChanges()),
        new Candidate().withId(Id.str("dev2")).withChanges(toDev2));
    EvaluateResult result = project.evaluate(candidates, new EvaluateOptions());

    for (CandidateResult candidate : result.candidates) {
      System.out.println(candidate.id + ": cost " + candidate.cost); // stay: cost 2.0, dev2: cost 0.0
    }
  }
}
```

## Related

- [`Candidate`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/candidate.md>) - one change set to score
- [`EvaluateOptions`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/evaluate-options.md>) - baseline check, leveling stage and focus tasks
- [`EvaluateResult`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/evaluate-result.md>) - baseline metrics and one result per candidate
- [`Execution`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/execution.md>) - sequential or parallel scoring with evaluateWith
- [Evaluating alternatives](<https://docs.dhtmlx.com/planning-engine/java/resources-and-assignment/evaluating-alternatives.md>) - comparing candidates and committing the winner
