Search code examples
javaoptaplanner

Optaplanner Constraint Streams Join Problem Fact and Planning Entity


I am trying to join the planning entity and a problem fact in a constraint streams but my IDE throws an error on that: Cannot resolve method 'join(java.lang.Class<Edge>, org.optaplanner.core.api.score.stream.bi.BiJoiner<A,B>)'

My problem structure is very similar to the transportation problem. I have nodes and edges and want to calculate the quantity of the edges.

My main problem fact is:

class Node{
   UUID id;
   int itemsInInventory;
   ...
}

And the planning entity:

@PlanningEntity
class Edge{
   Node from;
   Node to; 
   @PlanningVariable
   int itemsTransported;

   getFromId(){return from.getId()}
   getToId(){return to.getId()}

}

The code of the constraint is:

public Constraint minimizeShortage(ConstraintFactory constraintFactory) {
    return constraintFactory.from(Node.class)
            .join(Edge.class, equal(Edge::getFromId, Edge::getId))
            ...
}

If I try to join the edges with the edges for example:

public Constraint minimizeShortage(ConstraintFactory constraintFactory) {
    return constraintFactory.from(Node.class)
            .join(Node, equal(Node:: getId, Node::getId)) //EDITED
            ...
}

This works without an error. Is the reason, that I try to join Nodes into the Edges on the Edge property in the Nodes? Is there another way to do what I want?


Solution

  • I have to say I do not understand how your latter example works:

    public Constraint minimizeShortage(ConstraintFactory constraintFactory) {
        return constraintFactory.from(Node.class)
            .join(Node, equal(Node:: getId, Edge::getId))
            ...
    }
    

    In this case, you are joining Node and another Node. The equal(...) joiner therefore needs to use Node on both sides, like so:

    public Constraint minimizeShortage(ConstraintFactory constraintFactory) {
        return constraintFactory.from(Node.class)
            .join(Node.class, equal(Node::getId, Node::getId))
            ...
    }
    

    Or, more shortly:

    public Constraint minimizeShortage(ConstraintFactory constraintFactory) {
        return constraintFactory.from(Node.class)
            .join(Node.class, equal(Node::getId))
            ...
    }
    

    This is also the reason why your first example does not compile:

    public Constraint minimizeShortage(ConstraintFactory constraintFactory) {
        return constraintFactory.from(Node.class)
            .join(Edge.class, equal(Edge::getFromId, Edge::getId))
            ...
    }
    

    In this case, you are joining Node with Edge, so the equal(...) joiner needs to use Node on the left and Edge on the right, like so:

    public Constraint minimizeShortage(ConstraintFactory constraintFactory) {
        return constraintFactory.from(Node.class)
            .join(Edge.class, equal(Node::getId, Edge::getFromId))
            ...
    }