/*
   * (non-Javadoc)
   *
   * @see de.parsemis.strategy.Strategy#search(de.parsemis.miner.Algorithm,
   *      int)
   */
  public Collection<Fragment<NodeType, EdgeType>> search(final Algorithm<NodeType, EdgeType> algo) {
    final String filename = LocalEnvironment.env(this).objectFileName;

    final MiningStack<NodeType, EdgeType> mine =
        new LocalStack<NodeType, EdgeType>(0, this, LocalEnvironment.env(this));
    for (final Iterator<SearchLatticeNode<NodeType, EdgeType>> it = algo.initialNodes();
        it.hasNext(); ) {
      mine.push(it.next());
    }

    // initialize worker for the current thread
    answers[0] =
        (filename != null
            ? new FileSerializeCollection<Fragment<NodeType, EdgeType>>(filename)
            : new ArrayList<Fragment<NodeType, EdgeType>>());
    final Worker<NodeType, EdgeType> me =
        new Worker<NodeType, EdgeType>(mine, answers[0], algo.getExtender(0), 0);

    // initialize worker for further threads
    for (int i = 1; i < answers.length; ++i) {
      answers[i] =
          (filename != null
              ? new FileSerializeCollection<Fragment<NodeType, EdgeType>>(filename + "_" + i)
              : new HashSet<Fragment<NodeType, EdgeType>>());
      threads[i] = new SMPThread<NodeType, EdgeType>(i, algo, this, answers[i]);
    }

    // start other workers
    if (INFO) {
      stats.distributedTime -= System.currentTimeMillis();
    }
    for (int i = 1; i < answers.length; ++i) {
      threads[i].start();
    }

    // start local worker
    me.run();

    // wait for others
    for (int i = 1; i < answers.length; ++i) {
      try {
        threads[i].join();
      } catch (final InterruptedException ie) {
        if (WARN) {
          err.println(ie);
        }
      }
    }
    if (INFO) {
      stats.distributedTime += System.currentTimeMillis();
    }

    // collect data
    for (int i = 1; i < answers.length; ++i) {
      answers[0].addAll(answers[i]);
    }

    return answers[0];
  }