/** Resets this graph before locating a path */
  private boolean reset(List<BusinessTable> requiredTables) {
    try {
      // reset required tables and nodes
      this.requiredTables = requiredTables;
      if (needsReset) { // Don't need to reset first-time through
        if (this.searchStack != null) {
          this.searchStack.clear();
        }

        // Clear required-status from nodes
        for (Node n : nodes) {
          n.clearRequirement();
        }

        // Clear required-status from arcs
        for (Arc a : arcs) {
          a.clearRequirement();
        }
      } else {
        this.needsReset = true;
      }

      // initialize nodes
      for (Node n : nodes) {
        if (requiredTables.contains(n.getTable())) {
          n.setRequirement(true);
        }
      }

      return true;
    } catch (ConsistencyException cx) {
      logger.debug("failed to reset", cx);
      return false;
    }
  }
Example #2
0
 public JSONObject asJSONTreeAux(ConcurrentHashMap<DomainConcept, DomainConcept> written) {
   JSONObject jsonObj = new JSONObject();
   try {
     jsonObj.put("class", "ClassModel");
     jsonObj.put("id", id);
     if (written.contains(this)) {
       return jsonObj;
     }
     written.put(this, this);
     if (getHasArcs() != null) {
       JSONArray jsonHasArcs = new JSONArray();
       for (Arc row : getHasArcs()) {
         jsonHasArcs.put(row.asJSONTreeAux(written));
       }
       jsonObj.put("hasArcs", jsonHasArcs);
     }
     if (getHasPropertySet() != null) {
       jsonObj.put("hasPropertySet", getHasPropertySet().asJSONTreeAux(written));
     }
     jsonObj.put("id", getId());
     if (getHasDomainNodes() != null) {
       jsonObj.put("hasDomainNodes", getHasDomainNodes().asJSONTreeAux(written));
     }
     written.remove(this);
   } catch (Exception e1) {
     logWriter.error("Error in marshalling to JSON ", e1);
   }
   return jsonObj;
 }
  private void dumpStateToLog() {
    if (logger.isDebugEnabled()) {
      logger.debug("-------------------------------------------------");

      for (Arc arc : arcs) {
        if (arc.isRequired()) {
          logger.debug(arc + "-> Yes");
        } else if (arc.isNotRequired()) {
          logger.debug(arc + "-> No");
        } else {
          logger.debug(arc + "-> ?");
        }
      }

      for (Node n : nodes) {
        if (n.isRequired()) {
          logger.debug(n + "-> Yes");
        } else if (n.isNotRequired()) {
          logger.debug(n + "-> No");
        } else {
          logger.debug(n + "-> ?");
        }
      }

      logger.debug("=================================================");
    }
  }
  /** Calculates graph validity */
  private boolean isValid(PathType searchTechnique) {
    // remove all arcs from queue
    extendedNodeQueue.clear();

    // initialize node queue with all nodes in graph
    basicNodeQueue.clear();
    basicNodeQueue.addAll(nodes);

    try {
      // check for all search technique
      if (searchTechnique == PathType.ALL) {
        for (Node n : nodes) {
          n.setRequirement(true);
        }
        for (Arc a : arcs) {
          a.setRequirement(true);
        }
      }

      // start by making initial graph consistent
      propagate();

      // search to test assigning a requirement setting
      // to tables not yet determined
      search(searchTechnique);

      return true;
    } catch (ConsistencyException cx) {
      logger.debug("failed to validate", cx);
      return false;
    }
  }
Example #5
0
 @Override
 public int compareTo(Object o) {
   Arc arc = (Arc) o;
   if (this.getBegin() == arc.getBegin()) {
     return this.getEnd() - arc.getBegin();
   }
   return this.getBegin() - arc.getBegin();
 }
 public void deleteArc(Arc arcOfElt) {
   for (int i = 0; i < exits.length; i++) {
     Arc exit = exits[i];
     if (exit != null && exit.equals(arcOfElt)) {
       exits[i] = null;
     }
   }
 }
