
#include "scproblem.h"

#include "scpview.h"
#include "ilist.h"

SCPView* scp_view_new(SCProblem* problem) {

    

    int rows=0;
    int cols=0;
    int i=0;
    SCPView* v=NULL;

    /*Check parameter*/
    assert(problem!=NULL);

    

    rows=problem->rows;
    cols=problem->columns;

    /*Allocate memory*/
    v = (SCPView*)malloc(sizeof(SCPView));
    assert(v!=NULL);

    /*Assign problem*/
    v->problem=problem;

    /*Create initial mapping*/
    v->columnMap=(int*)malloc(cols*sizeof(int));
    v->rowMap=(int*)malloc(rows*sizeof(int));
    v->parentColumnMap=(int*)malloc(cols*sizeof(int));
    v->parentRowMap=(int*)malloc(rows*sizeof(int));
    
    assert(v->columnMap!=NULL && v->rowMap!=NULL&& v->parentRowMap!=NULL && v->parentColumnMap!=NULL);

    for(i=0;i<cols;i++) {v->columnMap[i]=i;v->parentColumnMap[i]=i;}
    for(i=0;i<rows;i++) {v->rowMap[i]=i;v->parentRowMap[i]=i;}


    /*Set dimensions*/
    v->rows=rows;
    v->columns=cols;

    /*Return*/
    return v;
}



void scp_view_delete(SCPView* v) {

    if (v!=NULL) {
        if (v->columnMap!=NULL) free(v->columnMap);
        if (v->rowMap!=NULL) free(v->rowMap);
        if (v->parentRowMap!=NULL) free(v->parentRowMap);
        if (v->parentColumnMap!=NULL) free(v->parentColumnMap);
        free(v);
    }
    else {
    }

    
    
    
}


unsigned char scp_view_get(SCPView* v,int row,int column) {

    int xr = v->rowMap[row];
    int xc = v->columnMap[column];
    unsigned char* p=NULL;

    assert(v!=NULL);
    assert(row>=0 && row<v->rows && column>=0 && column<v->columns);

    

    /*Get the value*/
    p=v->problem->data;
    return *(p+(xr*v->problem->columns)+xc);
}


int scp_view_get_cost(SCPView* v,int column) {

    /*Check parameters and conditions*/
    assert (column>=0 && column < v->columns);

    /*Get cost*/
    return v->problem->columnCosts[v->columnMap[column]];
}

SCPView* scp_view_get_dumb_copy(SCPView* v,int rows,int cols) {

    SCPView* copy=NULL;

    /*Check parameter*/
    assert(v!=NULL);

    /*Allocate memory*/
    copy = (SCPView*)malloc(sizeof(SCPView));
    assert(copy!=NULL);

    /*Allocate memory for mapping*/
    copy->columnMap=(int*)malloc(cols*sizeof(int));
    copy->rowMap=(int*)malloc(rows*sizeof(int));
    copy->parentColumnMap=(int*)malloc(cols*sizeof(int));
    copy->parentRowMap=(int*)malloc(rows*sizeof(int));

    assert(copy->columnMap!=NULL && copy->rowMap!=NULL&& copy->parentRowMap!=NULL && copy->parentColumnMap!=NULL);;

    /*Set dimensions*/
    copy->rows=rows;
    copy->columns=cols;
    copy->problem=v->problem;

    /*Return*/
    return copy;

}

SCPView* scp_view_get_copy(SCPView* v) {

    int i=0;
    SCPView* copy=NULL;

    /*Check parameters and coditions*/
    assert(v!=NULL);

    /*Create dumb copy*/
    copy=scp_view_get_dumb_copy(v,v->rows,v->columns);

    /*Copy mapping*/
    memcpy(copy->columnMap,v->columnMap,v->columns*sizeof(int));
    memcpy(copy->rowMap,v->rowMap,v->rows*sizeof(int));

    for(i=0;i<v->rows;i++) copy->parentRowMap[i]=i;
    for(i=0;i<v->columns;i++) copy->parentColumnMap[i]=i;

    /*Return*/
    return copy;
}

