bool LocalSearch::operateMoveDepotRouteM2(Route& ru, Route& rv, bool equal, bool operateM3) {

    bool result = false;
    bool endProcess = false;
    bool frontInserted = false;
    bool increasePosition = false;
    float cost;
    int demand, customer1, customer2;

    if (equal) {

        if (ru.getTour().size() <= 2)
            return result;

        for (auto iterRU = ru.getTour().begin(); iterRU != ru.getTour().end(); ++iterRU) {

            if (next(iterRU) == ru.getTour().end())
                continue;

            Route newRU = ru;

            auto nextIterRU = next(iterRU);

            //newRU.printSolution();

            newRU.remove((*iterRU));
            newRU.remove((*nextIterRU));
            //newRU.printSolution();

            // place x and u after v;
            if (operateM3) {
                customer1 = (*nextIterRU);
                customer2 = (*iterRU);
            } else { // then place u and x after v;
                customer1 = (*iterRU);
                customer2 = (*nextIterRU);
            }

            auto iterRV = newRU.getTour().begin();
            endProcess = false;
            frontInserted = false;

            while (!endProcess) {

                auto firstPosition = iterRV;
                auto secPosition = iterRV;

                increasePosition = true;

                if (!frontInserted || ru.getProblem()->getGranularNeighborhood().at((*iterRU) - 1).at((*iterRV) - 1) == 1) {

                    if (!frontInserted && iterRV == newRU.getTour().begin()) {
                        //cout << "Before: " << *iterRV << endl;
                        firstPosition = newRU.addAtFront(customer1);
                        frontInserted = true;
                        increasePosition = false;
                    }
                    else {
                        //cout << "After: " << *iterRV << endl;
                        firstPosition = newRU.addAfterPrevious(iterRV, customer1);
                        increasePosition = true;
                    }

                    secPosition = newRU.addAfterPrevious(firstPosition, customer2);
                    //newRU.printSolution();

                    if (Util::isBetterSolution(newRU.getTotalCost(), ru.getTotalCost())) {
                        ru = newRU;
                        result = true;
                        //cout << "Improved \n";
                        break;
                    }
                    else {
                        newRU.remove(firstPosition);
                        newRU.remove(secPosition);
                        //newRU.printSolution();
                        //cout << endl;
                    }

                }

                if (increasePosition)
                    iterRV++;

                if (iterRV == newRU.getTour().end())
                    endProcess = true;

                if (ru.getProblem()->getMonitor().isTerminated())
                    break;

            }

            if (result)
                break;

            if (ru.getProblem()->getMonitor().isTerminated())
                break;

        }

    } else {

        for (auto iterRU = ru.getTour().begin(); iterRU != ru.getTour().end(); ++iterRU) {

            if (next(iterRU) == ru.getTour().end())
                continue;

            demand = rv.getProblem()->getDemand().at((*iterRU) - 1);
            demand += rv.getProblem()->getDemand().at((*next(iterRU)) - 1);

            if (demand + rv.getDemand() > rv.getProblem()->getCapacity())
                continue;

            //ru.printSolution();

            Route newRU = ru;
            auto nextIterRU = next(iterRU);

            newRU.remove((*iterRU));
            newRU.remove((*nextIterRU));
            //newRU.printSolution();

            // place x and u after v;
            if (operateM3) {
                customer1 = (*nextIterRU);
                customer2 = (*iterRU);
            } else { // then place u and x after v;
                customer1 = (*iterRU);
                customer2 = (*nextIterRU);
            }

            //printf("%d\t%d\n", customer1, customer2);

            //cout << "\n\nTest = " << (*iterRU) << endl;

            //for (auto iterRV = newRU.getTour().begin(); iterRV != newRU.getTour().end(); ++iterRV) {
            auto iterRV = rv.getTour().begin();
            endProcess = false;
            frontInserted = false;

            while (!endProcess) {

                auto firstPosition = iterRV;
                auto secPosition = iterRV;

                cost = rv.getTotalCost();

                increasePosition = true;
                if (!frontInserted || ru.getProblem()->getGranularNeighborhood().at((*iterRU) - 1).at((*iterRV) - 1) == 1) {

                    if (!frontInserted && iterRV == rv.getTour().begin()) {
                        //cout << "Before: " << *iterRV << endl;
                        firstPosition = rv.addAtFront(customer1);
                        frontInserted = true;
                        increasePosition = false;
                    }
                    else {
                        //cout << "After: " << *iterRV << endl;
                        firstPosition = rv.addAfterPrevious(iterRV, customer1);
                        increasePosition = true;
                    }

                    secPosition = rv.addAfterPrevious(firstPosition, customer2);

                    //rv.printSolution();

                    if (Util::isBetterSolution(newRU.getTotalCost() + rv.getTotalCost(), ru.getTotalCost() + cost)) {
                        ru = newRU;
                        result = true;
                        //cout << "Improved \n";
                        break;
                    }
                    else {
                        rv.remove(firstPosition);
                        rv.remove(secPosition);
                        //rv.printSolution();
                        //cout << endl;
                    }

                }

                if (increasePosition)
                    iterRV++;

                if (iterRV == rv.getTour().end())
                    endProcess = true;

                if (ru.getProblem()->getMonitor().isTerminated())
                    break;

            }

            if (result)
                break;

            if (ru.getProblem()->getMonitor().isTerminated())
                break;

        }
    }

    return result;
}
bool LocalSearch::operateMoveDepotRouteM5(Route& ru, Route& rv, bool equal) {

    bool result = false;
    bool endProcess = false;
    bool frontInserted = false;
    bool isBeforeFrontRU = false, isBeforeFrontRV = false;
    float cost;
    int demand, customerBeforeRU, customerBeforeRV, customerV;

    if (equal) {

        if (ru.getTour().size() <= 2)
            return result;

        for (auto iterRU = ru.getTour().begin(); iterRU != ru.getTour().end(); ++iterRU) {

            if (next(iterRU) == ru.getTour().end())
                continue;

            auto beforeIteRU = ru.getTour().begin();
            if (iterRU != ru.getTour().begin())
                beforeIteRU = std::prev(iterRU);

            if (iterRU == ru.getTour().begin()) {
                isBeforeFrontRU = true;
                customerBeforeRU = 0;
            } else {
                isBeforeFrontRU = false;
                customerBeforeRU = (*beforeIteRU);
            }

            Route newRU = ru;

            auto nextIterRU = next(iterRU);

            newRU.remove((*iterRU));
            newRU.remove((*nextIterRU));
            //newRU.printSolution();

            //cout << "Before = " << customerBeforeRU << " - Next = " << (*nextIterRU) << endl;
            //cout << "\n\nTest = " << (*iterRU) << endl;

            //for (auto iterRV = newRU.getTour().begin(); iterRV != newRU.getTour().end(); ++iterRV) {
            auto iterRV = newRU.getTour().begin();
            //cout << "\n\niterRV = " << (*iterRV) << endl;

            endProcess = false;
            frontInserted = false;

            while (!endProcess) {

                auto firstPosition = iterRV;
                auto secPosition = iterRV;

                auto beforeIteRV = iterRV;
                if (beforeIteRV != newRU.getTour().begin())
                    beforeIteRV = prev(iterRV);

                auto insertedRV = iterRV;

                if (iterRV == newRU.getTour().begin()) {
                    isBeforeFrontRV = true;
                    customerBeforeRV = 0;
                } else {
                    isBeforeFrontRV = false;
                    customerBeforeRV = (*beforeIteRV);
                }

                // Remove from V
                customerV = (*iterRV);
                newRU.remove(iterRV);

                // Insert U in V
                firstPosition = newRU.addAfterPrevious(customerBeforeRV, (*iterRU));
                secPosition = newRU.addAfterPrevious(firstPosition, (*nextIterRU));

                //newRU.printSolution();

                // Insert V in U
                if (isBeforeFrontRU)
                    insertedRV = newRU.addAtFront(customerV);
                else if (customerBeforeRU == customerV)
                    insertedRV = newRU.addAfterPrevious((*nextIterRU), customerV);
                else {
                    insertedRV = newRU.addAfterPrevious(customerBeforeRU, customerV);
                }

                //newRU.printSolution();

                if (Util::isBetterSolution(newRU.getTotalCost(), ru.getTotalCost())) {
                    ru = newRU;
                    result = true;
                    //cout << "Improved \n";
                    break;
                } else {
                    newRU.remove(firstPosition);
                    newRU.remove(secPosition);
                    newRU.remove(insertedRV);

                    // Put V in correct place
                    iterRV = newRU.addAfterPrevious(customerBeforeRV, customerV);

                    //newRU.printSolution();
                    //cout << endl;
                }

                //newRU.printSolution();
                //cout << endl << endl;

                iterRV++;

                if (iterRV == newRU.getTour().end())
                    endProcess = true;

                if (ru.getProblem()->getMonitor().isTerminated())
                    break;

            }

            if (result)
                break;

            if (ru.getProblem()->getMonitor().isTerminated())
                break;

        }

    } else {

        if (ru.getTour().size() < 2)
            return result;

        for (auto iterRU = ru.getTour().begin(); iterRU != ru.getTour().end(); ++iterRU) {

            if (next(iterRU) == ru.getTour().end())
                continue;

            auto beforeIteRU = ru.getTour().begin();
            if (iterRU != ru.getTour().begin())
                beforeIteRU = std::prev(iterRU);

            if (iterRU == ru.getTour().begin()) {
                isBeforeFrontRU = true;
                customerBeforeRU = 0;
            } else {
                isBeforeFrontRU = false;
                customerBeforeRU = (*beforeIteRU);
            }

            Route newRU = ru;

            auto nextIterRU = next(iterRU);

            newRU.remove((*iterRU));
            newRU.remove((*nextIterRU));
            //newRU.printSolution();

            demand = ru.getProblem()->getDemand().at((*iterRU) - 1) + ru.getProblem()->getDemand().at((*nextIterRU) - 1);

            //cout << "Before = " << customerBeforeRU << " - Next = " << (*nextIterRU) << endl;
            //cout << "\n\nTest = " << (*iterRU) << endl;

            //for (auto iterRV = newRU.getTour().begin(); iterRV != newRU.getTour().end(); ++iterRV) {
            auto iterRV = rv.getTour().begin();

            //cout << "\n\niterRV = " << (*iterRV) << endl;

            endProcess = false;
            frontInserted = false;

            while (!endProcess) {

                if (rv.getDemand() - rv.getProblem()->getDemand().at((*iterRV) - 1) + demand > rv.getProblem()->getCapacity()) {
                    iterRV++;

                    if (iterRV == rv.getTour().end())
                        endProcess = true;

                    if (ru.getProblem()->getMonitor().isTerminated())
                        break;

                    continue;
                }

                auto firstPosition = iterRV;
                auto secPosition = iterRV;

                auto beforeIteRV = iterRV;
                if (beforeIteRV != rv.getTour().begin())
                    beforeIteRV = prev(iterRV);

                auto insertedRV = iterRV;

                if (iterRV == rv.getTour().begin()) {
                    isBeforeFrontRV = true;
                    customerBeforeRV = 0;
                } else {
                    isBeforeFrontRV = false;
                    customerBeforeRV = (*beforeIteRV);
                }

                cost = rv.getTotalCost();

                // Remove from V
                customerV = (*iterRV);
                rv.remove(iterRV);

                // Insert U in V
                firstPosition = rv.addAfterPrevious(customerBeforeRV, (*iterRU));
                secPosition = rv.addAfterPrevious(firstPosition, (*nextIterRU));

                //rv.printSolution();

                // Insert V in U
                insertedRV = newRU.addAfterPrevious(customerBeforeRU, customerV);

                //newRU.printSolution();

                if (Util::isBetterSolution(newRU.getTotalCost() + rv.getTotalCost(), ru.getTotalCost() + cost)) {
                    ru = newRU;
                    result = true;
                    //cout << "Improved \n";
                    break;
                } else {
                    rv.remove(firstPosition);
                    rv.remove(secPosition);
                    newRU.remove(insertedRV);

                    // Put V in correct place
                    iterRV = rv.addAfterPrevious(customerBeforeRV, customerV);

                }

                iterRV++;

                if (iterRV == rv.getTour().end())
                    endProcess = true;

                if (ru.getProblem()->getMonitor().isTerminated())
                    break;

            }

            if (result)
                break;

            if (ru.getProblem()->getMonitor().isTerminated())
                break;

        }
    }

    return result;
}
bool LocalSearch::operateMoveDepotRouteM1(Route& ru, Route& rv, bool equal) {

    bool result = false;
    bool endProcess = false;
    bool frontInserted = false;
    bool increasePosition = false;
    float cost;

    if (equal) {

        if (ru.getTour().size() <= 1)
            return result;

        for (auto iterRU = ru.getTour().begin(); iterRU != ru.getTour().end(); ++iterRU) {

            Route newRU = ru;
            newRU.remove((*iterRU));

            auto iterRV = newRU.getTour().begin();
            endProcess = false;
            frontInserted = false;

            //newRU.printSolution();

            while (!endProcess) {

                auto position = iterRV;

                increasePosition = true;

                if (!frontInserted || ru.getProblem()->getGranularNeighborhood().at((*iterRU) - 1).at((*iterRV) - 1) == 1) {

                    if (!frontInserted && iterRV == newRU.getTour().begin()) {
                        //cout << "Before: " << *iterRV << endl;
                        position = newRU.addAtFront((*iterRU));
                        frontInserted = true;
                        increasePosition = false;
                    } else {
                        //cout << "After: " << *iterRV << endl;
                        position = newRU.addAfterPrevious(iterRV, (*iterRU));
                        increasePosition = true;
                    }

                    //newRU.printSolution();

                    if (Util::isBetterSolution(newRU.getTotalCost(), ru.getTotalCost())) {
                        ru = newRU;
                        result = true;
                        //cout << "Improved \n";
                        break;
                    } else {
                        newRU.remove(position);
                        //newRU.printSolution();
                        //cout << endl;
                    }
                }

                if (increasePosition)
                    iterRV++;

                if (iterRV == newRU.getTour().end())
                    endProcess = true;

                if (ru.getProblem()->getMonitor().isTerminated())
                    break;

            }

            if (result)
                break;

            if (ru.getProblem()->getMonitor().isTerminated())
                break;

        }

    } else {

        for (auto iterRU = ru.getTour().begin(); iterRU != ru.getTour().end(); ++iterRU) {

            if (rv.getProblem()->getDemand().at((*iterRU) - 1) + rv.getDemand() > rv.getProblem()->getCapacity())
                continue;

            Route newRU = ru;
            newRU.remove((*iterRU));

            auto iterRV = rv.getTour().begin();
            endProcess = false;
            frontInserted = false;

            while (!endProcess) {

                auto position = iterRV;
                cost = rv.getTotalCost();

                increasePosition = true;

                if (!frontInserted || ru.getProblem()->getGranularNeighborhood().at((*iterRU) - 1).at((*iterRV) - 1) == 1) {

                    if (!frontInserted && iterRV == rv.getTour().begin()) {
                        //cout << "Before: " << *iterRV << endl;
                        position = rv.addAtFront((*iterRU));
                        frontInserted = true;
                        increasePosition = false;
                    } else {
                        //cout << "After: " << *iterRV << endl;
                        position = rv.addAfterPrevious(iterRV, (*iterRU));
                        increasePosition = true;
                    }

                    //rv.printSolution();

                    if (Util::isBetterSolution(newRU.getTotalCost() + rv.getTotalCost(), ru.getTotalCost() + cost)) {
                        ru = newRU;
                        result = true;
                        //cout << "Improved \n";
                        break;
                    } else {
                        rv.remove(position);
                        //rv.printSolution();
                        //cout << endl;
                    }
                }

                if (increasePosition)
                    iterRV++;

                if (iterRV == rv.getTour().end())
                    endProcess = true;

                if (ru.getProblem()->getMonitor().isTerminated())
                    break;

            }

            if (result)
                break;

            if (ru.getProblem()->getMonitor().isTerminated())
                break;

        }
    }

    return result;
}