Example #7
0
 // Methods
 public boolean ContainsOnEdge(Cartesian p) {
   for (Arc arc : this.getArcList()) {
     if (arc.ContainsOnEdge(p)) {
       return true;
     }
   }
   return false;
 }
 public List<E> getStations() {
   Set<E> stations = new LinkedHashSet<>();
   for (Arc<E> arc : arcs) {
     stations.add(arc.getStart());
     stations.add(arc.getEnd());
   }
   return new ArrayList<>(stations);
 }
Example #9
0
  @Override
  public void setup() {
    setSize(800, 600);

    arc.setFillColor(new RGBColor(0.3, 0.7, 0.3));
    arc.setStrokeColor(new RGBColor(0.5, 0.9, 0.5));
    arc.setStrokeWidth(10);
    addObject(arc);
  }
Example #10
0
 /**
  * Determines if a transition is enabled in this marking
  *
  * @param transition - transition to be checked
  * @return true if transition is enabled in the marking, otherwise false
  */
 public boolean isEnabled(Transition transition) {
   boolean isEnabled = true;
   lock.readLock().lock();
   try {
     for (Arc arc : transition.getConnectedArcs()) {
       if (arc.isPlaceToTransition()) {
         if (arc.getReset()) { // reset arc is always fireable
           continue; // but can be blocked by other arcs
         } else {
           if (!arc.getInhibitory()) {
             if (getTokens(arc.getPlaceNode()) < arc.getMultiplicity()) { // normal arc
               isEnabled = false;
               break;
             }
           } else {
             if (getTokens(arc.getPlaceNode()) >= arc.getMultiplicity()) { // inhibitory arc
               isEnabled = false;
               break;
             }
           }
         }
       }
     }
   } finally {
     lock.readLock().unlock();
   }
   return isEnabled;
 }
Example #11
0
 public void REinit() {
   Arc a;
   for (int i = 0; i < this.ListeArcs.size(); i++) {
     a = this.ListeArcs.elementAt(i);
     a.etat = 'r';
     a.nbre_veh = 0;
     for (int j = 0; j < a.ListeCellules.size(); j++) {
       a.ListeCellules.elementAt(j).oqp = false;
     }
   }
   // demarrer toutes les sources:
   for (int i = 0; i < this.ListeDesSources.size(); i++) {
     this.ListeDesSources.elementAt(i).demarrer_source();
   }
 }
    Solution(
        List<Arc> arcs,
        int rating,
        List<SearchDirection> searchPath,
        List<Arc> searchArcs,
        boolean partial) {
      this.rating = rating;
      this.searchPath = searchPath;
      this.searchArcs = searchArcs;
      this.partial = partial;

      this.solutionValues = new LinkedList<Boolean>();
      for (Arc a : arcs) {
        solutionValues.add(a.isRequired());
      }
    }
  /**
   * Attempts to assign an arc to a given requirement status and returns true if consistency may
   * still be possible
   */
  private boolean attemptArcAssignment(Arc arc, SearchDirection direction) {
    // initialize search stack for roll back
    pushSearchStack();

    // try to assign value to element and propagate changes
    // to other elements. If propagation fails, rollback changes
    try {
      if (logger.isDebugEnabled()) {
        logger.debug("Attempting move - Direction[" + direction + "], Arc[" + arc + "]");
      }
      arc.setRequirement((direction == SearchDirection.LEFT) ? false : true);
      propagate();

      if (logger.isDebugEnabled()) {
        logger.debug("Move succeeded - State after move");
        dumpStateToLog();
      }

      return true;
    } catch (ConsistencyException cx) {
      logger.debug("Move failed");
      popSearchStack();
      return false;
    }
  }