SCPView* scp_view_get_column_mask_subview(SCPView* v,unsigned char* mask,int trueVal) {

    int nr=0;
    int nc=0;
    int i=0;
    int j=0;
   

    SCPView* copy;

    /*Check parameters and conditions*/
    assert (v!=NULL && mask!=NULL);

    /*New subview will have same number of rows*/
    nr=v->rows;

    /*New subview will have different number of columns*/
    for(i=0;i<v->columns;i++) {
        if (mask[i]==trueVal) nc++;
    }

    /*Such subview does not exist*/
    if (nc<1) return NULL;

    /*Creating dumb copy of the view*/
    copy=scp_view_get_dumb_copy(v,nr,nc);

    /*Row mapping will be the same*/
    memcpy(copy->rowMap,v->rowMap,nr*sizeof(int));
    /*Rows of new copy will be mapped to rows of the original*/
    for(i=0;i<nr;i++) copy->parentRowMap[i]=i;

    /*Column mapping will be different*/
    j=0;
    for(i=0;i<v->columns;i++) {
        if (mask[i]==trueVal) {
            copy->columnMap[j]=v->columnMap[i];
            /*j-th row of the copy is mapped to i-th row of the original*/
            copy->parentColumnMap[j]=i;
            j++;
        }
    }

    /*Return that subproblem*/
    return copy;

}

SCPView* scp_view_get_column_list_subview(SCPView* v,IList* list) {

    int nr=0;
    int nc=0;
    int i=0;
    int j=0;


    SCPView* copy;

    /*Check parameters and conditions*/
    assert (v!=NULL && list!=NULL);

    /*New subview will have same number of rows*/
    nr=v->rows;

    /*New subview will have different number of columns*/
    nc=list->length;
    
    /*Such subview does not exist*/
    if (nc<1) return NULL;

    /*Creating dumb copy of the view*/
    copy=scp_view_get_dumb_copy(v,nr,nc);

    /*Row mapping will be the same*/
    memcpy(copy->rowMap,v->rowMap,nr*sizeof(int));
    /*Rows of new copy will be mapped to the rows of the original*/
    for(i=0;i<nr;i++) copy->parentRowMap[i]=i;

    /*Column mapping will be different*/
    i=0;
    ilist_start_iteration(list);
    while(ilist_iterate(list,&j)) {
        copy->columnMap[i]=v->columnMap[j];
        copy->parentColumnMap[i]=j;
        i++;
    }

    /*Return that subproblem*/
    return copy;

}

SCPView* scp_view_get_column_mask_subclone(SCPView* v,unsigned char* mask,int trueVal) {

    int nr=0;
    int nc=0;
    int i=0;
    int j=0;

    SCPView* copy;

    /*Check parameters and conditions*/
    assert (v!=NULL && mask!=NULL);

    /*New subview will have same number of rows*/
    nr=v->rows;

    /*New subview will have different number of columns*/
    for(i=0;i<v->columns;i++) {
        if (mask[i]==trueVal) nc++;
    }

    /*Such subview does not exist*/
    if (nc<1) return NULL;

    /*Creating dumb copy of the view*/
    copy=scp_view_get_dumb_copy(v,nr,nc);

    /*Row mapping will be the same*/
    memcpy(copy->rowMap,v->rowMap,nr*sizeof(int));
    memcpy(copy->parentRowMap,v->parentRowMap,nr*sizeof(int));

    /*Column mapping will be different*/
    j=0;
    for(i=0;i<v->columns;i++) {
        if (mask[i]==trueVal) {
            copy->columnMap[j]=v->columnMap[i];
            /*This is clone, so columns will be mapped to parents of the parent
              NOT to the parent itself*/
            copy->parentColumnMap[j]=v->parentColumnMap[i];
            j++;
        }
    }

    /*Return that subproblem*/
    return copy;

}

SCPView* scp_view_get_column_list_subclone(SCPView* v,IList* list) {

    int nr=0;
    int nc=0;
    int i=0;
    int j=0;

    SCPView* copy;

    /*Check parameters and conditions*/
    assert (v!=NULL && list!=NULL);

    /*New subview will have same number of rows*/
    nr=v->rows;

    /*New subview will have different number of columns*/
    nc=list->length;

    /*Such subview does not exist*/
    if (nc<1) return NULL;

    /*Creating dumb copy of the view*/
    copy=scp_view_get_dumb_copy(v,nr,nc);

    /*Row mapping will be the same*/
    memcpy(copy->rowMap,v->rowMap,nr*sizeof(int));
    memcpy(copy->parentRowMap,v->parentRowMap,nr*sizeof(int));

    /*Column mapping will be different*/
    i=0;
    ilist_start_iteration(list);
    while(ilist_iterate(list,&j)) {
        copy->columnMap[i]=v->columnMap[j];
        copy->parentColumnMap[i]=v->parentColumnMap[j];
        i++;
    }

    /*Return that subproblem*/
    return copy;

}

