private boolean ac3() {
        Deque<DimensionRenamer.Arc> workList = new ArrayDeque<>(constraints.keySet());
        while ( ! workList.isEmpty()) {
            DimensionRenamer.Arc arc = workList.pop();
            iterations++;
            if (revise(arc)) {
                if (possibleAssignments.get(arc.from).isEmpty()) return false;

                for (DimensionRenamer.Arc constraint : constraints.keySet()) {
                    if (arc.from.equals(constraint.to) && !arc.to.equals(constraint.from))
                        workList.add(constraint);
                }
            }
            if (iterations > maxIterations) return false;
        }
        return true;
    }
Try the solve the constraint problem given in the arguments, and put the result in renames.

This is done by performing iterative arc consistency until we have found a solution.
After an initial iteration, the dimensions will have multiple
valid values. Find a single valid assignment by iteratively locking one
dimension after another, and running the arc consistency algorithm
multiple times.

This requires having constraints that result in an absolute ordering:
equal, lessThan and greaterThan do that, but not necessarily notEqual
If that is needed, the algorithm needs to be adapted with a backtracking
(tree) search

@return the solution in the form of the renames to perform
model-integration/src/main/java/ai/vespa/rankingexpression/importer/NamingConstraintSolver.java