Example #14
0
 public boolean canBeUnfired(Transition transition) {
   boolean canBeUnfired = true;
   lock.readLock().lock();
   try {
     for (Arc arc : transition.getConnectedArcs()) {
       if (!arc.isPlaceToTransition()) {
         if (getTokens(arc.getPlaceNode()) < arc.getMultiplicity()) {
           canBeUnfired = false;
           break;
         }
       }
     }
   } finally {
     lock.readLock().unlock();
   }
   return canBeUnfired;
 }
  /**
   * Calculates and returns a path that satisfies the required tables list or null if one cannot be
   * found
   *
   * @param requiredTables Tables that are required to be in path
   * @return Path with smallest number of relationships to ensure all required tables are included
   */
  public Path getPath(PathType searchTechnique, List<BusinessTable> requiredTables) {
    // if reset works and validity check passes, build path
    if (reset(requiredTables) && isValid(searchTechnique)) {
      logger.debug("Path determined sucessfully");

      Path path = new Path();
      for (Arc arc : arcs) {
        if (arc.isRequired()) {
          if (logger.isDebugEnabled()) {
            logger.debug("Arc selected for path: " + arc);
          }
          path.addRelationship(arc.getRelationship());
        } else if (logger.isDebugEnabled()) {
          logger.debug(
              "Arc not used for path: Requirement Known["
                  + arc.isRequirementKnown()
                  + "], Required["
                  + arc.isRequired()
                  + "]");
        }
      }

      if (logger.isDebugEnabled()) {
        for (Node n : nodes) {
          logger.debug(
              "Node selection state: Requirement Known["
                  + n.isRequirementKnown()
                  + "], Required["
                  + n.isRequired()
                  + "]");
        }
      }
      if (path.size() > 0) {
        return path;
      }
    }

    return null;
  }
 //	Todos os arcos: Gera o resultado a partir de um objeto da classe Documento,
 //              	explicitando as relacoes entre os arcos em forma de Strings
 public void execute(CommandAllArcs command)
     throws ParserConfigurationException, SAXException, IOException, SQLException,
         ClassNotFoundException {
   if (this.filePrint) {
     this.context.addResult("Using file " + command.getFile());
     this.context.addResult("");
   }
   Expansor expansor = this.getDTS(command);
   Vector<Arc> documentArcs = new Vector<Arc>();
   Vector<Arc> filteredArcs = new Vector<Arc>();
   for (int i = 0; documentSet.size() > i; i++) {
     documentArcs.clear();
     filteredArcs.clear();
     if (this.filePrint)
       this.context.addResult(
           "Arcs from " + ((XmlDocument) documentSet.get(i)).getDocumentName() + ": ");
     documentArcs =
         ((XmlDocument) documentSet.get(i)).getArcs(expansor.getInicialDocument(this.base));
     filteredArcs = expansor.getFilteredArcs(documentArcs, this.arcsFilter);
     for (int j = 0; filteredArcs.size() > j; j++) {
       Arc arc = filteredArcs.get(j);
       if (this.filePrint)
         this.context.addResult(
             "Exist arc between "
                 + arc.getLabelFrom()
                 + " ("
                 + arc.getNodesFrom().size()
                 + ") and "
                 + arc.getLabelTo()
                 + " ("
                 + arc.getNodesTo().size()
                 + ")");
     }
     if (this.filePrint) this.context.addResult("");
     addArcs(filteredArcs);
   }
 }
Example #17
0
 /** method to marshall data from caching layer object to JSON * */
 public JSONObject asJSON() {
   JSONObject jsonObj = new JSONObject();
   try {
     jsonObj.put("class", "ClassModel");
     jsonObj.put("id", id);
     if (getHasArcs() != null) {
       JSONArray jsonHasArcs = new JSONArray();
       for (Arc row : getHasArcs()) {
         jsonHasArcs.put(row.getId());
       }
       jsonObj.put("hasArcs", jsonHasArcs);
     }
     if (getHasPropertySet() != null) {
       jsonObj.put("hasPropertySet", getHasPropertySet().getId());
     }
     jsonObj.put("id", getId());
     if (getHasDomainNodes() != null) {
       jsonObj.put("hasDomainNodes", getHasDomainNodes().getId());
     }
   } catch (Exception e1) {
     logWriter.error("Error in marshalling to JSON ", e1);
   }
   return jsonObj;
 }
