.packageName <- "inetwork"
`iassortativity` <-
function(A) {
 if (!is.matrix(A)) return("error: input is not a matrix")
 if (dim(A)[1] != dim(A)[2]) return("error: matrix is not square")
 if (dim(A)[1] < 3) return("network is trivial")
 if (any(A>1)) return("error: not an unweighted adjacency matrix")
 if (any(A<0)) return("error: not an unweighted adjacency matrix")

 k <- numeric()
 for (i in 1:dim(A)[1]) k[i] <- sum(A[i,])
 
 knn <- numeric()
 for (i in 1:dim(A)[1]) {
     knn[i] <- 0
     for (j in 1:dim(A)[1]) knn[i] <- knn[i] + A[i,j]*k[j]
     if (k[i] > 0) knn[i] <- knn[i]/k[i]
     else knn[i] <- 0
 }
 #Knn(k)
 Knnk <- numeric()
 for (h in 1:max(k)) {
     Knnk[h] <- 0
     j <- 0
     for (i in 1:dim(A)[1]) {
         if (k[i] == h) {
            Knnk[h] <- Knnk[h] + knn[i]
            j <- j + 1
         }
     }
     if (j > 0) Knnk[h] <- Knnk[h]/j
 }
 return(list(knn=knn,Knnk=Knnk))
}

