
function [ edgeBB , routEdgeLevel , XgH_BaseGrid , XgV_BaseGrid , XgSH , XgSV ] =  build_connections()


global s0 p0 layer maxLevel numBlocks max_row_idx max_clm_idx q0 
global ugH ucH  ugV ucV  ugHX ucHX  ugVX ucVX  ugx ucx

bb_max_row_idx = max_row_idx / sqrt ( numBlocks ) ; 
bb_max_clm_idx = max_clm_idx / sqrt ( numBlocks ) ;
N0 = bb_max_row_idx * bb_max_clm_idx ;

%%%%%%%%%%%%%%% EDGE ASSIGNMENTS %%%%%%%%%%%%%%%%%%%%%%
numEdges = ( ( max_row_idx - 1 ) * max_row_idx ) * 2 ;

bbBoundBox = mapBB ( max_clm_idx , numBlocks ) ;

edgeBB = sparse(numEdges,1) ;
sigEdgeCong = sparse ( numEdges , 1 ) ;
PGEdgeCong = sparse ( numEdges , 1 ) ;
numEdgesPerBB = ( ( max_clm_idx / sqrt(numBlocks) - 1 ) * ( max_clm_idx / sqrt(numBlocks) ) )* 2;

%% assign each edge a bbid
%% edgeBB ( matlabeid + 1 )
%% BB assignments
%% 4->5->6 
%% 1->2->3

%% Vertical
for i=1:max_row_idx
    for j=1:max_clm_idx-1
        gx1 = i ;
        gy1 = j ;
        gx2 = i ;
        gy2 = j + 1;
        bb=0;
        for k=1:numBlocks
            if (gy1 >= bbBoundBox(k).minRow & gx1 >= bbBoundBox(k).minClm & gy2 <= bbBoundBox(k).maxRow & gx2 <= bbBoundBox(k).maxClm)
                bb = k ;
            end
        end
        g1 = matlabGxGy_to_matlabGid ( gx1, gy1, max_clm_idx ) ; 
        g2 = matlabGxGy_to_matlabGid ( gx2, gy2, max_clm_idx ) ;
        
        eid = matlabGid_to_matlabEdge ( g1, g2, max_clm_idx ) ;
        
        edgeBB(eid) = bb ;
        
    end
end

% %% HORIZONTAL
for i=1:max_row_idx
    for j=1:max_clm_idx-1
        gy1 = i ;
        gx1 = j ;
        gy2 = i ;
        gx2 = j+1 ;
        bb=0;
        for k=1:numBlocks
            if (gy1 >= bbBoundBox(k).minRow & gx1 >= bbBoundBox(k).minClm & gy2 <= bbBoundBox(k).maxRow & gx2 <= bbBoundBox(k).maxClm)
                bb = k ;  
            end
        end
        g1 = matlabGxGy_to_matlabGid ( gx1, gy1, max_clm_idx ) ; 
        g2 = matlabGxGy_to_matlabGid ( gx2, gy2, max_clm_idx ) ;
        
        eid = matlabGid_to_matlabEdge ( g1, g2, max_clm_idx ) ;
        
        edgeBB(eid) = bb ;
        
    end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Build Insertion Matrix %%%%%%%%%%%%%%%%%%%%

XgH_BaseGrid.x = sparse(N0,N0);
XgV_BaseGrid.x = sparse(N0,N0);

XgH_nom.x=sparse(N0,N0);
XgV_nom.x=sparse(N0,N0);
 

for i=1:maxLevel
        XgSH(i).x=sparse(N0,N0);
        XgSV(i).x=sparse(N0,N0);
        XgSH_rout(i).x = sparse(N0,N0) ;
end

% Build Base Grid Connections
 
%% East
for i=1:bb_max_clm_idx-1
    gx1=i;
    gy1=1;
    gx2=i+1;
    gy2=1;
    XgH_BaseGrid.x=set_loc(gx1,gy1,gx2,gy2,bb_max_row_idx,XgH_BaseGrid.x); 
    gx1=i;
    gy1=bb_max_clm_idx;
    gx2=i+1;
    gy2=bb_max_clm_idx;
    XgH_BaseGrid.x=set_loc(gx1,gy1,gx2,gy2,bb_max_row_idx,XgH_BaseGrid.x); 
end