SCPView* scp_view_get_row_mask_subview(SCPView* v,unsigned char* mask,int trueVal) {

    int nr=0;
    int nc=0;
    int i=0;
    int j=0;


    SCPView* copy;

    /*Check parameters and conditions*/
    assert (v!=NULL && mask!=NULL);

    /*New subview will have same number of columns*/
    nc=v->columns;

    /*New subview will have different number of rows*/
    for(i=0;i<v->rows;i++) {
        if (mask[i]==trueVal) nr++;
    }

    /*Such subview does not exist*/
    if (nr<1) return NULL;

    /*Creating dumb copy of the view*/
    copy=scp_view_get_dumb_copy(v,nr,nc);

    /*Column mapping will be the same*/
    memcpy(copy->columnMap,v->columnMap,nc*sizeof(int));

    /*Columns of new copy will be the same as columns of original*/
    for(i=0;i<nc;i++) copy->parentColumnMap[i]=i;

    /*Row mapping will be different*/
    j=0;
    for(i=0;i<v->rows;i++) {
        if (mask[i]==trueVal) {
            copy->rowMap[j]=v->rowMap[i];
            /*j-th row of the copy is mapped to i-th row of the original*/
            copy->parentRowMap[j]=i;
            j++;
        }
    }

    /*Return that subproblem*/
    return copy;

}

SCPView* scp_view_get_row_list_subview(SCPView* v,IList* list) {

    int nr=0;
    int nc=0;
    int i=0;
    int j=0;


    SCPView* copy;

    /*Check parameters and conditions*/
    assert (v!=NULL && list!=NULL);

    /*New subview will have same number of columns*/
    nc=v->columns;

    /*New subview will have different number of rows*/
    nr=list->length;

    /*Such subview does not exist*/
    if (nr<1) return NULL;

    /*Creating dumb copy of the view*/
    copy=scp_view_get_dumb_copy(v,nr,nc);

    /*Column mapping will be the same*/
    memcpy(copy->columnMap,v->columnMap,nc*sizeof(int));
    /*Columns of new copy will be mapped to the columns of the original*/
    for(i=0;i<nc;i++) copy->parentColumnMap[i]=i;

    /*Row mapping will be different*/
    i=0;
    ilist_start_iteration(list);
    while(ilist_iterate(list,&j)) {
        copy->rowMap[i]=v->rowMap[j];
        copy->parentRowMap[i]=j;
        i++;
    }

    /*Return that subproblem*/
    return copy;

}

SCPView* scp_view_get_row_mask_subclone(SCPView* v,unsigned char* mask,int trueVal) {

    int nr=0;
    int nc=0;
    int i=0;
    int j=0;


    SCPView* copy;

    /*Check parameters and conditions*/
    assert (v!=NULL && mask!=NULL);

    /*New subview will have same number of columns*/
    nc=v->columns;

    /*New subview will have different number of rows*/
    for(i=0;i<v->rows;i++) {
        if (mask[i]==trueVal) nr++;
    }

    /*Such subview does not exist*/
    if (nr<1) return NULL;

    /*Creating dumb copy of the view*/
    copy=scp_view_get_dumb_copy(v,nr,nc);

    /*Column mapping will be the same*/
    memcpy(copy->columnMap,v->columnMap,nc*sizeof(int));
    memcpy(copy->parentColumnMap,v->parentColumnMap,nc*sizeof(int));
   

    /*Row mapping will be different*/
    j=0;
    for(i=0;i<v->rows;i++) {
        if (mask[i]==trueVal) {
            copy->rowMap[j]=v->rowMap[i];
            copy->parentRowMap[j]=v->parentRowMap[i];
            j++;
        }
    }

    /*Return that subproblem*/
    return copy;

}

SCPView* scp_view_get_row_list_subclone(SCPView* v,IList* list) {

    int nr=0;
    int nc=0;
    int i=0;
    int j=0;


    SCPView* copy;

    /*Check parameters and conditions*/
    assert (v!=NULL && list!=NULL);

    /*New subview will have same number of columns*/
    nc=v->columns;

    /*New subview will have different number of rows*/
    nr=list->length;

    /*Such subview does not exist*/
    if (nr<1) return NULL;

    /*Creating dumb copy of the view*/
    copy=scp_view_get_dumb_copy(v,nr,nc);

    /*Column mapping will be the same*/
    memcpy(copy->columnMap,v->columnMap,nc*sizeof(int));
    memcpy(copy->parentColumnMap,v->parentColumnMap,nc*sizeof(int));


    /*Row mapping will be different*/
    i=0;
    ilist_start_iteration(list);
    while(ilist_iterate(list,&j)) {
        copy->rowMap[i]=v->rowMap[j];
        copy->parentRowMap[i]=v->parentRowMap[j];
        i++;
    }

    /*Return that subproblem*/
    return copy;

}