Example #18
0
 public void undoFire(Transition transition) {
   lock.writeLock().lock();
   try {
     if (canBeUnfired(transition)) {
       for (Arc arc : transition.getConnectedArcs()) {
         if (!arc.isPlaceToTransition()) {
           int tokens = getTokens(arc.getPlaceNode());
           setTokens(arc.getPlaceNode(), tokens - arc.getMultiplicity());
         } else {
           int tokens = getTokens(arc.getPlaceNode());
           setTokens(arc.getPlaceNode(), tokens + arc.getMultiplicity());
         }
       }
     }
   } finally {
     lock.writeLock().unlock();
   }
 }
 public void specificArc(CommandXPathPlus command)
     throws ParserConfigurationException, SAXException, IOException, SQLException,
         ClassNotFoundException {
   if (this.filePrint) {
     this.context.addResult("Using file " + command.getFile());
     this.context.addResult("");
   }
   Expansor expansor = this.getDTS(command);
   Vector<Arc> documentArcs = new Vector<Arc>();
   Vector<Arc> filteredArcs = new Vector<Arc>();
   for (int i = 0; documentSet.size() > i; i++) {
     documentArcs.clear();
     filteredArcs.clear();
     if (this.filePrint)
       this.context.addResult(
           "Arcs from " + ((XmlDocument) documentSet.get(i)).getDocumentName() + ": ");
     documentArcs =
         ((XmlDocument) documentSet.get(i))
             .getArcs(
                 expansor.getInicialDocument(
                     this.startpoint == null ? StartPoint.INSTANCE : this.startpoint.getBase()));
     filteredArcs = expansor.getFilteredArcs(documentArcs, this.arcsFilter);
     for (int j = 0; filteredArcs.size() > j; j++) {
       Arc arc = filteredArcs.get(j);
       if (arc.getLabelFrom().equalsIgnoreCase(command.getElement())
           || (arc.getLabelTo().equalsIgnoreCase(command.getElement()))) {
         if (this.filePrint)
           this.context.addResult(
               "Exist arc between "
                   + arc.getLabelFrom()
                   + " ("
                   + arc.getNodesFrom().size()
                   + ") and "
                   + arc.getLabelTo()
                   + " ("
                   + arc.getNodesTo().size()
                   + ")");
       }
     }
     if (this.filePrint) this.context.addResult("");
     addArcs(filteredArcs);
   }
 }
  /**
   * Performs work of propagating changes from source nodes to target nodes until consistency is
   * reached
   *
   * @throws ConsistencyException When current graph cannot be made consistent
   */
  private void propagate() throws ConsistencyException {
    logger.debug("Beginning propagation");

    // first prune all non-required nodes
    for (Node n : nodes) {
      n.prune();
    }

    // process until queues are empty
    while (basicNodeQueue.size() > 0 || extendedNodeQueue.size() > 0) {

      // process basic node consistency enforcement because it's
      // faster than the extended arc propagation checks
      if (basicNodeQueue.size() > 0) {
        Node source = (Node) basicNodeQueue.remove();

        // check if source node is bound to a requirement setting
        // before processing arcs
        if (source.isRequirementKnown()) {

          // get list of arcs originating at node
          List<Arc> sourceArcs = source.getArcs();
          for (Arc arc : sourceArcs) {
            Node target = (arc.getLeft() == source) ? arc.getRight() : arc.getLeft();

            // if source is not required, arc is not required and
            // we can try and prune the target
            if (source.isNotRequired()) {
              arc.setRequirement(false);
              target.prune();
            }
          }
        }
      } else {
        // process extended enforcement of arc constraints on altered nodes
        // since we need to make sure that any node that is connected already
        Node source = (Node) extendedNodeQueue.remove();

        // enforce arc constraints on nodes
        List<Arc> sourceArcs = source.getArcs();
        for (Arc arc : sourceArcs) {
          arc.propagate(source);
        }
      }
    }

    // build required nodes list
    List<Node> requiredNodes = new LinkedList<Node>();
    for (Node n : nodes) {
      if (n.isRequired()) {
        requiredNodes.add(n);
      }
    }

    // make sure all required nodes can reach one another before returning
    // to ensure consistency
    if (requiredNodes.size() > 1) {
      List<Node> targetList = new LinkedList<Node>(requiredNodes);
      Node start = requiredNodes.remove(0);
      if (!start.canReachAllNodes(targetList)) {
        logger.debug(
            "Arc propagation completed, but not all targets could be reached from first node");
        throw new ConsistencyException(start);
      }
    }

    logger.debug("Propagation completed successfully");
  }