%North
for i=1:bb_max_row_idx-1
    gx1=1;
    gy1=i;
    gx2=1;
    gy2=i+1;
    XgH_BaseGrid.x=set_loc(gx1,gy1,gx2,gy2,bb_max_row_idx,XgH_BaseGrid.x); 
    gx1=bb_max_row_idx;
    gy1=i;
    gx2=bb_max_row_idx;
    gy2=i+1;
    XgH_BaseGrid.x=set_loc(gx1,gy1,gx2,gy2,bb_max_row_idx,XgH_BaseGrid.x); 
end

%Vertical Base insertion matrix

gx1=1;
gy1=1;
XgV_BaseGrid.x = set_loc(gx1,gy1,gx1,gy1,bb_max_row_idx,XgV_BaseGrid.x);
gx1=1;
gy1=bb_max_row_idx;
XgV_BaseGrid.x = set_loc(gx1,gy1,gx1,gy1,bb_max_row_idx,XgV_BaseGrid.x);
gx1=bb_max_clm_idx;
gy1=1;
XgV_BaseGrid.x = set_loc(gx1,gy1,gx1,gy1,bb_max_row_idx,XgV_BaseGrid.x);
gx1=bb_max_clm_idx;
gy1=bb_max_row_idx;
XgV_BaseGrid.x = set_loc(gx1,gy1,gx1,gy1,bb_max_row_idx,XgV_BaseGrid.x);


%% Uze Base Grid Information to build sensitivity for level 1
gx1=(bb_max_clm_idx-1)/2 + 1;
gy1=1;
gx2=gx1;
gy2=(bb_max_row_idx);
XgSH(1).x = set_loc(gx1,gy1,gx2,gy2,bb_max_row_idx,XgSH(1).x);

gy1=(bb_max_clm_idx-1)/2 + 1;
gx1=1;
gy2=gy1;
gx2=bb_max_row_idx;
XgSH(1).x = set_loc(gx1,gy1,gx2,gy2,bb_max_row_idx,XgSH(1).x);

gx1=(bb_max_row_idx-1)/2 + 1;
gy1=1;
XgSV(1).x = set_loc(gx1,gy1,gx1,gy1,bb_max_row_idx,XgSV(1).x);

gx1=1;
gy1=(bb_max_row_idx-1)/2 + 1;
XgSV(1).x = set_loc(gx1,gy1,gx1,gy1,bb_max_row_idx,XgSV(1).x);

gx1=bb_max_row_idx;
gy1=(bb_max_row_idx-1)/2 + 1;
XgSV(1).x = set_loc(gx1,gy1,gx1,gy1,bb_max_row_idx,XgSV(1).x);

gx1=(bb_max_row_idx-1)/2 + 1;
gy1=bb_max_row_idx;
XgSV(1).x = set_loc(gx1,gy1,gx1,gy1,bb_max_row_idx,XgSV(1).x);

%%% Build insertion matrix for routing

for i=1:bb_max_clm_idx-1
    gx1 = (bb_max_clm_idx-1)/2 + 1 ;
    gy1 =  i ;
    gx2 = gx1 ;
    gy2 = i+1 ;
    XgSH_rout(1).x = set_loc1(gx1,gy1,gx2,gy2,bb_max_row_idx,XgSH_rout(1).x) ;

    gy1 = (bb_max_clm_idx-1)/2 + 1 ;
    gx1 = i ;
    gy2 = gy1 ; 
    gx2 = i+1  ;
    XgSH_rout(1).x = set_loc1(gx1,gy1,gx2,gy2,bb_max_row_idx,XgSH_rout(1).x) ;
end