SCPView* scp_view_get_row_and_column_mask_subview(SCPView* v,unsigned char* rowMask,unsigned char* columnMask,int trueVal) {

    int nr=0;
    int nc=0;
    int i,j;

    SCPView* copy;

    /*Check parameters and conditions*/
    assert (v!=NULL && columnMask!=NULL && rowMask!=NULL);

    /*Calculate new number of rows and columns*/
    for(i=0;i<v->columns;i++) {
        if (columnMask[i]==trueVal) nc++;
    }
    for(i=0;i<v->rows;i++) {
        if (rowMask[i]==trueVal) nr++;
    }

    /*Such subproblem does not exist*/
    if (nr<1 || nc<1) return NULL;

    /*Create copy with appropriate number of rows and columns*/
    copy=scp_view_get_dumb_copy(v,nr,nc);


    /*Calculate new column mapping*/
    j=0;
    for(i=0;i<v->columns;i++) {
        if (columnMask[i]==trueVal) {
            copy->columnMap[j]=v->columnMap[i];
            copy->parentColumnMap[j]=i;
            j++;
        }
    }

    /*Calculate new row mapping*/
    j=0;
    for(i=0;i<v->rows;i++) {
        if (rowMask[i]==trueVal) {
            copy->rowMap[j]=v->rowMap[i];
            copy->parentRowMap[j]=i;
            j++;
        }
    }


    /*Done, return that subproblem*/
    return copy;

}

SCPView* scp_view_get_row_and_column_list_subview(SCPView* v,IList* rowList,IList* columnList) {

    int nr=0;
    int nc=0;
    int i,j;

    SCPView* copy;

    /*Check parameters and conditions*/
    assert (v!=NULL && columnList!=NULL && rowList!=NULL);

    /*Calculate new number of rows and columns*/
    nr=rowList->length;
    nc=columnList->length;

    /*Such subproblem does not exist*/
    if (nr<1 || nc<1) return NULL;

    /*Create copy with appropriate number of rows and columns*/
    copy=scp_view_get_dumb_copy(v,nr,nc);


    /*Calculate new column mapping*/
    i=0;
    ilist_start_iteration(columnList);
    while(ilist_iterate(columnList,&j)) {
        copy->columnMap[i]=v->columnMap[j];
        copy->parentColumnMap[i]=j;
        i++;
    }

    /*Calculate new row mapping*/
    i=0;
    ilist_start_iteration(rowList);
    while(ilist_iterate(rowList,&j)) {
        copy->rowMap[i]=v->rowMap[j];
        copy->parentRowMap[i]=j;
        i++;
    }

    /*Done, return that subproblem*/
    return copy;

}

SCPView* scp_view_get_row_and_column_mask_subclone(SCPView* v,unsigned char* rowMask,unsigned char* columnMask,int trueVal) {

    int nr=0;
    int nc=0;
    int i,j;

    SCPView* copy;

    /*Check parameters and conditions*/
    assert (v!=NULL && columnMask!=NULL && rowMask!=NULL);

    /*Calculate new number of rows and columns*/
    for(i=0;i<v->columns;i++) {
        if (columnMask[i]==trueVal) nc++;
    }
    for(i=0;i<v->rows;i++) {
        if (rowMask[i]==trueVal) nr++;
    }

    /*Such subproblem does not exist*/
    if (nr<1 || nc<1) return NULL;

    /*Create copy with appropriate number of rows and columns*/
    copy=scp_view_get_dumb_copy(v,nr,nc);


    /*Calculate new column mapping*/
    j=0;
    for(i=0;i<v->columns;i++) {
        if (columnMask[i]==trueVal) {
            copy->columnMap[j]=v->columnMap[i];
            copy->parentColumnMap[j]=v->parentColumnMap[i];
            j++;
        }
    }

    /*Calculate new row mapping*/
    j=0;
    for(i=0;i<v->rows;i++) {
        if (rowMask[i]==trueVal) {
            copy->rowMap[j]=v->rowMap[i];
            copy->parentRowMap[j]=v->parentRowMap[i];
            j++;
        }
    }


    /*Done, return that subproblem*/
    
    return copy;

}