Example #21
0
 /**
  * Fires a transition in this marking. Changes this marking.
  *
  * @param transition transition to be fired in the marking
  * @return false if the specified transition was not enabled, otherwise true
  */
 public boolean fire(Transition transition) {
   boolean success;
   lock.writeLock().lock();
   try {
     if (isEnabled(transition)) {
       for (Arc arc : transition.getConnectedArcs()) {
         if (arc.isPlaceToTransition()) {
           int tokens = getTokens(arc.getPlaceNode());
           if (!arc.getInhibitory()) { // inhibitory arc doesnt consume tokens
             if (arc.getReset()) { // reset arc consumes them all
               setTokens(arc.getPlaceNode(), 0);
             } else {
               setTokens(arc.getPlaceNode(), tokens - arc.getMultiplicity());
             }
           }
         } else {
           int tokens = getTokens(arc.getPlaceNode());
           setTokens(arc.getPlaceNode(), tokens + arc.getMultiplicity());
         }
       }
       success = true;
     } else {
       success = false;
     }
   } finally {
     lock.writeLock().unlock();
   }
   return success;
 }
Example #22
0
  // Not used. Could be implemented in a better way
  void organizeNetGraphically() {
    int thresholdXDistanceApart = 100;
    int thresholdYDistanceApart = 30;
    double currentX;
    double currentY;
    int size = newTransitions.size();
    // otherwise there are no transitons to seperate from each other
    if (size > 1) {
      boolean madeAMove = true;
      while (madeAMove) {
        madeAMove = false;
        /*
         * for(int i = 0; i < size-1; i++){ double prevX =
         * newTransitions.get(i).getPositionX(); double prevY =
         * newTransitions.get(i).getPositionY(); for(int j = i+1;
         * j<size; j++){ currentX =
         * newTransitions.get(j).getPositionX(); currentY =
         * newTransitions.get(j).getPositionY(); if((currentX - prevX) >
         * -thresholdXDistanceApart && Math.abs(currentY - prevY) <
         * thresholdYDistanceApart){
         * newTransitions.get(j).setPositionX(-thresholdXDistanceApart +
         * prevX); System.out.println("shifting" +
         * newTransitions.get(i).getId() + ": " +
         * -thresholdXDistanceApart + prevX); } else if((currentX -
         * prevX) < thresholdXDistanceApart && Math.abs(currentY -
         * prevY) < thresholdYDistanceApart){
         * newTransitions.get(j).setPositionX(thresholdXDistanceApart +
         * prevX); System.out.println("shifting" +
         * newTransitions.get(i).getId() + ": " +
         * thresholdXDistanceApart + prevX); madeAMove = true; break; }
         *
         * } }
         */
      }
    }

    // Now align all x position of places with respective transitions
    for (int i = 0; i < newPlaces.size(); i++) {
      Iterator<?> it = newPlaces.get(i).getConnectFromIterator();
      if (it.hasNext()) {
        Arc a = (Arc) it.next();
        PipeTransition t = (PipeTransition) a.getTarget();
        newPlaces.get(i).setPositionX(t.getPositionX());
      }
    }

    // Now separate all places from each other
    size = newPlaces.size();
    // otherwise there are no transitons to seperate from each other
    if (size > 1) {
      for (int i = 0; i < size - 1; i++) {
        double prevX = newPlaces.get(i).getPositionX();
        double prevY = newPlaces.get(i).getPositionY();
        for (int j = i + 1; j < size; j++) {
          currentX = newPlaces.get(j).getPositionX();
          currentY = newPlaces.get(j).getPositionY();
          /*
           * if((currentX - prevX) < -thresholdXDistanceApart){
           * newPlaces.get(j).setPositionX(-thresholdXDistanceApart +
           * prevX && Math.abs(currentY - prevY) <
           * thresholdYDistanceApart); } else
           */ if ((currentX - prevX) < thresholdXDistanceApart
              && Math.abs(currentY - prevY) < thresholdYDistanceApart) {
            newPlaces.get(j).setPositionX(thresholdXDistanceApart + prevX);
          }
        }
      }
    }
  }
  /** Precomputation. */
  public void precomputeArcFlags(double latMin, double latMax, double lngMin, double lngMax) {
    List<Arc> arcs;
    Arc arc0;
    Node headNode;
    Node tailNode;

    // compute boundary nodes
    for (int i = 0; i < graph.getAdjacentArcs().size(); i++) {
      arcs = graph.getAdjacentArcs().get(i);
      tailNode = graph.getMapNodeId().get(graph.getNodeIds().get(i));
      // if tailNode is in region, check if it is a boundary node
      if (isInRegion(latMin, latMax, lngMin, lngMax, tailNode)) {
        for (int j = 0; j < arcs.size(); j++) {
          arc0 = arcs.get(j);
          headNode = arc0.headNode;
          if (!isInRegion(latMin, latMax, lngMin, lngMax, headNode)) {
            if (!boundaryNodes.contains(tailNode.id)) {
              boundaryNodes.add(tailNode.getId());
            }
            // break;
          } else {
            // set arcFlag to true for arcs inside the region
            arc0.arcFlag = true;
          }
        }
      }
    }

    System.out.println("---All boundary nodes found---");
    System.out.println("#Of Boundary nodes: " + boundaryNodes.size());

    // compute Dijkstra for each of the boundary nodes
    // saves the map parents into a list
    for (int i = 0; i < boundaryNodes.size(); i++) {
      long boundaryNodeId = boundaryNodes.get(i);
      DijkstraAlgorithm dijAlg = new DijkstraAlgorithm(graph);
      dijAlg.computeShortestPath(boundaryNodeId, -1);

      // we set flags
      Map<Long, Long> parents = dijAlg.getParents();
      Iterator<Long> it = parents.keySet().iterator();
      while (it.hasNext()) {
        Long currentNodeId = (Long) it.next();
        Long parentNodeId = parents.get(currentNodeId);

        // System.out.println(currentNodeId + "-" + parentNodeId);

        if (parentNodeId != -1) {
          List<Arc> allArcs = graph.getNodeAdjacentArcs(currentNodeId);

          for (int k = 0; k < allArcs.size(); k++) {
            Arc arc = allArcs.get(k);
            if (arc.getHeadNode().getId() == parentNodeId) {
              arc.arcFlag = true;
            }
          }
        }
      }
      // System.out.println(numberOfArcProBNode);
      System.out.print(i + " - ");
    }
    System.out.println("\n---Dijkstra for all boundary node completed---");

    /*
     * for (int i = 0; i < parentsOfBoundaryNodes.size(); i++) { Map<Integer,
     * Integer> parents = parentsOfBoundaryNodes.get(i); Iterator<Integer> it =
     * parents.keySet().iterator(); while (it.hasNext()) { Integer currentNode =
     * (Integer) it.next(); Integer parentNode = parents.get(currentNode);
     * List<Arc> allArcs = graph.getNodeAdjacentArcs(parentNode);
     *
     * for (int k = 0; k < allArcs.size(); k++) { Arc arc = allArcs.get(k); if
     * (arc.getHeadNode().getId() == currentNode) { arc.arcFlag = true; } } } }
     */

    // exportToFile(boundaryNodes);
    System.out.println("---Finish boundary nodes!---");

    // TODO: mark arcFlags to arcs in shortest paths to boundary nodes.
  }