`icommunity` <-
function(A,nodes=NULL,partite=FALSE) {
 if (!is.matrix(A)) return("error: input is not a matrix")
 if (dim(A)[1] != dim(A)[2]) return("error: matrix is not square")
 if (dim(A)[1] < 3) return("network is trivial")
 if (any(A>1)) return("error: not an unweighted adjacency matrix")
 if (any(A<0)) return("error: not an unweighted adjacency matrix")

 degree <- numeric()
 degre1 <- numeric()
 for (i in 1:dim(A)[1]) {
     degree[i] <- sum(A[i,])
     degre1[i] <- sum(A[,i])
 }
 degre1 <- degree-degre1
 if (any(degre1 != 0)) return("error: matrix is not symmetric")
 
 Q <- numeric()
 sizes <- numeric()
 indivisibles <- character()
 ringleaders <- numeric()
 arrows <- numeric()
 xcoordinates <- numeric()
 ycoordinates <- numeric()
 if (!is.data.frame(nodes) & is.null(nodes)) nodes <- as.character(1:dim(A)[1])

 B <- matrix(nrow=dim(A)[1],ncol=dim(A)[1],data=0)
 for (i in 1:dim(A)[1]) {
     for (j in 1:dim(A)[1]) {
         B[i,j] = A[i,j]-degree[i]*degree[j]/sum(degree)
     }
 }
 if (partite) B <- -B
 eigenB <- eigen(B, symmetric=TRUE)
 iz <- which(degree==0)
 clusters <- list(Q=Q,sizes=sizes,indivisibles=indivisibles,ringleaders=ringleaders,arrows=arrows,xcoordinates=xcoordinates,ycoordinates=ycoordinates,indices=iz,singlets=nodes[iz])

 newman <- function(eigenvector1,B,nodes,indices,clusters,origin) {
  eigenB <- eigen(B, symmetric=TRUE)
  if (eigenB$values[1] <= 0) {
     clusters$sizes <- c(clusters$sizes,dim(B)[1])
     clusters$indivisibles <- c(clusters$indivisibles,nodes)
     clusters$ringleaders <- c(clusters$ringleaders,abs(eigenvector1))
     clusters$indices <- c(clusters$indices,indices)
     for (i in 1:dim(B)[1]) clusters$xcoordinates <- c(clusters$xcoordinates,origin[1])
     for (i in 1:dim(B)[1]) clusters$ycoordinates <- c(clusters$ycoordinates,origin[2]-i)
     return(clusters)
  }
  ip <- which(eigenB$vectors[,1] > 0)
  im <- which(eigenB$vectors[,1] < 0)
  dQ <- sum(abs(eigenB$vectors[c(ip,im),1]))^2 *eigenB$values[1]
  #clusters$Q <- c(clusters$Q, dQ)
  iz <- which(eigenB$vectors[,1] ==0)
  bp <- length(ip)
  bm <- length(im)
  arrows <- origin
  arrows[3] <- origin[1]
  arrows[4] <- origin[2] - dQ^(1/3)
  arrows[5:6] <- arrows[3:4]
  arrows[8] <- arrows[4]
  arrows[9:10] <- arrows[3:4]
  arrows[12] <- arrows[4]
  if (bp >= bm) {
     arrows[7] <- origin[1] + bp
     arrows[11] <- origin[1] - bm    
  } else {
     arrows[7] <- origin[1] + bm 
     arrows[11] <- origin[1] - bp
  }
  
  #print(paste(as.character(dim(B)[1]),as.character(bp),as.character(bm)))
  if (length(iz) > 0) {
     clusters$sizes <- c(clusters$sizes,rep(1,length(iz)))
     clusters$indivisibles <- c(clusters$indivisibles,nodes[iz])
     clusters$ringleaders <- c(clusters$ringleaders,eigenB$vectors[iz,1])
     clusters$indices <- c(clusters$indices,indices[iz])
     for (i in 1:length(iz)) clusters$xcoordinates <- c(clusters$xcoordinates,arrows[3]+i-1)
     for (i in 1:length(iz)) clusters$ycoordinates <- c(clusters$ycoordinates,arrows[4])
  }

  if ((bp+bm) == 0) return(clusters)

  if (bp == 0 || bm == 0) {
     clusters$sizes <- c(clusters$sizes,bp+bm)
     clusters$indivisibles <- c(clusters$indivisibles,nodes[c(ip,im)])
     clusters$ringleaders <- c(clusters$ringleaders,abs(eigenB$vectors[c(ip,im),1]))
     clusters$indices <- c(clusters$indices,indices[ip],indices[im])
     for (i in 1:(bp+bm)) clusters$xcoordinates <- c(clusters$xcoordinates,origin[1])
     for (i in 1:(bp+bm)) clusters$ycoordinates <- c(clusters$ycoordinates,origin[2]-i)
     return(clusters) 
  }

  clusters$Q <- c(clusters$Q, dQ)
  clusters$arrows <- c(clusters$arrows,arrows)

  if (bp == 1) {
     clusters$sizes <- c(clusters$sizes,1)
     clusters$indivisibles <- c(clusters$indivisibles,nodes[ip])
     clusters$ringleaders <- c(clusters$ringleaders,abs(eigenB$vectors[ip,1]))
     #clusters$Q <- clusters$Q + eigenB$vectors[ip,1]^2 * eigenB$values[1]
     clusters$indices <- c(clusters$indices,indices[ip])
     if (bm == 1) clusters$xcoordinates <- c(clusters$xcoordinates,arrows[3]+1)
     else clusters$xcoordinates <- c(clusters$xcoordinates,arrows[3]-1)
     clusters$ycoordinates <- c(clusters$ycoordinates,arrows[4]-1)
  } else {
     Bp <- matrix(nrow=bp,ncol=bp,data=0)
     #for (i in 1:bp) {
     #    for (j in 1:bp) {
     #        k <- ip[i]
     #        l <- ip[j]
     #        Bp[i,j] <- B[k,l]
     #    }
     #}
     Bp <- B[ip,ip]
     for (i in 1:bp) Bp[i,i] <- Bp[i,i]-sum(Bp[i,])
     #eigenBp <- eigen(Bp, symmetric=TRUE)     
     if (bp >= bm) clusters <- newman(eigenB$vectors[ip,1],Bp,nodes[ip],indices[ip],clusters,arrows[7:8])
     else clusters <- newman(eigenB$vectors[ip,1],Bp,nodes[ip],indices[ip],clusters,arrows[11:12])
  }

  if (bm == 1) {
     clusters$sizes <- c(clusters$sizes,1)
     clusters$indivisibles <- c(clusters$indivisibles,nodes[im])
     clusters$ringleaders <- c(clusters$ringleaders,abs(eigenB$vectors[im,1]))
     #clusters$Q <- clusters$Q + eigenB$vectors[im,1]^2 * eigenB$values[1]
     clusters$indices <- c(clusters$indices,indices[im])
     clusters$xcoordinates <- c(clusters$xcoordinates,arrows[3]-1)
     clusters$ycoordinates <- c(clusters$ycoordinates,arrows[4]-1)
     return(clusters)
  }
  Bm <- matrix(nrow=bm,ncol=bm,data=0)
  #for (i in 1:bm) {
  #    for (j in 1:bm) {
  #        k <- im[i]
  #        l <- im[j]
  #        Bm[i,j] <- B[k,l]
  #    }
  #}
  Bm <- B[im,im]
  for (i in 1:bm)  Bm[i,i] <- Bm[i,i]-sum(Bm[i,])
  #eigenBm <- eigen(Bm, symmetric=TRUE)
  #print(eigenBm$vectors[,1])
  if (bp >= bm) clusters <- newman(eigenB$vectors[im,1],Bm,nodes[im],indices[im],clusters,arrows[11:12])
  else clusters <- newman(eigenB$vectors[im,1],Bm,nodes[im],indices[im],clusters,arrows[7:8])
 } # end of newman

 if (eigenB$values[1] <= 0) {
    clusters$sizes <- dim(A)[1]-length(iz)
    clusters$indivisibles <- nodes[-iz]
    clusters$ringleaders <- abs(eigenB$vectors[-iz,1])
    clusters$indices <- (1:dim(A)[1])[-iz]
 } else {
    iz <- which(degree!=0)
    clusters <- newman(eigenB$vectors[iz,1],B[iz,iz],nodes[iz],iz,clusters,c(0,0))
 }
 clusters$Q <- clusters$Q/sum(A)/2
 #if (partite) clusters$Q <- -clusters$Q
 clusters <- c(list(A=A),clusters)
 return(clusters)
} # end of mycluster