SCPView* scp_view_get_row_and_column_list_subclone(SCPView* v,IList* rowList,IList* columnList) {

    int nr=0;
    int nc=0;
    int i,j;

    SCPView* copy;

    /*Check parameters and conditions*/
    assert (v!=NULL && columnList!=NULL && rowList!=NULL);

    /*Calculate new number of rows and columns*/
    nr=rowList->length;
    nc=columnList->length;

    /*Such subproblem does not exist*/
    if (nr<1 || nc<1) return NULL;

    /*Create copy with appropriate number of rows and columns*/
    copy=scp_view_get_dumb_copy(v,nr,nc);


    /*Calculate new column mapping*/
    i=0;
    ilist_start_iteration(columnList);
    while(ilist_iterate(columnList,&j)) {
        copy->columnMap[i]=v->columnMap[j];
        copy->parentColumnMap[i]=v->parentColumnMap[j];
        i++;
    }

    /*Calculate new row mapping*/
    i=0;
    ilist_start_iteration(rowList);
    while(ilist_iterate(rowList,&j)) {
        copy->rowMap[i]=v->rowMap[j];
        copy->parentRowMap[i]=v->parentRowMap[j];
        i++;
    }


    /*Done, return that subproblem*/
    return copy;

}

void scp_view_swap_rows(SCPView* v,int r1,int r2) {

    int k=0;

    /*Check parameters and conditions*/
    assert (v!=NULL);
    assert (r1>=0 && r2>=0 && r1 < v->rows && r2 < v->rows);

    /*Nonsense swap*/
    if (r1==r2) return;

    /*Swapping*/
    k=v->rowMap[r1];
    v->rowMap[r1]=v->rowMap[r2];
    v->rowMap[r2]=k;

    k=v->parentRowMap[r1];
    v->parentRowMap[r1]=v->parentRowMap[r2];
    v->parentRowMap[r2]=k;

    /*Done*/

}


void scp_view_swap_columns(SCPView* v,int c1,int c2) {

    int k=0;

    /*Check parameters and conditions*/
    assert (v!=NULL);
    assert (c1>=0 && c2>=0 && c1 < v->columns && c2 < v->columns);

    /*Nonsense swap*/
    if (c1==c2) return;

    /*Swapping*/
    k=v->columnMap[c1];
    v->columnMap[c1]=v->columnMap[c2];
    v->columnMap[c2]=k;

    k=v->parentColumnMap[c1];
    v->parentColumnMap[c1]=v->parentColumnMap[c2];
    v->parentColumnMap[c2]=k;

    /*Done*/

}


int scp_view_get_covered_by_column(SCPView* v,int c) {

    int cntr=0;
    int i=0;
   

    /*Check parameters and conditions*/
    assert (v!=NULL);
    assert (c>=0 && c<v->columns);

    /*Calculate number of rows covered by column*/
    for(i=0;i<v->rows;i++) {
        if (scp_view_get(v,i,c)==1) cntr++;
    }

    /*Return*/
    return cntr;
}

int scp_view_get_2c_union_size(SCPView* v,int c1,int c2) {

    int cntr=0;
    int i=0;
    unsigned char v1;
    unsigned char v2;
    


    /*Check parameters and conditions*/
    assert (v!=NULL);
    assert (c1>=0 && c1<v->columns && c2>=0 && c2<v->columns);

    /*Calculate*/
    for(i=0;i<v->rows;i++) {
        v1=scp_view_get(v,i,c1);
        v2=scp_view_get(v,i,c2);
        if (v1!=0 || v2!=0) cntr++;
    }
    /*Return value*/
    return cntr;
}

int scp_view_get_1c_mask_union_size(SCPView* v,unsigned char* mask,int c1) {

    int cntr=0;
    int i=0;
    int k=0;

    unsigned char v1;
    

    /*Check parameters and conditions*/
    assert (v!=NULL && mask!=NULL);
    assert (c1>=0 && c1<v->columns);


    /*Calculate*/
    for(i=0;i<v->rows;i++) {
        v1=scp_view_get(v,i,c1);
        if (v1!=0 || mask[k]!=0) cntr++;
        k++;
    }

    /*Return*/
    return cntr;

}

int scp_view_get_negative_list_diference_size(SCPView* v,IList* rowList,int c1) {

    int cntr=0;
  
    int rowIndex=0;

    unsigned char v1;

    /*Check parameters and conditions*/
    assert (v!=NULL && rowList!=NULL);
    assert (c1>=0 && c1<v->columns);


    /*Calculate*/
    ilist_start_iteration(rowList);
    while(ilist_iterate(rowList,&rowIndex)) {
        
        v1=scp_view_get(v,rowIndex,c1);
        if (v1==1) cntr++;
    }

    /*Return*/
    return cntr;

}

