/**
   * Performs step C of the algorithm, as indicated on page xxx of CPS, with the modification that
   * X--W--Y is oriented as X-->W<--Y if W is *determined by* the sepset of (X, Y), rather than W
   * just being *in* the sepset of (X, Y).
   */
  public static void pcdOrientC(
      SepsetMap set, IndependenceTest test, Knowledge knowledge, Graph graph) {
    TetradLogger.getInstance().log("info", "Staring Collider Orientation:");

    List<Node> nodes = graph.getNodes();

    for (Node y : nodes) {
      List<Node> adjacentNodes = graph.getAdjacentNodes(y);

      if (adjacentNodes.size() < 2) {
        continue;
      }

      ChoiceGenerator cg = new ChoiceGenerator(adjacentNodes.size(), 2);
      int[] combination;

      while ((combination = cg.next()) != null) {
        Node x = adjacentNodes.get(combination[0]);
        Node z = adjacentNodes.get(combination[1]);

        // Skip triples that are shielded.
        if (graph.isAdjacentTo(x, z)) {
          continue;
        }

        List<Node> sepset = set.get(x, z);

        if (sepset == null) {
          continue;
        }

        List<Node> augmentedSet = new LinkedList<Node>(sepset);
        augmentedSet.add(y);

        if (test.determines(sepset, y)) {
          continue;
        }
        //
        if (!test.splitDetermines(sepset, x, z) && test.splitDetermines(augmentedSet, x, z)) {
          continue;
        }

        if (!isArrowpointAllowed(x, y, knowledge) || !isArrowpointAllowed(z, y, knowledge)) {
          continue;
        }

        graph.setEndpoint(x, y, Endpoint.ARROW);
        graph.setEndpoint(z, y, Endpoint.ARROW);

        TetradLogger.getInstance()
            .log("colliderOriented", SearchLogUtils.colliderOrientedMsg(x, y, z));
      }
    }

    TetradLogger.getInstance().log("info", "Finishing Collider Orientation.");
  }