Issue1205

Title match in bounds for Weighted and Const evaluator
Priority feature Status reviewing
Superseder Nosy List jendrik, malte, simon
Assigned To Keywords
Optional summary

Created on 2026-02-17.14:49:59 by simon, last changed by simon.

Messages
msg12091 (view) Author: simon Date: 2026-07-15.14:37:21
The change can break some calls that use to find a solution.
concrete example:

./fast-downward.py --build debug ~/DOWNWARD_BENCHMARKS/blocks/probBLOCKS-4-1.pddl  --search "eager_greedy([weight(blind(),-1)])"

In the current main this would find a solution, in the PR it would halt with an Usage error.

I have doubts that anyone was seriously using calls like this...
msg12090 (view) Author: simon Date: 2026-07-15.12:27:37
For now I suggest that we disallow negative weights.

They can cause assertions to trigger in the sum and max evaluator.
Concrete examples:

./fast-downward.py --build debug --keep-sas-file --sas-file sas-from-arguments ~/DOWNWARD_BENCHMARKS/blocks/probBLOCKS-4-1.pddl  --search "astar(max([weight(blind(),-1)]),verbosity=debug)"

./fast-downward.py --build debug --keep-sas-file --sas-file sas-from-arguments ~/DOWNWARD_BENCHMARKS/blocks/probBLOCKS-4-1.pddl  --search "astar(sum([weight(blind(),-1)]),verbosity=debug)"

./fast-downward.py --build debug --keep-sas-file --sas-file sas-from-arguments ~/DOWNWARD_BENCHMARKS/blocks/probBLOCKS-4-1.pddl  --search "eager_wastar([blind()], w=-1 ,verbosity=debug)"

./fast-downward.py --build debug --keep-sas-file --sas-file sas-from-arguments ~/DOWNWARD_BENCHMARKS/blocks/probBLOCKS-4-1.pddl  --search "lazy_wastar([blind()], w=-1 ,verbosity=debug)"

I made a tiny PR (+8,-3) where the weight for weighted evaluator, for Eager weighted A* search and for (Weighted) A* search (lazy) is bound to be non-negative.

It is ready to be reviewed: https://github.com/aibasel/downward/pull/294


This avoids the assertions from the 4 examples and produces a nicer Usage error instead. So we get right after reading the input something like:
"""
Traceback:
  Constructing parsed object
  -> Constructing feature 'astar': astar(max([weight(blind(),-1)]),verbosity=debug)
  -> Constructing argument 'eval'
  -> Constructing feature 'max': max([weight(blind(),-1)])
  -> Constructing argument 'evals'
  -> Constructing list
  -> Constructing element 0
  -> Constructing feature 'weight': weight(blind(),-1)
  -> Constructing argument 'weight'
  -> Constructing value with bounds
  -> Checking bounds

Value is not in bounds.
Usage error occurred.
Peak memory: 46176 KB
search exit code: 33
"""

instead of starting the search and getting something like

"""
downward: /home/dolsim00/downward/src/search/evaluators/max_evaluator.cc:19: virtual int max_evaluator::MaxEvaluator::combine_values(const std::vector<int>&): Assertion `value >= 0' failed.
Peak memory: 46176 KB
caught signal 6 -- exiting
search exit code: -6

Driver aborting after search
INFO     Planner time: 0.30s
"""
msg12009 (view) Author: simon Date: 2026-02-17.15:30:10
[Malte on discord]

Negative values are not allowed to be returned by evaluators, and the current code cannot fully support them. For example, heuristics internally use the values "-1" for dead end and "-2" for "value unknown". They contain an assertion that we can never return a heuristic value other than non-negative values or "-1" (dead end), which at some point is then converted to max integer.
I haven't checked this thoroughly, but it's possible our open lists currently work for negative values, but this is by accident, not by design. 
It is worth reconsidering this because I think someone might want to use general linear expressions including negative coefficients (both as in 5 h_1 - 2 h_2 and as in h_1 + h_2 - 3).
But if we want to do this, it would need to be a conscious decision that we now expect open lists and search algorithms to handle such negative values, and we should be clear about where they are allowed. (For example, are they allowed in g values under cost transformations?)
msg12005 (view) Author: simon Date: 2026-02-17.14:49:59
The weighted evaluator accepts negative values but the constant evaluator does not.
However, you can basically build the ConstEvaluator for any negative number with 'weight(const(42), -1)'.
I think we should allow negative values for the ConstEvaluator, too.
Alternatively, we could restrict the WeightedEvaluator to non-negative values.
The current mix form is weird.
I am in favour of giving the user more flexibility and allow negative values for the ConstEvaluator.
History
Date User Action Args
2026-07-15 14:37:21simonsetmessages: + msg12091
2026-07-15 12:27:37simonsetmessages: + msg12090
status: chatting -> reviewing
title: mismatch in bounds for Weighted and Const evaluator -> match in bounds for Weighted and Const evaluator
2026-02-17 15:30:39simonsetnosy: + malte, jendrik
2026-02-17 15:30:10simonsetmessages: + msg12009
2026-02-17 14:49:59simoncreate