biclique.cpp 8.25 KB
#include <iostream>
#include <time.h>
#include <cfloat>
#include <tuple>
#include <algorithm>

#include "biclique.h"


BicliqueChr::BicliqueChr(int coef1, int coef2, float lambdaMin, float lambdaMax, float U2, unsigned int ncores,
                   const std::vector < unsigned int > &verticesId,
                   const std::vector < float > &verticesW1,
                   const std::vector < float > &verticesW2,
                   const std::vector < std::vector < unsigned int > > &NvBs,
                   const std::vector < std::pair < unsigned int, unsigned int > > &E2)
    : Boip(coef1, coef2, lambdaMin, lambdaMax, U2)
{
    verticesId_ = std::vector < unsigned int > (verticesId);
    verticesW1_ = std::vector < float > (verticesW1);
    verticesW2_ = std::vector < float > (verticesW2);
    E2_ = std::vector < std::pair < unsigned int, unsigned int > > (E2);
    NvB = std::vector < std::vector < unsigned int > > (NvBs);
    k_ = 3;

    /*std::cout << "v" << std::endl;
    for(size_t i = 0, size = verticesId_.size(); i != size; i++)
    {
        std::cout << verticesId_[i] << " ";
    }
    std::cout << std::endl;

    std::cout << "vW1" << std::endl;
    for(size_t i = 0, size = verticesW1_.size(); i != size; i++)
    {
        std::cout << verticesW1_[i] << " ";
    }
    std::cout << std::endl;

    std::cout << "vW2" << std::endl;
    for(size_t i = 0, size = verticesW2_.size(); i != size; i++)
    {
        std::cout << verticesW2_[i] << " ";
    }
    std::cout << std::endl;

    std::cout << "NvB" << std::endl;
    for(size_t i = 0, size = NvB.size(); i != size; i++)
    {
        std::cout << "\n" << i << ": ";
        for(size_t j = 0, size2 = NvB[i].size(); j != size2; j++)
            std::cout << NvB[i][j] << " ";
    }
    std::cout << std::endl;

    std::cout << "E2" << std::endl;
    for(size_t i = 0, size = E2_.size(); i != size; i++)
    {
        std::cout << "(" << E2_[i].first << "," << E2_[i].second << ") ";
    }
    std::cout << std::endl;*/

    ip_ = new IP(IP::MIN, int(ncores));

    size_t i, j, size, size2;

    //QUAND IL Y A LES CONTRAINTES UTILISATEURS, NvB renvoie àdes sommets qui ne sont pas à la même place quand dans verticesId


    //std::cout << "Creating decision variables ..." << std::endl;
    // Creating variables and objective function
    for(i=0, size = verticesId_.size(); i != size; i++)
    {
        // Clique variables
        v_.push_back(ip_->make_variable(verticesW1_[verticesId_[i]]));

        // Chromatic number variables
        varVC_.push_back(std::vector < int > ());
        for(j = 0; j != k_; j++) // color
        {
            varVC_[i].push_back(ip_->make_variable(0.0));
        }
    }
    // Chromatic number variables
    for(i = 0; i != k_; i++) // color
    {
        varColorUsed_.push_back(ip_->make_variable(0));
    }
    ip_->update();

    // Creating constraints
    //std::cout << "Creating constraints ..." << std::endl;

    int rowC, row, rowColorUsed;
    // For each vertice
    for (i = 0, size = verticesId_.size(); i != size; i++)
    {
        // Clique constraint
        row = ip_->make_constraint(IP::UP, 0, double(NvB[verticesId_[i]].size()));
        ip_->add_constraint(row, v_[i], double(NvB[verticesId_[i]].size()));

        for (j = 0, size2 = NvB[verticesId_[i]].size(); j != size2; j++)
        {
            ip_->add_constraint(row, v_[
                                std::distance(
                                    verticesId_.begin(),
                                    std::find(verticesId_.begin(), verticesId_.end(), NvB[verticesId_[i]][j])
                                )], 1);
        }

        // Chromatic number constraints

        // One color per vertex
        rowC = ip_->make_constraint(IP::FX, 1.0, 0.0);

        for(j = 0; j != k_; j++)
        {
            ip_->add_constraint(rowC, varVC_[i][j], 1.0);
        }

        // varColorUsed is equal to 0 if the color is not used and vice versa
        for(j = 0; j != k_; j++) // color
        {
            rowColorUsed = ip_->make_constraint(IP::UP, 0.0, 0.0);
            ip_->add_constraint(rowColorUsed, varVC_[i][j], 1.0);
            ip_->add_constraint(rowColorUsed, varColorUsed_[j], -1.0);
        }
    }

    // The color must be different between two adjacent vertices
    for(i=0, size = E2_.size(); i != size; i++)
    {
        for(j = 0; j != k_; j++) // color
        {
            row = ip_->make_constraint(IP::UP, 0.0, 1.0);
            ip_->add_constraint(row, varVC_[E2_[i].first][j], 1.0);
            ip_->add_constraint(row, varVC_[E2_[i].second][j], 1.0);

        }
    }

    // Second objective variable as constraint
    int ctObj21 = ip_->make_constraint(IP::UP, 0, lambdaMax_);
    int ctObj22 = ip_->make_constraint(IP::LO, lambdaMin_, 0);
    for (size_t i = 0, size = verticesId_.size(); i != size; i++)
    {
        ip_->add_constraint(ctObj21, v_[i], double(-verticesW2_[verticesId_[i]]));
        ip_->add_constraint(ctObj22, v_[i], double(-verticesW2_[verticesId_[i]]));
    }

    //std::cout << "End bicliquechr constructor" << std::endl;
}

