Esempio n. 1
0
QList<SStep::SCandidate> CTSPSolver::findCandidate(const TMatrix &matrix, int &nRow, int &nCol) const
{
    nRow = -1;
    nCol = -1;
QList<SStep::SCandidate> alts;
SStep::SCandidate cand;
double h = -1;
double sum;
    for (int r = 0; r < nCities; r++)
        for (int c = 0; c < nCities; c++)
            if (matrix.at(r).at(c) == 0) {
                sum = findMinInRow(r,matrix,c) + findMinInCol(c,matrix,r);
                if (sum > h) {
                    h = sum;
                    nRow = r;
                    nCol = c;
                    alts.clear();
                } else if ((sum == h) && !hasSubCycles(r,c)) {
                    cand.nRow = r;
                    cand.nCol = c;
                    alts.append(cand);
                }
            }
    return alts;
}
Esempio n. 2
0
// Using the cost matrix provided configure nRow and nCol to locate the canidate that maximises
// the difference between the inclusion and exclusion branch. We return a vector of alternative
// canidate paths
std::vector<SStep::SCandidate> CTSPSolver::findCandidate(const TMatrix &matrix, int &nRow, int &nCol) const {
    nRow = -1;
    nCol = -1;
    std::vector<SStep::SCandidate> alts;

    double bestMax = -1.0;

    #pragma omp parallel num_threads(numThreads)
    {

      // Our best difference so far
      double h = -1;
      double sum;
      int localRow = 0, localCol = 0;
      SStep::SCandidate cand;

      // For each row and col check for canidate paths. Because we have performed aligns to the
      // cost matrix we are only concerned with 0 values
      #pragma omp for
      for (int r = 0; r < nCities; r++) {
          for (int c = 0; c < nCities; c++) {
              if (matrix.at(r).at(c) == 0) {
                  // Find the cost change for the exclusion branch by selecting this nRow, nCol
                  sum = findMinInRow(r, matrix, c) + findMinInCol(c, matrix, r);

                  // If the difference is greater then we want to choose this path.
                  if (sum > h) {
                      h = sum;
                      localRow = r;
                      localCol = c;
                  // Alternativly we are finding paths of equal difference and will store these. The
                  // optimum soulution could use one of these paths rather than the one we have selected.
                  } else if ((sum == h) && !hasSubCycles(r ,c)) {
                      cand.nRow = r;
                      cand.nCol = c;
                  }
              }
          }
      }

      #pragma omp critical
      {
        if(bestMax < h) {
          nRow = localRow;
          nCol = localCol;
          bestMax = h;
        }

      }
    }

    return alts;
}
Esempio n. 3
0
/*!
 * \brief Solves the given task.
 * \param numCities Number of cities in the task.
 * \param task The matrix of city-to-city travel costs.
 * \return Pointer to the root of the solution tree.
 *
 * \todo TODO: Comment the algorithm.
 */
SStep *CTSPSolver::solve(int numCities, const TMatrix &task)
{
    if (numCities < 3)
        return NULL;

QMutexLocker locker(&mutex);
    cleanup();
    canceled = false;
    locker.unlock();

    nCities = numCities;

SStep *step = new SStep();
    step->matrix = task;
    // We need to distinguish the values forbidden by the user
    // from the values forbidden by the algorithm.
    // So we replace user's infinities by the maximum available double value.
    normalize(step->matrix);
#ifdef DEBUG
    qDebug() << step->matrix;
#endif // DEBUG
    step->price = align(step->matrix);
    root = step;

SStep *left, *right;
int nRow, nCol;
bool firstStep = true;
double check = INFINITY;
    total = 0;
    while (route.size() < nCities) {
        step->alts = findCandidate(step->matrix,nRow,nCol);

        while (hasSubCycles(nRow,nCol)) {
#ifdef DEBUG
            qDebug() << "Forbidden: (" << nRow << ";" << nCol << ")";
#endif // DEBUG
            step->matrix[nRow][nCol] = INFINITY;
            step->price += align(step->matrix);
            step->alts = findCandidate(step->matrix,nRow,nCol);
        }

#ifdef DEBUG
        qDebug() /*<< step->matrix*/ << "Selected: (" << nRow << ";" << nCol << ")";
        qDebug() << "Alternate:" << step->alts;
        qDebug() << "Step price:" << step->price << endl;
#endif // DEBUG

        locker.relock();
        if ((nRow == -1) || (nCol == -1) || canceled) {
            if (canceled && cc)
                cleanup();
            return NULL;
        }
        locker.unlock();

        // Route with (nRow,nCol) path
        right = new SStep();
        right->pNode = step;
        right->matrix = step->matrix;
        for (int k = 0; k < nCities; k++) {
            if (k != nCol)
                right->matrix[nRow][k] = INFINITY;
            if (k != nRow)
                right->matrix[k][nCol] = INFINITY;
        }
        right->price = step->price + align(right->matrix);
        // Forbid the selected route to exclude its reuse in next steps.
        right->matrix[nCol][nRow] = INFINITY;
        right->matrix[nRow][nCol] = INFINITY;

        // Route without (nRow,nCol) path
        left = new SStep();
        left->pNode = step;
        left->matrix = step->matrix;
        left->matrix[nRow][nCol] = INFINITY;
        left->price = step->price + align(left->matrix);

        step->candidate.nRow = nRow;
        step->candidate.nCol = nCol;
        step->plNode = left;
        step->prNode = right;

        // This matrix is not used anymore. Restoring infinities back.
        denormalize(step->matrix);

        if (right->price <= left->price) {
            // Route with (nRow,nCol) path is cheaper
            step->next = SStep::RightBranch;
            step = right;
            route[nRow] = nCol;
            emit routePartFound(route.size());
            if (firstStep) {
                check = left->price;
                firstStep = false;
            }
        } else {
            // Route without (nRow,nCol) path is cheaper
            step->next = SStep::LeftBranch;
            step = left;
            QCoreApplication::processEvents();
            if (firstStep) {
                check = right->price;
                firstStep = false;
            }
        }
        total++;
    }

    mayNotBeOptimal = (check < step->price);

    return root;
}
Esempio n. 4
0
/*!
 * \brief Solves the given task.
 * \param numCities Number of cities in the task.
 * \param task The matrix of city-to-city travel costs.
 * \return Pointer to the root of the solution tree.
 *
 * \todo TODO: Comment the algorithm.
 */
