interval.cpp
/***************************************************************************
* Copyright (C) 2007 by Touati Sid *
* Sid-nospam.Touati-nospam@univ-cotedazur-nospam.fr *
* Copyright INRIA and the University of Versailles *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "interval.h"
#include <algorithm> //sort
#include <vector> //stal container
/*! \mainpage A C++ implementation of a O(n log n) algorithm computing a maximal stable set of an interval graph.
*/
using namespace std;
ENDPOINT::ENDPOINT(){
val=0;
is_left=true;
}
ENDPOINT::ENDPOINT(double x){
val=x;
is_left=true;
}
ENDPOINT::ENDPOINT(const ENDPOINT &x){
val=x.value();
is_left=x.is_left_endpoint();
}
ENDPOINT::~ENDPOINT(){
}
ENDPOINT & ENDPOINT::operator= (const ENDPOINT& x){
val=x.value();
is_left=x.is_left_endpoint();
}
ENDPOINT & ENDPOINT::operator= (const double& x){
val=x;
is_left=true;
}
INTERVAL::INTERVAL()
{
x=0;
y=0;
w=1;
}
INTERVAL::INTERVAL(double xx, double yy)
{
if(yy<xx) throw INVALID_INTERVAL(xx,yy);
x=xx;
x.set_left_endpoint(true);
y=yy;
y.set_left_endpoint(false);
w=1;
}
INTERVAL::INTERVAL(double xx, double yy, double ww)
{
if(yy<xx) throw INVALID_INTERVAL(xx,yy);
x=xx;
x.set_left_endpoint(true);
y=yy;
y.set_left_endpoint(false);
w=ww;
}
INTERVAL & INTERVAL::operator= (const INTERVAL& z){
x=z.left();
y=z.right();
if(x.value()>y.value()) throw INVALID_INTERVAL(x.value(),y.value());
}
INTERVAL::INTERVAL(ENDPOINT xx, ENDPOINT yy)
{
if(yy<xx) throw INVALID_INTERVAL(xx,yy);
x=xx;
x.set_left_endpoint(true);
y=yy;
y.set_left_endpoint(false);
w=1;
}
INTERVAL::INTERVAL(ENDPOINT xx, ENDPOINT yy, double ww)
{
if(yy<xx) throw INVALID_INTERVAL(xx,yy);
x=xx;
x.set_left_endpoint(true);
y=yy;
y.set_left_endpoint(false);
w=ww;
}
INTERVAL::~INTERVAL()
{
}
bool operator==(const ENDPOINT & x, const ENDPOINT &y){
return (x.value()==y.value()&&x.is_left_endpoint()==y.is_left_endpoint());
}
bool operator<=(const ENDPOINT &x, const ENDPOINT &y){
if (x.value()<y.value()) return true;
else if (x.value()>y.value()) return false;
else{
if (x.is_left_endpoint()&&!y.is_left_endpoint())return false;
else return true;
}
}
bool operator<(const ENDPOINT &x, const ENDPOINT &y){
if (x.value()<y.value()) return true;
else if (x.value()>y.value()) return false;
else{
if (x.is_left_endpoint()==y.is_left_endpoint())return false;
if (x.is_left_endpoint()&&!y.is_left_endpoint())return false;
if (!x.is_left_endpoint()&&y.is_left_endpoint())return true;
}
}
bool operator>(const ENDPOINT &x, const ENDPOINT &y){
if (x.value()>y.value()) return true;
else if (x.value()<y.value()) return false;
else{
if (x.is_left_endpoint()==y.is_left_endpoint())return false;
if (x.is_left_endpoint()&&!y.is_left_endpoint())return true;
if (!x.is_left_endpoint()&&y.is_left_endpoint())return false;
}
}
bool operator>=(const ENDPOINT & x, const ENDPOINT &y){
if (x.value()>y.value()) return true;
else if (x.value()<y.value()) return false;
else{
if (!x.is_left_endpoint()&&y.is_left_endpoint())return true;
else return true;
}
}
bool operator==(const INTERVAL& x, const INTERVAL &y){
return (x.left()==y.left()&&x.right()==y.right());
}
bool operator<(const INTERVAL &x, const INTERVAL &y){
return (x.right()<y.left());
}
bool operator>(const INTERVAL &x, const INTERVAL &y){
return ( x.left()>y.right());
}
INVALID_INTERVAL::INVALID_INTERVAL(double x, double y){
cerr<<"Invalid interval. Leftend="<< x <<". Rightend="<<y<<endl;
}
INVALID_INTERVAL::INVALID_INTERVAL(ENDPOINT x, ENDPOINT y){
cerr<<"Invalid interval. Leftend="<< x <<". Rightend="<<y;
}
ostream& operator<<(ostream &os, ENDPOINT x) /* output stream */
{
os<<x.value()<<' '<<x.is_left_endpoint();
return os;
}
istream& operator>>(istream &is, ENDPOINT &x) /* in stream */
{
double y;
bool isleft;
is>>y>>isleft;
x.setValue(y);
x.set_left_endpoint(isleft);
return is;
}
ostream& operator<<(ostream &os, INTERVAL x) /* output stream */
{
os<<x.left().value()<<' '<<x.right().value();
return os;
}
istream& operator>>(istream &is, INTERVAL &x) /* in stream */
{
ENDPOINT e;
double val;
//read left value
is>>val;
e.setValue(val);
e.set_left_endpoint(true);
x.set_left(e);
//read right value
is>>val;
e.setValue(val);
e.set_left_endpoint(false);
x.set_right(e);
return is;
}
int lexicographic_compare(const ENDPOINT &x, const ENDPOINT&y){
double xx=x.value();
double yy=y.value();
bool leftx=x.is_left_endpoint();
bool lefty=y.is_left_endpoint();
if(xx<yy) return -1;
if(xx>yy) return 1;
if(xx==yy) {
if (leftx && !lefty) return 1;
if (leftx && lefty) return 0;
if (!leftx && lefty) return -1;
if (!leftx && !lefty) return 0;
}
}
bool operator < (const SortTable& m1, const SortTable& m2)
{
return (m1.ep < m2.ep);
}
int MAXIMAL_STABLE_SET_IG(const std::list<INTERVAL> &intervals, int *colour){
std::vector<SortTable> endpoints(2*intervals.size()); // N is the number of intervals
std::list<INTERVAL>::const_iterator it;
std::vector<int> ASGN(intervals.size()), NEXT(intervals.size());
int i=0,j=0, temp, N;
int maxchan=0, counter=0, channel=0;
N=intervals.size();
if (N==0) return 0;
// construct the list of endpoints
for(it = intervals.begin(); it!=intervals.end(); it++){
endpoints[2*i].ep=it->left();
endpoints[2*i].interval_number=i;
endpoints[2*i+1].ep=it->right();
endpoints[2*i+1].interval_number=i;
i++;
}
//step 1 : sort the 2N endpoint tp obtain z_0 <= z_1 <= z_2 <= ....<= z_{2N-1}
// if z_i = z_1{i+1}= z_{i+2} we assure that the right enpoints appear before the left endpoints
std::sort (endpoints.begin(), endpoints.end());
// step 2 already made : maxchan=0, counter=0, channel=0;
//step 3
for(i=0;i<N;i++){
NEXT[i]=i+1;
}
//step 4
for(j=0;j<2*N;j++){
// if zj is a left endpoint of some interval Ik
// here, k = endpoints[j].interval_number
if(endpoints[j].ep.is_left_endpoint()) {
counter++;
maxchan=max(counter,maxchan);
ASGN[endpoints[j].interval_number]=channel;
channel=NEXT[channel];
}
else { // zj is a right endpoint of some interval Ik
counter --;
temp=ASGN[endpoints[j].interval_number];
NEXT[temp]=channel;
channel=temp;
}
}
// returns the colour of each interval
for(i=0;i<N;i++){
colour[i]=ASGN[i];
}
return maxchan;
}
int MAXIMAL_STABLE_SET_IG(const std::list<INTERVAL> &intervals){
std::vector<SortTable> endpoints(2*intervals.size()); // N is the number of intervals
std::list<INTERVAL>::const_iterator it;
std::vector<int> ASGN(intervals.size()), NEXT(intervals.size());
int i=0,j=0, temp, N;
int maxchan=0, counter=0, channel=0;
N=intervals.size();
if (N==0) return 0;
// construct the list of endpoints
for(it = intervals.begin(); it!=intervals.end(); it++){
endpoints[2*i].ep=it->left();
endpoints[2*i].interval_number=i;
endpoints[2*i+1].ep=it->right();
endpoints[2*i+1].interval_number=i;
i++;
}
//step 1 : sort the 2N endpoint tp obtain z_0 <= z_1 <= z_2 <= ....<= z_{2N-1}
// if z_i = z_1{i+1}= z_{i+2} we assure that the right enpoints appear before the left endpoints
std::sort (endpoints.begin(), endpoints.end());
// step 2 already made : maxchan=0, counter=0, channel=0;
//step 3
for(i=0;i<N;i++){
NEXT[i]=i+1;
}
//step 4
for(j=0;j<2*N;j++){
// if zj is a left endpoint of some interval Ik
// here, k = endpoints[j].interval_number
if(endpoints[j].ep.is_left_endpoint()) {
counter++;
maxchan=max(counter,maxchan);
ASGN[endpoints[j].interval_number]=channel;
channel=NEXT[channel];
}
else { // zj is a right endpoint of some interval Ik
counter --;
temp=ASGN[endpoints[j].interval_number];
NEXT[temp]=channel;
channel=temp;
}
}
return maxchan;
}