int scp_view_get_1c_mask_intersect_size(SCPView* v,unsigned char* mask,int c1) {

    int cntr=0;
    int i=0;
    int k=0;

    unsigned char v1;
    

    /*Check parameters and conditions*/
    assert (v!=NULL && mask!=NULL);
    assert (c1>=0 && c1<v->columns);

    /*Calculate*/
    for(i=0;i<v->rows;i++) {
        v1=scp_view_get(v,i,c1);
        if (v1!=0 && mask[k]!=0) cntr++;
        k++;
    }

    /*Return*/
    return cntr;
}

int scp_view_get_columns_covering(SCPView* v,int r) {

    int cntr=0;
    int i=0;

    /*Check parameters and conditions*/
    assert (v!=NULL);
    assert (r >= 0 && r < v->rows);

    /*Calculate*/
    for(i=0;i<v->columns;i++) {
        if (scp_view_get(v,r,i)==1) cntr++;
    }

    /*Return*/
    return cntr;
}

int scp_view_is_solution(SCPView* v,unsigned char* x) {

    int j=0;
    int i=0;
    int k=0;
    unsigned char* tmp=NULL;

    /*Check parameters and conditions*/
    assert (v!=NULL && x!=NULL);

    /*Whether rows are covered*/
    tmp = (unsigned char*)malloc(v->rows);
    assert(tmp!=NULL);

    /*Zero*/
    memset(tmp,0,v->rows);
    k=0;
    for(j=0;j < v->columns;j++) {
        if (x[j]==0) continue;
        for(i=0;i<v->rows;i++) {
            if (tmp[i]==0 && scp_view_get(v,i,j)==1) {tmp[i]=1;k++;}
        }
    }
    
    /*All covered ?*/
    if (k==v->rows) j=1;else j=0;

    free(tmp);

    return j;

}

int scp_view_is_solution_d(SCPView* v,double* x) {

    int j=0;
    int i=0;
    int k=0;
    unsigned char* tmp=NULL;

    /*Check parameters and conditions*/
    assert (v!=NULL && x!=NULL);

    /*Whether rows are covered*/
    tmp = (unsigned char*)malloc(v->rows);
    assert(tmp!=NULL);

    /*Zero*/
    memset(tmp,0,v->rows);
    k=0;
    for(j=0;j < v->columns;j++) {
        if (x[j]!=0 && x[j]!=1) assert(0);
        if (x[j]==0) continue;
        for(i=0;i<v->rows;i++) {
            if (tmp[i]==0 && scp_view_get(v,i,j)==1) {tmp[i]=1;k++;}
        }
    }

    /*All covered ?*/
    if (k==v->rows) j=1;else j=0;

    /*for(i=0;i<v->rows;i++) {
        printf("i:%d\n",tmp[i]);
    }*/

    free(tmp);
    return j;

}


int scp_view_get_cost_mask(SCPView* v,unsigned char* mask,int count) {

    int sum=0;
    int j=0;

    /*Check parameters and conditions*/
    assert (v!=NULL && mask!=NULL);
    assert (count <= v->columns);

    /*Simply calculate sum*/
    for(j=0;j<count;j++) {
        if (mask[j]==1) sum+=v->problem->columnCosts[v->columnMap[j]];
    }

    return sum;

}

int scp_view_get_mask_coverage(SCPView* v,unsigned char* mask) {

    int i=0;
    int j=0;
    int cntr=0;
    unsigned char val;
    unsigned char* rowMask=NULL;

    /*Check parameters*/
    assert(v!=NULL && mask!=NULL);
    
    rowMask=(unsigned char*)malloc(v->rows);
    assert(rowMask!=NULL);
    memset(rowMask,0,v->rows);

    for(i=0;i<v->columns;i++) {
        if (mask[i]==0) continue;
        
        for(j=0;j<v->rows;j++) {
            
            if (rowMask[j]==0 && (val=scp_view_get(v,j,i)==1) ) {
                cntr++;
                rowMask[j]=val;
            }
            
        }
    }

    free(rowMask);
    return cntr;
}