SStep* CTSPSolver::solve(int numCities, const TMatrix &task) {
    if (numCities < 3) {
        return NULL;
    }

    nCities = numCities;
    SStep *step = new SStep(); // Initial node for the solution
    step->matrix = task;       // Copy the initial cost matrix

    // Align the matrix and set the price of the first step to a lower bound for the
    // entire algorithm.
    step->price = align(step->matrix);
    root = step;

    SStep *left, *right;
    int nRow, nCol;
    bool firstStep = true;
    double check = INFINITY;
    total = 0;
    while (route.size() < nCities) {
        // For this step setup the alternative paths while also setting the nRow nCol for the next transition
        step->alts = findCandidate(step->matrix, nRow, nCol);

        // Continually align the matrix while the path has any subcycles. We also
        // eliminate the currently considered path as we can determine this is not within
        // the solution. For each align we need to update the currenly lower bound.
        while (hasSubCycles(nRow,nCol)) {
            step->matrix[nRow][nCol] = INFINITY; // Eliminate path from consideration
            step->price += align(step->matrix);  // Update lower bound
            step->alts = findCandidate(step->matrix,nRow,nCol); // Get new best path
        }

        // A path could not be generated without subcycles; our algorithm has failed
        if ((nRow == -1) || (nCol == -1)) {
            return NULL;
        }

        // Create the inclusion transition. This will compute a new cost matrix with the
        // the selected path as being within the soulution.
        right = new SStep();
        right->pNode = step;
        right->matrix = step->matrix;

        // Remove the to and from paths for the respective cities as we are selecting a path.
        // This effectivly reduces the matrix from a NxN => (N-1)x(N-1)
        for (int k = 0; k < nCities; k++) {
            if (k != nCol) {
                right->matrix[nRow][k] = INFINITY;
            }

            if (k != nRow) {
                right->matrix[k][nCol] = INFINITY;
            }
        }

        // By considering the path compute the new lower bound for the matrix
        right->price = step->price + align(right->matrix);

        // Remove the path to and symetrical path from from the cost matrix
        right->matrix[nCol][nRow] = INFINITY;
        right->matrix[nRow][nCol] = INFINITY;

        // Create the left child for the current step and invalidate nRow and nCol
        left = new SStep();
        left->pNode = step;
        left->matrix = step->matrix;

        // Exclude this path from the solution
        left->matrix[nRow][nCol] = INFINITY;

        // Update the lower bound for this cost matrix with the path excluded
        left->price = step->price + align(left->matrix);

        // Book-keeping for the old GUI program
        step->candidate.nRow = nRow;
        step->candidate.nCol = nCol;
        step->plNode = left;
        step->prNode = right;

        // If the right price is cheaper or equal then we will include the path into the solution
        // and add this transition to the route. Then we will repeat the algorithm from the right child.
        if (right->price <= left->price) {
            step->next = SStep::RightBranch;
            step = right;
            route[nRow] = nCol;

            if (firstStep) {
                check = left->price;
                firstStep = false;
            }

        // The exclusion path is cheaper and we will repeat the algorithm using the left child.
        // IMPORTANT: We do not modify the route
        } else {
            step->next = SStep::LeftBranch;
            step = left;

            if (firstStep) {
                check = right->price;
                firstStep = false;
            }
        }

        total++;
    }

    // On out first transition the step price is an estimated lower bound for the entire algorithm.
    // If our final steps price is greater or equal then we cannot guarantee the solution is optimum.
    mayNotBeOptimal = (check < step->price);
    totalCost = step->price;

    return root;
}