예제 #1
0
  /**
   * Goal-driven recursive (depth-first, exhaustive) search with backtracking
   *
   * @param problem
   * @param algorithm
   * @param subtaskRelsInPath
   * @param depth
   */
  private boolean subtaskPlanningImpl(
      PlanningContext context,
      Set<Rel> relsWithSubtasks,
      EvaluationAlgorithm algorithm,
      LinkedList<Rel> subtaskRelsInPath,
      int depth) {

    Set<Rel> relsWithSubtasksCopy = new LinkedHashSet<Rel>(relsWithSubtasks);

    Set<Rel> relsWithSubtasksToRemove = new LinkedHashSet<Rel>();

    boolean firstMLB = true;

    // start building Maximal Linear Branch (MLB)
    MLB:
    while (!relsWithSubtasksCopy.isEmpty()) {

      if (isSubtaskLoggingOn()) {
        String print = p(depth) + "Starting new MLB with: ";
        for (Rel rel : relsWithSubtasksCopy) {
          print +=
              "\n" + p(depth) + "  " + rel.getParent().getFullName() + " : " + rel.getDeclaration();
        }
        /*
        print += "\n" + p( depth ) + " All remaining rels in problem:";
        for ( Rel rel : problem.getAllRels() ) {
            print += "\n" + p( depth ) + " " + rel.getParentObjectName() + " : " + rel.getDeclaration();
        }
        print += "\n" + p( depth ) + "All found variables: ";
        for ( Var var : problem.getFoundVars() ) {
            print += "\n" + p( depth ) + " " + var.toString();
        }
        */
        logger.debug(print);
      }

      // if this is a first attempt to construct an MLB to solve a subtask(i.e. depth>0),
      // do not invoke linear planning because it has already been done
      if ((depth == 0) || !firstMLB) {

        boolean solvedIntermediately = linearForwardSearch(context, algorithm, true);

        // Having constructed some MLBs the (sub)problem may be solved
        // and there is no need in wasting precious time planning unnecessary branches
        if (solvedIntermediately
            && ( // on the top level optimize only if computing goals
            (depth == 0 && !computeAll)
                // otherwise (inside subtasks) always optimize
                || (depth != 0))) {
          // If the problem is solved, optimize and return
          if (!isOptDisabled) Optimizer.optimize(context, algorithm);
          return true;
        }
      } else {
        firstMLB = false;
      }

      // or children
      OR:
      for (Iterator<Rel> subtaskRelIterator = relsWithSubtasksCopy.iterator();
          subtaskRelIterator.hasNext(); ) {

        Rel subtaskRel = subtaskRelIterator.next();

        if (isSubtaskLoggingOn())
          logger.debug(
              p(depth)
                  + "OR: depth: "
                  + (depth + 1)
                  + " rel - "
                  + subtaskRel.getParent().getFullName()
                  + " : "
                  + subtaskRel.getDeclaration());

        if (subtaskRel.equals(subtaskRelsInPath.peekLast())
            || (!context.isRelReadyToUse(subtaskRel))
            || context.getFoundVars().containsAll(subtaskRel.getOutputs())
            || (!isSubtaskRepetitionAllowed && subtaskRelsInPath.contains(subtaskRel))) {

          if (isSubtaskLoggingOn()) {
            logger.debug(p(depth) + "skipped");
            if (!context.isRelReadyToUse(subtaskRel)) {
              logger.debug(p(depth) + "because it has unknown inputs"); // TODO print unknown
            } else if (context.getFoundVars().containsAll(subtaskRel.getOutputs())) {
              logger.debug(p(depth) + "because all outputs in FoundVars");
            } else if (subtaskRel.equals(subtaskRelsInPath.peekLast())) {
              logger.debug(p(depth) + "because it is nested in itself");
            } else if (!isSubtaskRepetitionAllowed && subtaskRelsInPath.contains(subtaskRel)) {
              logger.debug(
                  p(depth)
                      + "This rel with subtasks is already in use, path: "
                      + subtaskRelsInPath);
            }
          }
          continue OR;
        }

        LinkedList<Rel> newPath = new LinkedList<Rel>(subtaskRelsInPath);
        newPath.add(subtaskRel);

        PlanningResult result = new PlanningResult(subtaskRel, true);

        // this is true if all subtasks are solvable
        boolean allSolved = true;
        // and children
        AND:
        for (SubtaskRel subtask : subtaskRel.getSubtasks()) {
          if (isSubtaskLoggingOn()) logger.debug(p(depth) + "AND: subtask - " + subtask);

          EvaluationAlgorithm sbtAlgorithm = null;

          ////////////////////// INDEPENDENT SUBTASK////////////////////////////////////////
          if (subtask.isIndependent()) {
            if (isSubtaskLoggingOn()) logger.debug("Independent!!!");

            if (subtask.isSolvable() == null) {
              if (isSubtaskLoggingOn())
                logger.debug("Start solving independent subtask " + subtask.getDeclaration());
              // independent subtask is solved only once
              Problem problemContext = subtask.getContext();
              DepthFirstPlanner planner = new DepthFirstPlanner();
              planner.indSubtasks = indSubtasks;
              planner.nested = true;
              sbtAlgorithm = planner.invokePlaning(problemContext, isOptDisabled);
              PlanningContext indCntx = problemContext.getCurrentContext();
              boolean solved = indCntx.getFoundVars().containsAll(indCntx.getAllGoals());
              if (solved) {
                subtask.setSolvable(Boolean.TRUE);
                indSubtasks.put(subtask, sbtAlgorithm);
                if (isSubtaskLoggingOn()) logger.debug("Solved " + subtask.getDeclaration());
              } else {
                subtask.setSolvable(Boolean.FALSE);
                if (RuntimeProperties.isLogInfoEnabled()) {
                  logger.debug("Unable to solve " + subtask.getDeclaration());
                }
              }
              allSolved &= solved;
            } else if (subtask.isSolvable() == Boolean.TRUE) {
              if (isSubtaskLoggingOn()) logger.debug("Already solved");
              allSolved &= true;
              sbtAlgorithm = indSubtasks.get(subtask);
            } else {
              if (isSubtaskLoggingOn()) logger.debug("Not solvable");
              allSolved &= false;
            }
            if (isSubtaskLoggingOn()) logger.debug("End of independent subtask " + subtask);

            if (!allSolved) {
              continue OR;
            }

            assert sbtAlgorithm != null;

            result.addSubtaskAlgorithm(subtask, sbtAlgorithm);
          }
          ////////////////////// DEPENDENT SUBTASK//////////////////////////////////////
          else {
            // lets clone the environment
            PlanningContext newContext = prepareNewContext(context, subtask);

            sbtAlgorithm = new EvaluationAlgorithm();

            // during linear planning, if some goals are found, they are removed from the set
            // "goals"
            boolean solved =
                linearForwardSearch(
                    newContext,
                    sbtAlgorithm,
                    // do not optimize here, because the solution may require additional rels with
                    // subtasks
                    true);

            if (solved) {
              if (isSubtaskLoggingOn()) logger.debug(p(depth) + "SOLVED subtask: " + subtask);

              if (!isOptDisabled) {
                // if a subtask has been solved, optimize its algorithm
                Optimizer.optimize(newContext, sbtAlgorithm);
              }

              result.addSubtaskAlgorithm(subtask, sbtAlgorithm);
              allSolved &= solved;
              continue AND;
            } else if (!solved && (depth == maxDepth)) {
              if (isSubtaskLoggingOn())
                logger.debug(p(depth) + "NOT SOLVED and cannot go any deeper, subtask: " + subtask);
              continue OR;
            }

            if (isSubtaskLoggingOn()) logger.debug(p(depth) + "Recursing deeper");

            solved =
                subtaskPlanningImpl(newContext, relsWithSubtasks, sbtAlgorithm, newPath, depth + 1);

            if (isSubtaskLoggingOn()) logger.debug(p(depth) + "Back to depth " + (depth + 1));

            // the linear planning has been performed at the end of MLB on the depth+1,
            // if the problem was solved, there is no need to run linear planning again
            if ((solved || (solved = linearForwardSearch(newContext, sbtAlgorithm, true)))
                && !isOptDisabled) {
              // if solved, optimize here with full list of goals in order to get rid of
              // unnecessary subtask instances and other relations
              Optimizer.optimize(newContext, sbtAlgorithm);
            }

            if (isSubtaskLoggingOn())
              logger.debug(p(depth) + (solved ? "" : "NOT") + " SOLVED subtask: " + subtask);

            allSolved &= solved;

            // if at least one subtask is not solvable, try another
            // branch
            if (!allSolved) {
              continue OR;
            }

            result.addSubtaskAlgorithm(subtask, sbtAlgorithm);
          }
        } // AND

        if (allSolved) {
          algorithm.add(result);

          Set<Var> newVars = new LinkedHashSet<Var>();

          unfoldVarsToSet(subtaskRel.getOutputs(), newVars);

          context.getKnownVars().addAll(newVars);
          context.getFoundVars().addAll(newVars);

          subtaskRelIterator.remove();

          if (isSubtaskLoggingOn()) {
            logger.debug(
                p(depth)
                    + "SOLVED ALL SUBTASKS for "
                    + subtaskRel.getParent().getFullName()
                    + " : "
                    + subtaskRel.getDeclaration());
            logger.debug(p(depth) + "Updating the problem graph and continuing building new MLB");
          }

          // this is used for incremental dfs
          if (depth == 0) {
            relsWithSubtasksToRemove.add(subtaskRel);
          }

          continue MLB;
        }
        if (isSubtaskLoggingOn())
          logger.debug(
              p(depth)
                  + "NOT SOLVED ALL subtasks, removing from path "
                  + subtaskRel.getParent().getFullName()
                  + " : "
                  + subtaskRel.getDeclaration());
        newPath.remove(subtaskRel);
      } // end OR

      // exit loop because there are no more rels with subtasks to be
      // applied
      // (i.e. no more rels can introduce new variables into the
      // algorithm)
      if (isSubtaskLoggingOn()) logger.debug(p(depth) + "No more MLB can be constructed");
      break MLB;
    }

    // incremental dfs, remove solved subtasks
    if (depth == 0) {
      relsWithSubtasks.removeAll(relsWithSubtasksToRemove);
    }

    return false;
  }
  public boolean execute() {
    if (CDState.getCycle() % period != 0) return false;

    MycoCast mycocast = (MycoCast) Network.get(0).getProtocol(mycocastPid);

    int bio = mycocast.countBiomass();
    int ext = mycocast.countExtending();
    int bra = mycocast.countBranching();
    int imm = mycocast.countImmobile();

    // Update vertices
    Set<MycoNode> activeNodes = new HashSet<MycoNode>();
    for (int i = 0; i < Network.size(); i++) {
      MycoNode n = (MycoNode) Network.get(i);
      activeNodes.add(n);
      HyphaData data = n.getHyphaData();
      // if (data.isBiomass()) { continue; }
      if (graph.containsVertex(n)) {
        graph.removeVertex(n);
      }
      if (!graph.containsVertex(n)) {
        graph.addVertex(n);
      }
    }
    Set<MycoNode> jungNodes = new HashSet<MycoNode>(graph.getVertices());
    jungNodes.removeAll(activeNodes);

    for (MycoNode n : jungNodes) {
      graph.removeVertex(n);
    }

    // Update edges
    for (int i = 0; i < Network.size(); i++) {
      MycoNode n = (MycoNode) Network.get(i);
      HyphaData data = n.getHyphaData();
      HyphaLink link = n.getHyphaLink();

      synchronized (graph) {

        // We now add in all links and tune out display in Visualizer
        java.util.List<MycoNode> neighbors = (java.util.List<MycoNode>) link.getNeighbors();

        //// Adding only links to hypha thins out links to biomass
        //    (java.util.List<MycoNode>) link.getHyphae();

        Collection<MycoNode> jungNeighbors = graph.getNeighbors(n);

        // Remove edges from Jung graph that are not in peersim graph
        for (MycoNode o : jungNeighbors) {
          if (!neighbors.contains(o)) {
            MycoEdge edge = graph.findEdge(n, o);
            while (edge != null) {
              graph.removeEdge(edge);
              edge = graph.findEdge(n, o);
            }
          }
        }

        // Add missing edges to Jung graph that are in peersim graph
        for (MycoNode o : neighbors) {
          if (graph.findEdge(n, o) == null) {
            MycoEdge edge = new MycoEdge();
            graph.addEdge(edge, n, o, EdgeType.DIRECTED);
          }
        }
      }

      // log.finest("VERTICES: " + graph.getVertices());
      // log.finest("EDGES: " + graph.getEdges());
    }

    for (ChangeListener cl : changeListeners) {
      cl.stateChanged(new ChangeEvent(graph));
    }
    if (walking) {
      try {
        Thread.sleep(walkDelay);
      } catch (InterruptedException e) {
      }
      stepBlocked = false;
    }

    try {
      while (stepBlocked && !noBlock) {
        synchronized (JungGraphObserver.class) {
          JungGraphObserver.class.wait();
        }
      }
    } catch (InterruptedException e) {
      stepBlocked = true;
    }
    stepBlocked = true;
    // System.out.println(graph.toString());
    return false;
  }