`ihierarchy` <-
function(clusters,fan=FALSE,spread=1) {
 if (sum(clusters$Q) == 0) return("the network is indivisible")
 op <- par()$mar
 par(mar=c(1.1,2.1,1.1,2.1))

 if (fan) {
    if (spread < 0.01) spread <- 0.01
    x <- abs(clusters$ycoordinates)*cos((spread*clusters$xcoordinates-90)*pi/180)
    y <- abs(clusters$ycoordinates)*sin((spread*clusters$xcoordinates-90)*pi/180)
 } else {
    x <- clusters$xcoordinates
    y <- clusters$ycoordinates
 }

 plot(c(0,x),c(0,y),pch="",axes=FALSE,ann=FALSE)
 for (i in 1:(length(clusters$arrows)/12)) {
     if (fan) {
        x1 <- abs(clusters$arrows[(i-1)*12+2])*cos((spread*clusters$arrows[(i-1)*12+1]-90)*pi/180)
        y1 <- abs(clusters$arrows[(i-1)*12+2])*sin((spread*clusters$arrows[(i-1)*12+1]-90)*pi/180)
        x2 <- abs(clusters$arrows[(i-1)*12+4])*cos((spread*clusters$arrows[(i-1)*12+3]-90)*pi/180)
        y2 <- abs(clusters$arrows[(i-1)*12+4])*sin((spread*clusters$arrows[(i-1)*12+3]-90)*pi/180)
        arrows(x1,y1,x2,y2,length=0)
        r <- abs(clusters$arrows[(i-1)*12+4])
        x1 <- r*cos((spread*clusters$arrows[(i-1)*12+7]-90)*pi/180)
        y1 <- r*sin((spread*clusters$arrows[(i-1)*12+7]-90)*pi/180)
        x2 <- r*cos((spread*clusters$arrows[(i-1)*12+11]-90)*pi/180)
        y2 <- r*sin((spread*clusters$arrows[(i-1)*12+11]-90)*pi/180)
        if (y1 < 0 & y2 < 0) { 
           curve(-sqrt(r*r-x^2),from=-r,to=min(x1,x2),add=TRUE,col="gray",lwd=0.5)
           curve(-sqrt(r*r-x^2),from=max(x1,x2),to=r,add=TRUE,col="gray",lwd=0.5)
           curve(sqrt(r*r-x^2),from=-r,to=r,add=TRUE,col="gray",lwd=0.5)
           curve(-sqrt(r*r-x^2),from=min(x1,x2),to=max(x1,x2),add=TRUE)
        }
        if (y1 >=0 & y2 < 0) { 
           curve(-sqrt(r*r-x^2),from=-r,to=x2,add=TRUE,col="gray",lwd=0.5)
           curve(sqrt(r*r-x^2),from=-r,to=x1,add=TRUE,col="gray",lwd=0.5)
           curve(-sqrt(r*r-x^2),from=x2,to=r,add=TRUE)
           curve(sqrt(r*r-x^2),from=x1,to=r,add=TRUE)  
        }
        if (y1 < 0 & y2 >=0) { 
           curve(-sqrt(r*r-x^2),from=-r,to=x1,add=TRUE,col="gray",lwd=0.5)
           curve(sqrt(r*r-x^2),from=-r,to=x2,add=TRUE,col="gray",lwd=0.5)
           curve(-sqrt(r*r-x^2),from=x1,to=r,add=TRUE)
           curve(sqrt(r*r-x^2),from=x2,to=r,add=TRUE)
        }
        if (y1 >= 0 & y2 >= 0) { 
           curve(sqrt(r*r-x^2),from=-r,to=min(x1,x2),add=TRUE,col="gray",lwd=0.5)
           curve(sqrt(r*r-x^2),from=max(x1,x2),to=r,add=TRUE,col="gray",lwd=0.5)
           curve(-sqrt(r*r-x^2),from=-r,to=r,add=TRUE,col="gray",lwd=0.5)
           curve(sqrt(r*r-x^2),from=min(x1,x2),to=max(x1,x2),add=TRUE)
        }
     } else {
        arrows(clusters$arrows[(i-1)*12+1],clusters$arrows[(i-1)*12+2],clusters$arrows[(i-1)*12+3],
clusters$arrows[(i-1)*12+4],length=0)
        arrows(clusters$arrows[(i-1)*12+7],clusters$arrows[(i-1)*12+8],clusters$arrows[(i-1)*12+11],
clusters$arrows[(i-1)*12+12],length=0)
     }
 }
 nodec <- numeric() 
 for (i in 1:length(clusters$sizes)) nodec <- c(nodec,rep(i,clusters$sizes[i]))
 cols <- order(clusters$sizes,decreasing=TRUE)
 for (i in 1:length(clusters$sizes)) {
     o <- order(clusters$ringleaders[nodec == i],decreasing=TRUE)
     text(x[nodec==i],y[nodec==i],labels=(clusters$indivisibles[nodec==i])[o],col=(which(cols==i)+1),xpd=TRUE)
 }
 par(mar=op)
}