BicliqueChr::BicliqueChr(const BicliqueChr& that) :
    Boip(that.coef1_, that.coef2_, that.lambdaMin_, that.lambdaMax_, that.U2_),
    verticesId_(that.verticesId_), verticesW1_(that.verticesW1_), verticesW2_(that.verticesW2_), NvB(that.NvB)
{
    ip_ = new IP ();
    ip_ = that.ip_;
}

BicliqueChr::~BicliqueChr()
{
}

void BicliqueChr::add_bj_ct(BoipChrSolution sol)
{
    // We want a different clique so the constraint is defined only on the v variables
    std::vector < double > v = sol.get_v_();
    int row = ip_->make_constraint(IP::LO, 0, 0);
    int B(0);
    for(size_t i = 0, size = v.size(); i != size; i++)
    {
        if(v[i] > 0.5)
        {
            ip_->add_constraint(row, v_[i], 1);
            B++;
        }
        else
        {
            ip_->add_constraint(row, v_[i], -1);
        }
    }
    ip_->chg_constraint(row, IP::UP, -DBL_MAX, B-1);
}

int BicliqueChr::solve(BoipChrSolution& s)
{
    //std::cout << "BiokoP debut solve" << std::endl;
    time_t start, end;  // Returns elapsed time in sec
    double total_time;
    start = clock();

    int status = ip_->solve();

    end = clock();
    total_time = double( end - start )/double(CLOCKS_PER_SEC);

    printf( "\nElapsed time SOLVE IP: %0.3f \n", total_time );

    if(status == 0){

        //recover first objective value
        float obj1(float(ip_->get_obj()));

        //recover decision variable values
        std::vector < double > v = std::vector < double > (v_.size());
        for (size_t i = 0, size = v_.size(); i != size; i++)
        {
            v[i] = ip_->get_value(v_[i]);
        }
        std::vector < std::vector < double > > varVC = std::vector < std::vector < double > > (varVC_.size());
        for (size_t i = 0, size = varVC_.size(); i != size; i++)
        {
            varVC[i] = std::vector < double > (varVC_[i].size());
            for(size_t j = 0, size2 = varVC_[i].size(); j != size2; j++)
                varVC[i][j] = ip_->get_value(varVC_[i][j]);
        }
        std::vector < double > varColorUsed = std::vector < double > (varColorUsed_.size());
        for (size_t i = 0, size = varColorUsed_.size(); i != size; i++)
        {
            varColorUsed[i] = ip_->get_value(varColorUsed_[i]);
        }

        //recover second objective value
        float obj2 = 0.0;
        for (size_t i = 0, size = verticesId_.size(); i != size; i++)
        {
            if(ip_->get_value(v_[i]) > 0.5)
                obj2 -= verticesW2_[verticesId_[i]];
        }

        s.set_v_(v);
        s.set_varVC_(varVC);
        s.set_varColorUsed_(varColorUsed);
        s.set_obj1_(obj1);
        s.set_obj2_(obj2);
        std::cout << "Solve obj1 " << obj1 << " obj2 " << obj2 << std::endl;
    }
    //std::cout << "End solve " << std::endl;
    return 	status;
}


BicliqueChr& BicliqueChr::operator=(const BicliqueChr& that)
{
    verticesId_ = that.verticesId_;
    verticesW1_ = that.verticesW1_;
    verticesW2_ = that.verticesW2_;
    NvB = that.NvB;
    coef1_ = that.coef1_;
    coef2_ = that.coef2_;
    lambdaMin_ = that.lambdaMin_;
    lambdaMax_ = that.lambdaMax_;
    v_ = that.v_;
    varColorUsed_ = that.varColorUsed_;
    varVC_ = that.varVC_;
    U2_ = that.U2_;
    IP * local_ip = new IP ();
    local_ip = that.ip_;
    delete ip_;
    ip_ = local_ip;
    return *this;
}