void scp_view_modify_for_gth(SCPView* v,int startColumn,int endColumn) {

    /*This is dangerous operation, because modified view's
     *parentRowMap is one field shorter than it should be, so
     *it can't be used
     */
    int i=0;
    int delta=0;

    /*Check parameters and conditions*/
    assert(v!=NULL);

    /*Temporarily enlarge underlying SCP*/
    v->problem->rows++;
    /*Temporarily enlarge view*/
    v->rows++;

    /*Realloc rowMap*/
    v->rowMap=(int*)realloc(v->rowMap,sizeof(int)*v->rows);
    v->parentRowMap=(int*)realloc(v->parentRowMap,sizeof(int)*v->rows);
    assert(v->rowMap!=NULL && v->parentRowMap!=NULL);
    
    /*Modified view's last row is mapped to spare row of underlying SCP*/
    v->rowMap[v->rows-1]=v->problem->rows-1;
    v->parentRowMap[v->rows-1]=v->problem->rows-1;

    /*Set ones where necessary*/
    delta=endColumn-startColumn+1;
    for(i=0;i<delta;i++) {
        scproblem_spare_row_set(v->problem,v->columnMap[i],1);
    }
    /*Done*/
}

void scp_view_demodify_for_gth(SCPView* v) {

    /*Check parameter*/
    assert(v!=NULL);

    v->problem->rows--;
    v->rows--;

    /*Clear spare row*/
    memset(v->problem->data+v->problem->rows*v->problem->columns,0,v->columns);

    /*Reallocate memory for row map*/
    
    v->rowMap=(int*)realloc(v->rowMap,sizeof(int)*v->rows);
    v->parentRowMap=(int*)realloc(v->parentRowMap,sizeof(int)*v->rows);
    
    assert(v->rowMap!=NULL && v->parentRowMap!=NULL);
    /*Done*/
}

void scp_view_remove_dominance(SCPView** v) {

    unsigned char* rm;
    unsigned char* cm;

    int rsuc=0;
    int clmsuc=0;

    SCPView* nv=*v;
    SCPView* pv=NULL;

    next:

    rm=scp_view_remove_row_dominance(nv,&rsuc);
    cm=scp_view_remove_column_dominance(nv,&clmsuc);
    

    if (rsuc==0 && clmsuc==0) {
        free(rm);
        free(cm);
        goto f_end;
    }

    if (rsuc==1 && clmsuc==1) {
         pv = nv;
         nv = scp_view_get_row_and_column_mask_subclone(pv,rm,cm,1);
         scp_view_delete(pv);
        
    }

    if (rsuc==1 && clmsuc==0) {
         pv = nv;
         nv = scp_view_get_row_mask_subclone(pv,rm,1);
         scp_view_delete(pv);
    }

    if (rsuc==0 && clmsuc==1) {
         pv=nv;
         nv = scp_view_get_column_mask_subclone(pv,cm,1);
         scp_view_delete(pv);
    }

    
    free(cm);
    free(rm);

    goto next;

    f_end:
    (*v)=nv;
    
}


unsigned char* scp_view_remove_row_dominance(SCPView* v,int* suc) {

    unsigned char* mask=NULL;
    int i=0,j=0;
    int k=0,q=0;
    unsigned char v1,v2;

    *suc=0;

    /*Check parameters*/
    assert(v!=NULL);
    mask=(unsigned char*)malloc(v->rows);
    assert(mask!=NULL);
    memset(mask,1,v->rows);

    for(j=0;j<v->rows;j++) {

        if (mask[j]==0) continue;

        for(i=0;i<j;i++) {

            if (mask[i]==0) continue;

            q=1;
            for(k=0;k<v->columns;k++) {
                v1=scp_view_get(v,j,k);
                /*If i-th row does not have 1 as j-th row, j-th
                 *row does not dominate i-tj row*/
                if (v1==1 && (v2=scp_view_get(v,i,k))==0) {q=0;break;}
            }
            if (q==1) {mask[i]=0;*suc=1;}

        }
        for(i=j+1;i<v->rows;i++) {
            if (mask[i]==0) continue;
            q=1;
            for(k=0;k<v->columns;k++) {
                v1=scp_view_get(v,j,k);
                /*If i-th row does not have 1 as j-th row, j-th
                 *row does not dominate i-tj row*/
                if (v1==1 && (v2=scp_view_get(v,i,k))==0) {q=0;break;}
            }
            if (q==1) {mask[i]=0;*suc=1;}
        }
    }

    /*Only masked rows can stay in the solution*/
    return mask;
}