Example #24
0
  public void actionPerformed(ActionEvent event) {
    if (d.again) {
      initTree(tree);
      d.again = false;
    }
    if (event.getSource() == send) {
      String c1 = attachment1.getText();
      String c2 = attachment2.getText();
      String c3 = valueOfArc.getText();

      if (c1.matches(regularExpression)
          && c2.matches(regularExpression)
          && c3.matches(regularExpression)) {

        int s1 = Integer.parseInt(c1);
        int s2 = Integer.parseInt(c2);
        int value = Integer.parseInt(c3);

        if (s1 <= d.getNumberOfNodes() && s2 <= d.getNumberOfNodes() && s1 != s2) {
          Arc a = new Arc(s1, s2, value);

          boolean already = false;
          int emplacement = 0;
          int i = 0;

          while (tree[i] != null && i < tree.length) {
            if ((tree[i].getNode1() == a.getNode1() || tree[i].getNode1() == a.getNode2())
                && (tree[i].getNode2() == a.getNode1() || tree[i].getNode2() == a.getNode2())) {
              emplacement = i;
              already = true;
            }
            i++;
          }
          if (!already) {
            tree[d.getNumberOfArc()] = a;
            d.addArc(a, d.getNumberOfArc());
          } else {
            tree[emplacement].setCost(value);
            d.modifArc(emplacement, value);
          }

          d.repaint();
        }
      }
    } else if (event.getSource() == step) {
      if (tree[0] != null) {
        if (d.getCpt() == 0) {
          if (d.getChoice().equals("Kruskal")) {
            k = new Kruskal(tree, d.getNumberOfNodes(), d.getNumberOfArc());
            d.finalTree = k.tree;
          }

          d.end = true;
        }

        if (d.finalTree[d.getCpt()] != null) {
          d.setCpt(d.getCpt() + 1);
        }
        d.repaint();
      }
    }
  }
  /**
   * Attempts to find next valid solution to the graph depending on what type of <code>PathType
   * </code> is desired.
   *
   * @param searchTechnique Indicates type of search that should be performed
   * @param prevSolution Previous solution to allow this search to continue from that point
   * @return The resulting solution
   * @throws ConsistencyException When determine that graph is impossible to satisfy
   */
  private Solution searchForNextSolution(PathType searchTechnique, Solution prevSolution)
      throws ConsistencyException {
    // A left move equates to setting a requirement to false and a right move is equivalent to true.
    // Try setting to "false" first to reduce the number of tables for most searches.
    // For the "any relevant" search use "true" first which is quicker
    SearchDirection firstDirection;
    SearchDirection secondDirection;
    if (searchTechnique == PathType.ANY_RELEVANT) {
      firstDirection = SearchDirection.RIGHT;
      secondDirection = SearchDirection.LEFT;
    } else {
      firstDirection = SearchDirection.LEFT;
      secondDirection = SearchDirection.RIGHT;
    }

    // if this is a subsequent search after a solution was already found, we need
    // to return to the location where the last move in the first direction was made
    List<SearchDirection> searchPath = new LinkedList<SearchDirection>();
    List<Arc> searchArcs = new LinkedList<Arc>();
    if (prevSolution != null) {
      // check for situation where we have already traversed all possible paths
      boolean prevContainsFirstDirection = false;
      for (SearchDirection direction : prevSolution.searchPath) {
        if (direction == firstDirection) {
          prevContainsFirstDirection = true;
          break;
        }
      }
      if (!prevContainsFirstDirection) {
        return null;
      }

      ListIterator<SearchDirection> pathIter =
          prevSolution.searchPath.listIterator(prevSolution.searchPath.size());

      // continue to move back in search path until we find an arc that can
      // be assigned the second direction
      boolean foundSecondDir = false;
      while (pathIter.hasPrevious() && !foundSecondDir) {

        // reset the search function for next search operation
        reset(requiredTables);
        propagate();
        searchPath.clear();
        searchArcs.clear();

        // locate the last move that has an alternative
        while (pathIter.hasPrevious()) {
          SearchDirection direction = pathIter.previous();

          if (direction == firstDirection) {
            break;
          }
        }

        // recreate path up to point where we can try a different direction
        Iterator<Arc> arcIter = prevSolution.getSearchArcs().iterator();
        if (pathIter.hasPrevious()) {
          Iterator<SearchDirection> redoIter = prevSolution.getSearchPath().iterator();
          int lastIdx = pathIter.previousIndex();
          for (int idx = 0; idx <= lastIdx; idx++) {

            // all of these operations should work without issue
            SearchDirection direction = redoIter.next();
            Arc arc = arcIter.next();
            if (!attemptArcAssignment(arc, direction)) {
              throw new ConsistencyException(arc);
            }

            // add movement to newly constructed search path
            searchPath.add(direction);
            searchArcs.add(arc);
          }
        }

        // before any searching will begin, make sure the path we are going down shouldn't
        // just be skipped
        int rating = getRatingForCurrentState(searchTechnique);

        // current state isn't any better, return it as next solution
        if (rating >= prevSolution.getRating()) {
          return new Solution(arcs, rating, searchPath, searchArcs, true);
        }

        // retrieve arc which we are going to move second direction
        Arc arc = arcIter.next();

        // if we can't move the second direction here, continue
        // to move back in search path until we find an arc that can
        // be assigned the second direction
        if (attemptArcAssignment(arc, secondDirection)) {
          // update new search path
          searchPath.add(secondDirection);
          searchArcs.add(arc);

          // before any searching will begin, make sure the path we are going down shouldn't
          // just be skipped
          rating = getRatingForCurrentState(searchTechnique);

          // current state isn't any better, return it as next solution
          if (rating >= prevSolution.getRating()) {
            return new Solution(arcs, rating, searchPath, searchArcs, true);
          }

          // set second direction flag so search will continue
          foundSecondDir = true;
        }
      }

      // if we weren't able to make another movement, there are not more solutions
      if (searchPath.size() == 0) {
        return null;
      }
    }

    // dump current state of graph
    if (logger.isDebugEnabled()) {
      logger.debug("-- Graph State Before Search --");
      dumpStateToLog();
    }

    // look for arcs that are not bound
    int rating = -1;
    for (Arc a : arcs) {
      if (!a.isRequirementKnown()) {
        // try the first direction
        if (attemptArcAssignment(a, firstDirection)) {
          searchPath.add(firstDirection);
        } else if (attemptArcAssignment(
            a, secondDirection)) { // if first direction fails, try the second
          searchPath.add(secondDirection);
        } else { // If arc cannot be assigned a requirement value, throw an exception
          throw new ConsistencyException(a);
        }

        // record arc that was altered in search path
        searchArcs.add(a);

        // make sure solution is getting better
        if (prevSolution != null) {
          rating = getRatingForCurrentState(searchTechnique);

          // current state isn't any better, return it as next solution
          if (rating >= prevSolution.getRating()) {
            return new Solution(arcs, rating, searchPath, searchArcs, true);
          }
        }
      }
    }

    // compute rating if never computed
    if (rating < 0) {
      rating = getRatingForCurrentState(searchTechnique);
    }

    // return solution to graph problem
    return new Solution(arcs, rating, searchPath, searchArcs, false);
  }