for i=2:maxLevel
    iter=2^(i-1);  %% # iterations on a row
    idx=1;  
    tileSize = (bb_max_clm_idx-1)/iter;
    for j=1:iter
        startRow=tileSize*(j-1)+1;
        endRow = startRow+tileSize;
        startClm=1;
        
        for k=1:iter
            endClm=startClm+tileSize;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% SENSITIVITIES %%%%%%%%%%%%         
            tmp=sparse(N0,N0);
            gx1=(endClm-startClm)/2 + startClm;
            gy1=startRow;
            gx2=gx1;
            gy2=endRow;
            XgSH(i).x = set_loc(gx1,gy1,gx2,gy2,bb_max_row_idx,XgSH(i).x) ;
            
            gx1 = startClm;
            gy1 = (endRow-startRow)/2 + startRow;
            gx2 = endClm;
            gy2 = gy1;
            XgSH(i).x = set_loc(gx1,gy1,gx2,gy2,bb_max_row_idx,XgSH(i).x) ;

            tmp=sparse(N0,N0);
            gx1=(endClm-startClm)/2 + startClm;
            gy1=startRow;
            XgSV(i).x = set_loc(gx1,gy1,gx1,gy1,bb_max_row_idx,XgSV(i).x) ;
            
            gx1=(endClm-startClm)/2 + startClm;
            gy1=endRow;
            XgSV(i).x = set_loc(gx1,gy1,gx1,gy1,bb_max_row_idx,XgSV(i).x) ;
            
            gx1=startClm;
            gy1=(endRow-startRow)/2 + startRow;
            XgSV(i).x = set_loc(gx1,gy1,gx1,gy1,bb_max_row_idx,XgSV(i).x) ;
            
            gx1=endClm;
            gy1=(endRow-startRow)/2 + startRow;
            XgSV(i).x = set_loc(gx1,gy1,gx1,gy1,bb_max_row_idx,XgSV(i).x) ;
            
            %% build insertion for routing
            for mm=startRow:endRow-1
                gx1=(endClm-startClm)/2 + startClm ;
                gy1 = mm ;
                gx2 = gx1 ; 
                gy2 = mm+1 ; 
                XgSH_rout(i).x = set_loc1(gx1,gy1,gx2,gy2,bb_max_row_idx,XgSH_rout(i).x) ;
            end
            
            for nn=startClm:endClm-1
                gx1 = nn ;
                gy1 = (endRow-startRow)/2 + startRow;
                gx2 = nn+1 ;
                gy2 = gy1 ;
                XgSH_rout(i).x = set_loc1(gx1,gy1,gx2,gy2,bb_max_row_idx,XgSH_rout(i).x) ;
            end
            
            startClm=endClm;
        end
    end
end

%%%%%%%%%%%%%%  ASSIGN EDGES A SENSITIVITY LEVEL %%%%%%%%%%%%%%%%

routEdgeLevel = sparse ( numEdges , 1 ) ;
  for kk=1:maxLevel

    [aa,bb,cc]=find (XgSH_rout(1,kk).x) ;
    [mm,nn]=size(aa) ;
    for i=1:mm
       gid1 = aa(i) ;
       gid2 = bb(i) ;
       if(gid1~=gid2)

           %%%%%%%%%%%%%%  INITIAL GRID 00 %%%%%%%%%%%%%%%%%

           [ gx1, gy1 ] = matlabGid_to_matlabGxGy ( gid1 , bb_max_clm_idx ) ; 
           [ gx2, gy2 ] = matlabGid_to_matlabGxGy ( gid2 , bb_max_clm_idx ) ;

           for j=1:sqrt(numBlocks)
           %   display('move up vertically')
               tgx1 = gx1 ; 
               tgy1 = gy1 + (j-1)*bb_max_clm_idx ; 
               tgx2 = gx2 ; 
               tgy2 = gy2 + (j-1)*bb_max_clm_idx ; 

               gid1 = matlabGxGy_to_matlabGid ( tgx1 , tgy1 , max_clm_idx ) ;
               gid2 = matlabGxGy_to_matlabGid ( tgx2 , tgy2 , max_clm_idx ) ;
               eid = matlabGid_to_matlabEdge ( gid1, gid2, max_clm_idx ) ;

               routEdgeLevel ( eid , 1 ) = kk ; 

        %% move across horizontally
                for k=1:sqrt(numBlocks)-1

                    tgx1 = gx1  + (k)*bb_max_clm_idx ;
                    tgy1 = tgy1  ;
                    tgx2 = gx2 + (k)*bb_max_clm_idx ;
                    tgy2 = tgy2 ;

                    gid1 = matlabGxGy_to_matlabGid ( tgx1 , tgy1 , max_clm_idx ) ;
                    gid2 = matlabGxGy_to_matlabGid ( tgx2 , tgy2 , max_clm_idx ) ;
                    eid = matlabGid_to_matlabEdge ( gid1, gid2, max_clm_idx ) ;

                    routEdgeLevel ( eid , 1 ) = kk ;  

                end
           end
       end
    end
  end