unsigned char* scp_view_remove_column_dominance(SCPView* v,int* suc) {

    unsigned char* mask=NULL;
    int i=0,j=0;
    int k=0,q=0;
    unsigned char v1,v2;
    int cj,ci;

    /*Check parameters*/
    assert(v!=NULL);
    mask=(unsigned char*)malloc(v->columns);
    assert(mask!=NULL);
    memset(mask,1,v->columns);

    *suc=0;

    for(j=0;j<v->columns;j++) {

        if (mask[j]==0) continue;
        cj=scp_view_get_cost(v,j);

        for(i=0;i<j;i++) {

            if (mask[i]==0) continue;
            ci=scp_view_get_cost(v,i);
            if (cj!=ci) continue;

            q=1;
            for(k=0;k<v->rows;k++) {
                v2=scp_view_get(v,k,i);
                if (v2==1 && (v1=scp_view_get(v,k,j))==0) {q=0;break;}
            }
            if (q==1) {mask[i]=0;*suc=1;}

        }

        for(i=j+1;i<v->columns;i++) {
            if (mask[i]==0) continue;
            
            ci=scp_view_get_cost(v,i);
            if (cj!=ci) continue;
            q=1;
            for(k=0;k<v->rows;k++) {
                v2=scp_view_get(v,k,i);
                if (v2==1 && (v1=scp_view_get(v,k,j))==0) {q=0;break;}
            }
            if (q==1) {mask[i]=0;*suc=1;}
        }
    }
    return mask;
    
}

IList* scp_view_remove_fixed_columns(SCPView** v) {
    
    IList* columnList=NULL;
    IList* rowList=NULL;
    IList* parentList=NULL;
    
    int i=0,j=0,c=0,cntr=0;
    unsigned char* columnMask=NULL;
    unsigned char* rowMask=NULL;
    int rows=0,cols=0;
    SCPView* nv;

    assert(v!=NULL && (*v)!=NULL);

    columnList=ilist_new();
    rowList=ilist_new();
    parentList=ilist_new();


    rows=(*v)->rows;
    cols=(*v)->columns;

    for(j=0;j<rows;j++) {
        c=-1;
        cntr=0;

        for(i=0;cntr<3 && i<cols;i++) {
            if (scp_view_get(*v,j,i)==1) {cntr++;c=i;}
        }
        assert(cntr>0); /*If cntr==0, problem is not solvable*/
        if (cntr==1) {
            ilist_append(columnList,c);
            ilist_append(parentList,(*v)->parentColumnMap[c]);
        }
    }

    columnMask=(unsigned char*)malloc(cols);
    rowMask=(unsigned char*)malloc(rows);

    assert(rowMask!=NULL && columnMask!=NULL);

    /*We have to examine what rows are covered by columns selected
     *to be removed
     */
    ilist_start_iteration(columnList);
    while(ilist_iterate(columnList,&c)) {
        for(j=0;j<rows;j++) {
            if (scp_view_get((*v),j,c)==1) ilist_append(rowList,j);
        }
    }
    
    ilist_make_mask(columnList,columnMask,cols,1);
    ilist_make_mask(rowList,rowMask,rows,1);

    nv=scp_view_get_row_and_column_mask_subclone(*v,rowMask,columnMask,0);
    scp_view_delete(*v);
    *v=nv;

    ilist_delete(rowList);
    ilist_delete(columnList);
    
    free(columnMask);
    free(rowMask);
    
    return parentList;

}



int scp_view_check_solvable(SCPView* v) {

    int i=0;
    int j=0;
    unsigned char tag=0;

    /*Check parameter*/
    assert(v!=NULL);

    for(i=0;i<v->rows;i++) {
        tag=0;
        for(j=0;j<v->columns;j++) {
            if (scp_view_get(v,i,j)==1) {
                tag=1;
                break;
            }
        }
        /*There is no column that cover i-th row*/
        if (tag==0) return 0;
    }
    
    return 1;
}



void scp_view_print(SCPView* v,int showMaps) {

    int i=0;
    int j=0;

    /*General information*/
    printf("SCPView {");
    if (v==NULL) {
        printf("!!! NULL !!!\n}\n");
        return;
    }
    else {
        printf("R:%d,C:%d\n}\n",v->rows,v->columns);
    }

    printf("MATRIX:\n");
    for(i=0;i<v->rows;i++) {
        for(j=0;j<v->columns;j++) {
            printf("%d",scp_view_get(v,i,j));
        }
        printf("\n");
    }

    for(j=0;j<v->columns;j++) {
        printf("C:");
        printf("%d ",scp_view_get_cost(v,j));
    }

    printf("\n");

    if (showMaps==1) {
        printf("COLMAP: VIEW -> PARENT -> SCP  COST:\n");
        for(i=0;i<v->columns;i++) {
            printf("%02d  %02d  %02d  C:%d\n",i,v->parentColumnMap[i],v->columnMap[i],scp_view_get_cost(v,i));
        }

        printf("ROWMAP: VIEW -> SCP\n");
        for(i=0;i<v->rows;i++) {
            printf("%02d  %02d  %02d\n",i,v->parentRowMap[i],v->rowMap[i]);
        }
    }


}