`inetplot` <-
function(clusters,theta=30,shaft=1,circle=TRUE,singlets=FALSE,labels=TRUE,edges=TRUE,points=TRUE,shadow=TRUE) {
 x <- numeric()
 y <- numeric()
 c <- numeric()
 s <- numeric()
 module <- c(rep(0,length(clusters$singlets)),rep(1:length(clusters$sizes),clusters$sizes))   
 di <- order(clusters$sizes,decreasing=TRUE)
 #theta <- 2*pi/length(di)
 theta <- theta*2*pi/360
 if (theta == 0) theta <- 2*pi/12
 for (i in 1:length(di)) { # no. of communities
     shrink <- clusters$sizes[di[i]]/clusters$sizes[di[1]]
     #shrink <- 1
     centerx <- (i-1)*shaft*shrink*cos((i-1)*theta)
     centery <- (i-1)*shaft*shrink*sin((i-1)*theta)
     #symbols(centerx,centery,circles=shrink,add=TRUE,inches=FALSE)
     tmp1 <- 0
     if (di[i] > 1) tmp1 <- sum(clusters$sizes[1:di[i]-1])
     sizes <- clusters$ringleaders[tmp1 + (1:clusters$sizes[di[i]])]
     size2 <- min(sizes)
     size1 <- max(sizes)    
     tmp <- length(clusters$singlets)
     if (di[i] > 1) tmp <- tmp + sum(clusters$sizes[1:di[i]-1])
     for (j in 1:clusters$sizes[di[i]]) {
         k <- clusters$indices[tmp+j]
         if (circle) {
            phi <- 2*pi/clusters$sizes[di[i]]
            x[k] <- centerx + shrink*cos((j-1)*phi) 
            y[k] <- centery + shrink*sin((j-1)*phi) 
         } else {
            phi <- theta
            x[k] <- centerx + log2(j)*cos((j+2)*phi) 
            y[k] <- centery + log2(j)*sin((j+2)*phi) 
         }
         c[k] <- i+1
         if (size1 != 0) s[k] <- 1.5*clusters$ringleaders[tmp1+j]/size1
         else s[k] <- 1.5*size2
         if (s[k] == 0) s[k] <- 1
     }  
 }
 # for singlets
 if (singlets) {
    radius <- max(max(c(x,y),na.rm=TRUE),abs(min(c(x,y),na.rm=TRUE)))
    radius <- radius + 1
    for (i in 1:length(clusters$singlets)) {
        phi <- 2*pi/length(clusters$singlets)
        k <- clusters$indices[i]
        x[k] <- radius*cos((i-1)*phi) 
        y[k] <- radius*sin((i-1)*phi) 
        c[k] <- 1
        s[k] <- 1
    }  
 }
 op <- par()$mar
 par(mar=c(1.1,1.1,1.1,1.1))
 #plot(x,y,pch=" ",axes=F,ann=F)
 #for (i in 1:length(di)) { # no. of communities
 #    shrink <- 1
 #    centerx <- (i-1)*shaft*shrink*cos((i-1)*theta)
 #    centery <- (i-1)*shaft*shrink*sin((i-1)*theta)
 #    shrink <- clusters$sizes[di[i]]/clusters$sizes[di[1]]
 #    symbols(centerx,centery,circles=shrink,add=T,inches=F)
 #    text(centerx+4,centery,labels=paste("i=",as.character(i)))
 #    #points(centerx,centery,pch=21)
 #}
 plot(x,y,pch=" ",axes=FALSE,ann=FALSE)
 if (edges) {
    for (i in 1:dim(clusters$A)[1]) {
        for (j in i:dim(clusters$A)[1]) {
            if (clusters$A[i,j] == 1) {
               if (module[which(clusters$indices == i)]*module[which(clusters$indices == j)] != 0) {
                  if (module[which(clusters$indices == i)] != module[which(clusters$indices == j)]) { 
                     if (shadow) arrows(x[i],y[i],x[j],y[j],length=0,col="gray")                     else arrows(x[i],y[i],x[j],y[j],length=0)
                  }
               }
            }
        }
    }
 }
 if (edges) {
    for (i in 1:dim(clusters$A)[1]) {
        for (j in i:dim(clusters$A)[1]) {
            if (clusters$A[i,j] == 1) {
               if (module[which(clusters$indices == i)]*module[which(clusters$indices == j)] != 0) {
                  if (module[which(clusters$indices == i)] == module[which(clusters$indices == j)])  
                     arrows(x[i],y[i],x[j],y[j],length=0)
               }
            }
        }
    }
 }

 #symbols(centerx,centery,circles=shrink,add=T,inches=F)
 for (i in 1:dim(clusters$A)[1]) {
     if (labels) {
        if (points) points(x[clusters$indices[i]],y[clusters$indices[i]],pch=19,cex=s[clusters$indices[i]])
        text(x[clusters$indices[i]],y[clusters$indices[i]],labels=c(clusters$singlets,clusters$indivisibles)[i],col=c[clusters$indices[i]],xpd=TRUE)
     } else {
        points(x[clusters$indices[i]],y[clusters$indices[i]],pch=19,col=c[clusters$indices[i]],cex=s[clusters$indices[i]])
     }
 }
 par(mar=op)
}
`itransitivity` <-
function(A) {
 if (!is.matrix(A)) return("error: input is not a matrix")
 if (dim(A)[1] != dim(A)[2]) return("error: matrix is not square")
 if (dim(A)[1] < 3) return("network is trivial")
 if (any(A>1)) return("error: not an unweighted adjacency matrix")
 if (any(A<0)) return("error: not an unweighted adjacency matrix")

 k <- numeric()
 for (i in 1:dim(A)[1]) k[i] <- sum(A[i,])

 c <- numeric()
 for (i in 1:dim(A)[1]) {
     c[i] <- 0
     for (j in 1:dim(A)[1]) {
         for (h in 1:dim(A)[1]) {
             if (i != j && i != h && j != h && A[i,j] != 0 && A[i,h] != 0 && A[j,h] != 0) {
                c[i] <- c[i] + 1 #A[i,j]*A[i,h]*A[j,h]
             }
         }
     }
     if (k[i] > 1) c[i] <- c[i]/k[i]/(k[i]-1)
     else c[i] <- 0
 }
 #C(k)
 Ck <- numeric()
 for (h in 1:max(k)) {
     Ck[h] <- 0
     j <- 0
     for (i in 1:dim(A)[1]) {
         if (k[i] == h) {
            Ck[h] <- Ck[h] + c[i]
            j <- j + 1
         }
     }
     if (j > 0) Ck[h] <- Ck[h]/j    
 }
 return(list(c=c,Ck=Ck))
}

