Wire Neo4j heuristics into the search fitness function - #1731
Conversation
# Conflicts: # core/src/main/kotlin/org/evomaster/core/search/service/Statistics.kt
…b and cassandra heuristics
… from its result types
| * @param evaluationFailure whether the evaluation failed | ||
| */ | ||
| public Neo4jDistanceWithMetrics(double distance, int numberOfEvaluatedNodes, boolean evaluationFailure) { | ||
| if (distance < 0.0d || distance > 1.0d || Double.isNaN(distance)) { |
There was a problem hiding this comment.
hi @andyfelder16 .thx ;) but should first request @jgaleotti review, and, then, once that is completed, JP asks for my review. anyway, with a quick look here i can see the naming is confusing. see DistanceHelper for a definition of distance vs heuristic inside EM codebase
There was a problem hiding this comment.
Hi @arcuri82 , I am taking over the review. However, this is indeed a distance since it follows the same model as MongoDistanceWithMetrics, RedisDistanceWithMetrics, DynamoDbDistanceWithMetrics and CqlDistanceWithMetrics (i.e., Cassandra)
There was a problem hiding this comment.
if this is distance, why are we throwing an exception if greater than 1? this is confusing. if it is a normalized distance, then it should be explicitely called that, eg, double normalizedDistance
| * @param evaluationFailure whether the evaluation failed | ||
| */ | ||
| public Neo4jDistanceWithMetrics(double distance, int numberOfEvaluatedNodes, boolean evaluationFailure) { | ||
| if (distance < 0.0d || distance > 1.0d || Double.isNaN(distance)) { |
There was a problem hiding this comment.
Hi @arcuri82 , I am taking over the review. However, this is indeed a distance since it follows the same model as MongoDistanceWithMetrics, RedisDistanceWithMetrics, DynamoDbDistanceWithMetrics and CqlDistanceWithMetrics (i.e., Cassandra)
| metrics = new Neo4jDistanceWithMetrics(distance, graph.nodeCount(), false); | ||
| } catch (Exception e) { | ||
| SimpleLogger.uniqueWarn("Failed to compute Neo4j heuristic for query: " + query); | ||
| metrics = new Neo4jDistanceWithMetrics(1.0, graph.nodeCount(), true); |
There was a problem hiding this comment.
replace 1.0 with Neo4HeuristicsCalculator.MAX_NEO4J_DISTANCE = 1.0d
There was a problem hiding this comment.
the value of MAX_NEO4J_DISTANCE should be Double.MAX_VALUE instead of 1.0d
| .toList() | ||
|
|
||
| if (toMinimize.isNotEmpty()) { | ||
| fv.setExtraToMinimize(i, toMinimize) |
There was a problem hiding this comment.
this code is behind master
|
@andyfelder16 please update branch and fix conflicts |
| * @param evaluationFailure whether the evaluation failed | ||
| */ | ||
| public Neo4jDistanceWithMetrics(double distance, int numberOfEvaluatedNodes, boolean evaluationFailure) { | ||
| if (distance < 0.0d || distance > 1.0d || Double.isNaN(distance)) { |
There was a problem hiding this comment.
if this is distance, why are we throwing an exception if greater than 1? this is confusing. if it is a normalized distance, then it should be explicitely called that, eg, double normalizedDistance
| */ | ||
| public Neo4jDistanceWithMetrics(double distance, int numberOfEvaluatedNodes, boolean evaluationFailure) { | ||
| if (distance < 0.0d || distance > 1.0d || Double.isNaN(distance)) { | ||
| throw new IllegalArgumentException("distance must be between 0 and 1, but was " + distance); |
There was a problem hiding this comment.
a distance does not need to be within 0 and 1. if it is a normalized distance, then explicitely state so, eg, a normalized distance must be between 0 and 1,
| /** | ||
| * Creates a Neo4j heuristic result. | ||
| * | ||
| * @param distance normalized distance to satisfying the query, 0 meaning satisfied |
There was a problem hiding this comment.
any specific reason why Neo4j works on normalized distances?
| /** | ||
| * @return normalized distance to satisfying the query, 0 meaning satisfied | ||
| */ | ||
| public double getDistance() { |
There was a problem hiding this comment.
if normalized, then the name getDistance is confusing.
| try { | ||
| neo4jHandler.handle(it); | ||
| } catch (Exception e){ | ||
| SimpleLogger.error("FAILED TO HANDLE NEO4J COMMAND"); |
There was a problem hiding this comment.
could add the e.getMessage to the this error log
| * cannot compute a distance (for example when the evaluation throws) reports this value, so a failure | ||
| * never looks closer to satisfied than a genuine miss. | ||
| */ | ||
| public static final double MAX_NEO4J_DISTANCE = 1.0d; |
There was a problem hiding this comment.
why does Neo4J require this bound, where all other systems do not? note that normalizing distances do lose information. that is why in DistanceHelper there are a lot of different helper functions to deal then a maxed distance is Double.MAX_VALUE
arcuri82
left a comment
There was a problem hiding this comment.
approved by mistake, there are comments to address first
|
hi @arcuri82 , the term normalized came from the fact that the Neo4JHeuristicsCalculator returns a Truthness that is in the [0..1] range. The |
|
@jgaleotti what do you mean with |
|
@jgaleotti if the distance is computed from |
|
please @andyfelder16 remove the checks that constrain the Neo4J distance to be <1. Also, replace 1.0d with Double.MAX_VALUE as the MAX_NEO4J_DISTANCE |
…1 check on the distance
Last of the PRs splitting #1641, on top of #1580, #1672, #1647, #1697 and #1715, all of which are merged. It closes the chain: the Cypher queries the SUT runs have been captured since #1460, and this is what finally turns them into search guidance.
Neo4jHandlercollects the queries intercepted fromSession.run, reads the graph once per action rather than once per query, and scores each query against that snapshot. Only MATCH queries are scored; anything that does not parse as one, such as a write, is skippedNeo4jCommandWithDistanceandNeo4jDistanceWithMetricscarry the result to the DTOEnterpriseFitness.handleNeo4jHeuristicsfeeds the distances to the search, behind the newheuristicsForNeo4joption, and reports evaluation counts and the average number of nodes inspected throughStatisticsStatisticsTest, covering the scored path, a write being skipped, no driver, heuristics disabled, and a driver that cannot be reached