지금까지 여러 가지 모형의 육종가를 R로 구하였는데 모형이 복잡해지면서 R 프로그래밍 또한 복잡해 지고 있다. 각각의 모형에 알맞은 프로그램이 아니라 어느 정도 범용적으로 사용할 수 있는 프로그램을 만들어 보자. 본 내용은 Computational techniques in  animal breeding, Ignacy Misztal (University of Georgia, Athens, USA)를 참고하였다. 위 책은 포트란 소스로 되어 있는데 그것을 R로 바꾸었다.

 

또한 농촌진흥청에 발행한 "동물 육종을 위한 육종가 추정 프로그램 작성"을 참고할 수 있다.

 

  • single trait 2 fixed effect least square model

 

먼저 가장 기본적인 2개의 고정효과가 있는 최소제곱 모형을 다루어 보자.

 

자료

  1 1 5
  1 2 8
  2 1 7
  2 2 6
  2 3 9

 

프로그램

# Single trait 2 fixed effects least squares model

# Date : 2020.08.05

# Reference : Computational techneques in animal breeding, Ignacy Misztal

# MASS packages
if (!("MASS" %in% installed.packages())) {
    install.packages("MASS", dependencies = TRUE)
}
library(MASS)

# function : find address
find_addresses <- function() {
    
    for (i in 1:neff) {
        if (i == 1) {
            address[i] <<- indata[i]
        } else {
            address[i] <<- sum(nlev[1:i - 1]) + indata[i]
        }
    }
    
}

# parameters

# number of effects
neff = 2
neff

# number of levels for each effect
nlev = c(2, 3)
nlev

# number of equations
neq = sum(nlev)
neq

# make a empty left hand side
lhs = matrix(rep(0, neq * neq), nrow = neq)
lhs

# make a empty right hand side
rhs = matrix(rep(0, neq))
rhs

# addresses
address = c(rep(0, neff))
address

# set working directory setwd(choose.dir())
setwd("D:/temp/00_prediction")

# print working directory
getwd()

# read data : effect1, effect2, y1
data = read.table("01_lsq_data.txt", header = FALSE, sep = "", col.names = c("e1", 
    "e2", "y1"), stringsAsFactors = FALSE)
data

# number of data
ndata = nrow(data)
ndata

# fill lhs and rhs
for (k in 1:ndata) {
    indata = as.numeric(data[k, 1:neff])
    y = as.numeric(data[k, neff + 1])
    
    find_addresses()
    
    for (i in 1:neff) {
        for (j in 1:neff) {
            lhs[address[i], address[j]] = lhs[address[i], address[j]] + 1
        }
        rhs[address[i]] = rhs[address[i]] + y
    }
    
}

# print lhs, rhs
lhs
rhs

# generalised inverse of lhs
gi_lhs = ginv(lhs)

# print
gi_lhs

# solution
sol = gi_lhs %*% rhs

# print
sol

 

실행 결과

> # MASS packages
> if (!("MASS" %in% installed.packages())) {
+     install.packages("MASS", dependencies = TRUE)
+ }
> library(MASS)
> # function : find address
> find_addresses <- function() {
+     
+     for (i in 1:neff) {
+         if (i == 1) {
+             address[i] <<- indata[i]
+         } else {
+             address[i] <<- sum(nlev[1:i - 1]) + indata[i]
+         }
+     }
+     
+ }
> # number of effects
> neff = 2
> neff
[1] 2
> # number of levels for each effect
> nlev = c(2, 3)
> nlev
[1] 2 3
> # number of equations
> neq = sum(nlev)
> neq
[1] 5
> # make a empty left hand side
> lhs = matrix(rep(0, neq * neq), nrow = neq)
> lhs
     [,1] [,2] [,3] [,4] [,5]
[1,]    0    0    0    0    0
[2,]    0    0    0    0    0
[3,]    0    0    0    0    0
[4,]    0    0    0    0    0
[5,]    0    0    0    0    0
> # make a empty right hand side
> rhs = matrix(rep(0, neq))
> rhs
     [,1]
[1,]    0
[2,]    0
[3,]    0
[4,]    0
[5,]    0
> # addresses
> address = c(rep(0, neff))
> address
[1] 0 0
> # set working directory setwd(choose.dir())
> setwd("D:/temp/00_prediction")
> # print working directory
> getwd()
[1] "D:/temp/00_prediction"
> # read data : effect1, effect2, y1
> data = read.table("01_lsq_data.txt", header = FALSE, sep = "", col.names = c("e1", 
+     "e2", "y1"), stringsAsFactors = FALSE)
> data
  e1 e2 y1
1  1  1  5
2  1  2  8
3  2  1  7
4  2  2  6
5  2  3  9
> # number of data
> ndata = nrow(data)
> ndata
[1] 5
> # fill lhs and rhs
> for (k in 1:ndata) {
+     indata = as.numeric(data[k, 1:neff])
+     y = as.numeric(data[k, neff + 1])
+     
+     find_addresses()
+     
+     for (i in 1:neff) {
+         for (j in 1:neff) {
+             lhs[address[i], address[j]] = lhs[address[i], address[j]] + 1
+         }
+         rhs[address[i]] = rhs[address[i]] + y
+     }
+     
+ }
> # print lhs, rhs
> lhs
     [,1] [,2] [,3] [,4] [,5]
[1,]    2    0    1    1    0
[2,]    0    3    1    1    1
[3,]    1    1    2    0    0
[4,]    1    1    0    2    0
[5,]    0    1    0    0    1
> rhs
     [,1]
[1,]   13
[2,]   22
[3,]   12
[4,]   14
[5,]    9
> # generalised inverse of lhs
> gi_lhs = ginv(lhs)
> # print
> gi_lhs
      [,1]  [,2]  [,3]  [,4]  [,5]
[1,]  0.44 -0.16 -0.04 -0.04  0.36
[2,] -0.16  0.24  0.06  0.06 -0.04
[3,] -0.04  0.06  0.39 -0.11 -0.26
[4,] -0.04  0.06 -0.11  0.39 -0.26
[5,]  0.36 -0.04 -0.26 -0.26  0.84
> # solution
> sol = gi_lhs %*% rhs
> # print
> sol
     [,1]
[1,]  4.4
[2,]  4.4
[3,]  1.6
[4,]  2.6
[5,]  4.6
> 

 

  • single traits 1 fixed effect least squares model with covariable

다음은 공변이(covariable)가 있는 최소 제곱 모형이다.

자료

1 1 5
1 2 8
2 1 7
2 2 6
2 3 9

 

첫 열은 분류 변수, 둘째 열이 공변이 변수이다.

 

프로그램

# single traits 1 fixed effect least squares model with covariable

# Date : 2020.08.05

# Reference : Computational techneques in animal breeding, Ignacy Misztal

# MASS packages
if (!("MASS" %in% installed.packages())) {
    install.packages("MASS", dependencies = TRUE)
}
library(MASS)

# function : find address
find_addresses <- function() {
    
    for (i in 1:neff) {
        if (efftype[i] == "effcross") {
            weight_cov[i] <<- 1
            
            if (i == 1) {
                address[i] <<- indata[i]
            } else {
                address[i] <<- sum(nlev[1:i - 1]) + indata[i]
            }
            
            
        } else if (efftype[i] == "effcov") {
            weight_cov[i] <<- indata[i]
            
            if (nestedcov[i] == 0) {
                
                if (i == 1) {
                  address[i] <<- 1
                } else {
                  address[i] <<- sum(nlev[1:i - 1]) + 1
                }
            } else if (nestedcov[i] > 0 && nestedcov[i] < neff) {
                if (i == 1) {
                  address[i] <<- indata[nestedcov[i]]
                } else {
                  address[i] <<- sum(nlev[1:i - 1]) + indata[nestedcov[i]]
                }
                
            } else {
                warning("wrong descriptin of nested covariable")
            }
            
        } else {
            warning("unimplemented effect type")
        }
    }

}

# parameters

# number of effects
neff = 2
neff

# effect type
efftype = c("effcross", "effcov")
efftype

# nested covariable
nestedcov = c(0, 1)
nestedcov

# nlev
nlev = c(2, 2)
nlev

# set working directory setwd(choose.dir())
setwd("D:/temp/00_prediction")

# print working directory
getwd()

# read data : effect1, effect2, y1
data = read.table("02_lsqr_data.txt", header = FALSE, sep = "", col.names = c("eff1", 
    "eff2", "y1"), stringsAsFactors = FALSE)
data

# number of data
ndata = nrow(data)
ndata

# number of equation
neq = sum(nlev)
neq

# make a empty left hand side
lhs = matrix(rep(0, neq * neq), nrow = neq)
lhs

# make a empty right hand side
rhs = matrix(rep(0, neq))
rhs

# addresses
address = rep(0, neff)
address

# weight of covariable
weight_cov = rep(0, neff)
weight_cov

# fill lhs and rhs
for (k in 1:ndata) {
    # k = 1
    indata = as.numeric(data[k, 1:neff])
    y = as.numeric(data[k, neff + 1])
    
    find_addresses()
    
    for (i in 1:neff) {
        for (j in 1:neff) {
            lhs[address[i], address[j]] = lhs[address[i], address[j]] + weight_cov[i] * weight_cov[j]
        }
        rhs[address[i]] = rhs[address[i]] + y * weight_cov[i]
    }
    
}

# print lhs, rhs
lhs
rhs

# generalised inverse of lhs
gi_lhs = ginv(lhs)

# print
gi_lhs

# solution
sol = gi_lhs %*% rhs

# print
sol

 

실행 결과

> # MASS packages
> if (!("MASS" %in% installed.packages())) {
+     install.packages("MASS", dependencies = TRUE)
+ }
> library(MASS)
> 
> # function : find address
> find_addresses <- function() {
+     
+     for (i in 1:neff) {
+         if (efftype[i] == "effcross") {
+             weight_cov[i] <<- 1
+             
+             if (i == 1) {
+                 address[i] <<- indata[i]
+             } else {
+                 address[i] <<- sum(nlev[1:i - 1]) + indata[i]
+             }
+             
+             
+         } else if (efftype[i] == "effcov") {
+             weight_cov[i] <<- indata[i]
+             
+             if (nestedcov[i] == 0) {
+                 
+                 if (i == 1) {
+                   address[i] <<- indata[i]
+                 } else {
+                   address[i] <<- sum(nlev[1:i - 1]) + indata[i]
+                 }
+             } else if (nestedcov[i] > 0 && nestedcov[i] < neff) {
+                 if (i == 1) {
+                   address[i] <<- indata[nestedcov[i]]
+                 } else {
+                   address[i] <<- sum(nlev[1:i - 1]) + indata[nestedcov[i]]
+                 }
+                 
+             } else {
+                 warning("wrong descriptin of nested covariable")
+             }
+             
+         } else {
+             warning("unimplemented effect type")
+         }
+     }
+ 
+ }
> 
> # parameters
> 
> # number of effects
> neff = 2
> neff
[1] 2
> 
> # effect type
> efftype = c("effcross", "effcov")
> efftype
[1] "effcross" "effcov"  
> 
> # nested covariable
> nestedcov = c(0, 1)
> nestedcov
[1] 0 1
> 
> # nlev
> nlev = c(2, 2)
> nlev
[1] 2 2
> 
> # set working directory setwd(choose.dir())
> setwd("D:/temp/00_prediction")
> 
> # print working directory
> getwd()
[1] "D:/temp/00_prediction"
> 
> # read data : effect1, effect2, y1
> data = read.table("02_lsqr_data.txt", header = FALSE, sep = "", col.names = c("eff1", 
+     "eff2", "y1"), stringsAsFactors = FALSE)
> data
  eff1 eff2 y1
1    1    1  5
2    1    2  8
3    2    1  7
4    2    2  6
5    2    3  9
> 
> # number of data
> ndata = nrow(data)
> ndata
[1] 5
> 
> # number of equation
> neq = sum(nlev)
> neq
[1] 4
> 
> # make a empty left hand side
> lhs = matrix(rep(0, neq * neq), nrow = neq)
> lhs
     [,1] [,2] [,3] [,4]
[1,]    0    0    0    0
[2,]    0    0    0    0
[3,]    0    0    0    0
[4,]    0    0    0    0
> 
> # make a empty right hand side
> rhs = matrix(rep(0, neq))
> rhs
     [,1]
[1,]    0
[2,]    0
[3,]    0
[4,]    0
> 
> # addresses
> address = rep(0, neff)
> address
[1] 0 0
> 
> # weight of covariable
> weight_cov = rep(0, neff)
> weight_cov
[1] 0 0
> 
> # fill lhs and rhs
> for (k in 1:ndata) {
+     # k = 1
+     indata = as.numeric(data[k, 1:neff])
+     y = as.numeric(data[k, neff + 1])
+     
+     find_addresses()
+     
+     for (i in 1:neff) {
+         for (j in 1:neff) {
+             lhs[address[i], address[j]] = lhs[address[i], address[j]] + weight_cov[i] * weight_cov[j]
+         }
+         rhs[address[i]] = rhs[address[i]] + y * weight_cov[i]
+     }
+     
+ }
> 
> # print lhs, rhs
> lhs
     [,1] [,2] [,3] [,4]
[1,]    2    0    3    0
[2,]    0    3    0    6
[3,]    3    0    5    0
[4,]    0    6    0   14
> rhs
     [,1]
[1,]   13
[2,]   22
[3,]   21
[4,]   46
> 
> # generalised inverse of lhs
> gi_lhs = ginv(lhs)
> 
> # print
> gi_lhs
     [,1]      [,2] [,3] [,4]
[1,]    5  0.000000   -3  0.0
[2,]    0  2.333333    0 -1.0
[3,]   -3  0.000000    2  0.0
[4,]    0 -1.000000    0  0.5
> 
> # solution
> sol = gi_lhs %*% rhs
> 
> # print
> sol
         [,1]
[1,] 2.000000
[2,] 5.333333
[3,] 3.000000
[4,] 1.000000
> 

 

  • Inverse of Numerator Relationship Matirx

animal model을 이용하기 위해선 개체들 사이의 혈연 계수 행렬 또는 혈연 계수 행렬의 역행렬을 구해야 한다. 다음은 혈연 계수 행렬의 역행렬을 구하는 프로그램이다.

 

자료

1 0 0
2 0 0
3 0 0
4 1 2
5 3 2
6 1 5
7 3 4
8 1 7

 

프로그램

# inverse of numerator relationship matrix

# Date : 2020.08.05

# Reference : Computational techneques in animal breeding, Ignacy Misztal

# function to make inverse of numerator relationship matrix
ainv = function() {
    
    w = c(1, -0.5, -0.5)
    res = c(2, 4/3, 1, 0)
    
    for (di in 1:nped) {

        p = as.numeric(pedi[di,])
        
        i = 1
        if(p[2] == 0){  i = i + 1 }
        if(p[3] == 0){  i = i + 1 }
        
        mendel = res[i]
        
        for (k in 1:3) {
            for (l in 1:3) {
                if (p[k] != 0 && p[l] != 0) {
                    a[p[k], p[l]] <<- a[p[k], p[l]] + w[k] * w[l] * mendel
                }
            }
        }
        
    }

}

# set working directory setwd(choose.dir())
setwd("D:/temp/00_prediction")

# print working directory
getwd()

# read pedigree data
pedi = read.table("03_ainv_data.txt", header = FALSE, sep = "", col.names = c("a", 
                                                                              "s", "d"), stringsAsFactors = FALSE)
pedi

# number of pedi
nped = nrow(pedi)
nped

# inverse matrix of NRM(Nemerator Relationship Matrix)
a = matrix(c(0), nrow = nped, ncol = nped)
a

# run function ainv
ainv()

# print NRM
a

 

실형 결과

> # function to make inverse of numerator relationship matrix
> ainv = function() {
+     
+     w = c(1, -0.5, -0.5)
+     res = c(2, 4/3, 1, 0)
+     
+     for (di in 1:nped) {
+ 
+         p = as.numeric(pedi[di,])
+         
+         i = 1
+         if(p[2] == 0){  i = i + 1 }
+         if(p[3] == 0){  i = i + 1 }
+         
+         mendel = res[i]
+         
+         for (k in 1:3) {
+             for (l in 1:3) {
+                 if (p[k] != 0 && p[l] != 0) {
+                     a[p[k], p[l]] <<- a[p[k], p[l]] + w[k] * w[l] * mendel
+                 }
+             }
+         }
+         
+     }
+ 
+ }
> 
> # set working directory setwd(choose.dir())
> setwd("D:/temp/00_prediction")
> 
> # print working directory
> getwd()
[1] "D:/temp/00_prediction"
> 
> # read pedigree data
> pedi = read.table("03_ainv_data.txt", header = FALSE, sep = "", col.names = c("a", 
+                                                                               "s", "d"), stringsAsFactors = FALSE)
> pedi
  a s d
1 1 0 0
2 2 0 0
3 3 0 0
4 4 1 2
5 5 3 2
6 6 1 5
7 7 3 4
8 8 1 7
> 
> # number of pedi
> nped = nrow(pedi)
> nped
[1] 8
> 
> # inverse matrix of NRM(Nemerator Relationship Matrix)
> a = matrix(c(0), nrow = nped, ncol = nped)
> a
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]    0    0    0    0    0    0    0    0
[2,]    0    0    0    0    0    0    0    0
[3,]    0    0    0    0    0    0    0    0
[4,]    0    0    0    0    0    0    0    0
[5,]    0    0    0    0    0    0    0    0
[6,]    0    0    0    0    0    0    0    0
[7,]    0    0    0    0    0    0    0    0
[8,]    0    0    0    0    0    0    0    0
> 
> # run function ainv
> ainv()
> 
> # print NRM
> a
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]  2.5  0.5  0.0 -1.0  0.5   -1  0.5   -1
[2,]  0.5  2.0  0.5 -1.0 -1.0    0  0.0    0
[3,]  0.0  0.5  2.0  0.5 -1.0    0 -1.0    0
[4,] -1.0 -1.0  0.5  2.5  0.0    0 -1.0    0
[5,]  0.5 -1.0 -1.0  0.0  2.5   -1  0.0    0
[6,] -1.0  0.0  0.0  0.0 -1.0    2  0.0    0
[7,]  0.5  0.0 -1.0 -1.0  0.0    0  2.5   -1
[8,] -1.0  0.0  0.0  0.0  0.0    0 -1.0    2
> 

 

  • single trait animal model

다음은 단형질 개체 모형이다.

 

표현형 자료

1 2 8
1 1 5
2 1 7
2 2 6
2 3 9

 

1열: 분류변수, 2열 : 개체, 3열 : 표현형 자료

 

혈통 자료

5 0 0
1 3 4
2 3 4
3 5 0
4 0 0

 

프로그램

# single trait animal model

# Date : 2020.08.05

# Reference : Computational techneques in animal breeding, Ignacy Misztal

# MASS packages
if (!("MASS" %in% installed.packages())) {
    install.packages("MASS", dependencies = TRUE)
}
library(MASS)

# function : find address
find_addresses <- function() {
    
    for (i in 1:neff) {
        if (i == 1) {
            address[i] <<- indata[i]
        } else {
            address[i] <<- sum(nlev[1:i - 1]) + indata[i]
        }
    }
    
}

# address for given level l of effect e
address1 <- function(e, l){
ifelse(e == 1, l, sum(nlev[1 : e - 1]) + l)
    return(ifelse(e == 1, l, sum(nlev[1 : e - 1]) + l))
}

# function to make inverse of numerator relationship matrix
ainv = function(eff) {
    
    w = c(1, -0.5, -0.5)
    res = c(2, 4/3, 1, 0)
    
    for (di in 1:nped) {
        
        p = as.numeric(pedi[di,])
        
        i = 1
        if(p[2] == 0){  i = i + 1 }
        if(p[3] == 0){  i = i + 1 }
        
        mendel = res[i]
        
        for (k in 1:3) {
            for (l in 1:3) {
                if (p[k] != 0 && p[l] != 0) {
                    m = address1(eff, p[k])
                    n = address1(eff, p[l])
                    a[p[k], p[l]] <<- a[p[k], p[l]] + w[k] * w[l] * mendel
                    lhs[m, n] <<- lhs[m, n] + w[k] * w[l] * mendel / var_a
                }
            }
        }
        
    }
    
}

# when random effect is diagonal
diag <- function(eff){
    for(i in 1 : nlev[eff]){
        m = address1(eff, i)
        lhs[m, m] <<- lhs[m, m] + 1 / var_a
    }
}

# parameters

# number of effects
neff = 2
neff

# nlev
nlev = c(2, 5)
nlev

# random effect number
addeff = 2
addeff

# type of random effect
random = "diag"
random

# additive genetic variance
var_a = 2
var_a

# residual variance
var_e = 10
var_e

# number of equation
neq = sum(nlev)
neq

# empty left hand side
lhs = matrix(c(0), nrow = neq, ncol=neq)
lhs

# empty right hand side
rhs = matrix(c(0), nrow = neq)
rhs

# addresses
address = c(rep(0, neff))
address

# set working directory setwd(choose.dir())
setwd("D:/temp/00_prediction")

# print working directory
getwd()

# read data : effect1, effect2, y1
data = read.table("04_stam_data.txt", header = FALSE, sep = "", col.names = c("e1", 
    "e2", "y1"), stringsAsFactors = FALSE)
data

# number of data
ndata = nrow(data)
ndata

# read pedigree : animal, sire, dam
pedi = read.table("04_stam_pedi.txt", header = FALSE, sep = "", col.names = c("animal", 
    "sire", "dam"), stringsAsFactors = FALSE)
pedi

# number of pedigree
nped = nrow(pedi)
nped

# inverse matrix of NRM(Nemerator Relationship Matrix)
a = matrix(c(0), nrow = nped, ncol = nped)
a

# fill lhs and rhs

for (k in 1 : ndata) {
    # k = 1
    indata = as.numeric(data[k, 1:neff])
    y = as.numeric(data[k, neff + 1])
    
    find_addresses()
    
    for (i in 1:neff) {
        for (j in 1:neff) {
            lhs[address[i], address[j]] = lhs[address[i], address[j]] + 1/var_e
        }
        rhs[address[i]] = rhs[address[i]] + y/var_e
    }
    
}

# print lhs, rhs
lhs
rhs

# process random effect
for (i in 1:neff) {
    if (i == addeff) {

        if (random == "add") {
            
            # add the inverse of NRM to lhs
            ainv(i)
            
        } else if (random == "diag") {

            # add the inverse of var_a to the diagonal of lhs
            diag(i)
            
        } else {
            warning("Choose add or diag as a type of random effect")
        }
    }
}

# print
lhs
rhs

# generalised inverse of lhs
gi_lhs = ginv(lhs)

# print
gi_lhs

# solution
sol = gi_lhs %*% rhs

# print
sol

 

실행 결과

> # MASS packages
> if (!("MASS" %in% installed.packages())) {
+     install.packages("MASS", dependencies = TRUE)
+ }
> library(MASS)
> 
> # function : find address
> find_addresses <- function() {
+     
+     for (i in 1:neff) {
+         if (i == 1) {
+             address[i] <<- indata[i]
+         } else {
+             address[i] <<- sum(nlev[1:i - 1]) + indata[i]
+         }
+     }
+     
+ }
> 
> # address for given level l of effect e
> address1 <- function(e, l){
+ ifelse(e == 1, l, sum(nlev[1 : e - 1]) + l)
+     return(ifelse(e == 1, l, sum(nlev[1 : e - 1]) + l))
+ }
> 
> # function to make inverse of numerator relationship matrix
> ainv = function(eff) {
+     
+     w = c(1, -0.5, -0.5)
+     res = c(2, 4/3, 1, 0)
+     
+     for (di in 1:nped) {
+         
+         p = as.numeric(pedi[di,])
+         
+         i = 1
+         if(p[2] == 0){  i = i + 1 }
+         if(p[3] == 0){  i = i + 1 }
+         
+         mendel = res[i]
+         
+         for (k in 1:3) {
+             for (l in 1:3) {
+                 if (p[k] != 0 && p[l] != 0) {
+                     m = address1(eff, p[k])
+                     n = address1(eff, p[l])
+                     a[p[k], p[l]] <<- a[p[k], p[l]] + w[k] * w[l] * mendel
+                     lhs[m, n] <<- lhs[m, n] + w[k] * w[l] * mendel / var_a
+                 }
+             }
+         }
+         
+     }
+     
+ }
> 
> # when random effect is diagonal
> diag <- function(eff){
+     for(i in 1 : nlev[eff]){
+         m = address1(eff, i)
+         lhs[m, m] <<- lhs[m, m] + 1 / var_a
+     }
+ }
> 
> # parameters
> 
> # number of effects
> neff = 2
> neff
[1] 2
> 
> # nlev
> nlev = c(2, 5)
> nlev
[1] 2 5
> 
> # random effect number
> addeff = 2
> addeff
[1] 2
> 
> # type of random effect
> random = "diag"
> random
[1] "diag"
> 
> # additive genetic variance
> var_a = 2
> var_a
[1] 2
> 
> # residual variance
> var_e = 10
> var_e
[1] 10
> 
> # number of equation
> neq = sum(nlev)
> neq
[1] 7
> 
> # empty left hand side
> lhs = matrix(c(0), nrow = neq, ncol=neq)
> lhs
     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,]    0    0    0    0    0    0    0
[2,]    0    0    0    0    0    0    0
[3,]    0    0    0    0    0    0    0
[4,]    0    0    0    0    0    0    0
[5,]    0    0    0    0    0    0    0
[6,]    0    0    0    0    0    0    0
[7,]    0    0    0    0    0    0    0
> 
> # empty right hand side
> rhs = matrix(c(0), nrow = neq)
> rhs
     [,1]
[1,]    0
[2,]    0
[3,]    0
[4,]    0
[5,]    0
[6,]    0
[7,]    0
> 
> # addresses
> address = c(rep(0, neff))
> address
[1] 0 0
> 
> # set working directory setwd(choose.dir())
> setwd("D:/temp/00_prediction")
> 
> # print working directory
> getwd()
[1] "D:/temp/00_prediction"
> 
> # read data : effect1, effect2, y1
> data = read.table("04_stam_data.txt", header = FALSE, sep = "", col.names = c("e1", 
+     "e2", "y1"), stringsAsFactors = FALSE)
> data
  e1 e2 y1
1  1  2  8
2  1  1  5
3  2  1  7
4  2  2  6
5  2  3  9
> 
> # number of data
> ndata = nrow(data)
> ndata
[1] 5
> 
> # read pedigree : animal, sire, dam
> pedi = read.table("04_stam_pedi.txt", header = FALSE, sep = "", col.names = c("animal", 
+     "sire", "dam"), stringsAsFactors = FALSE)
> pedi
  animal sire dam
1      5    0   0
2      1    3   4
3      2    3   4
4      3    5   0
5      4    0   0
> 
> # number of pedigree
> nped = nrow(pedi)
> nped
[1] 5
> 
> # inverse matrix of NRM(Nemerator Relationship Matrix)
> a = matrix(c(0), nrow = nped, ncol = nped)
> a
     [,1] [,2] [,3] [,4] [,5]
[1,]    0    0    0    0    0
[2,]    0    0    0    0    0
[3,]    0    0    0    0    0
[4,]    0    0    0    0    0
[5,]    0    0    0    0    0
> 
> # fill lhs and rhs
> 
> for (k in 1 : ndata) {
+     # k = 1
+     indata = as.numeric(data[k, 1:neff])
+     y = as.numeric(data[k, neff + 1])
+     
+     find_addresses()
+     
+     for (i in 1:neff) {
+         for (j in 1:neff) {
+             lhs[address[i], address[j]] = lhs[address[i], address[j]] + 1/var_e
+         }
+         rhs[address[i]] = rhs[address[i]] + y/var_e
+     }
+     
+ }
> 
> # print lhs, rhs
> lhs
     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,]  0.2  0.0  0.1  0.1  0.0    0    0
[2,]  0.0  0.3  0.1  0.1  0.1    0    0
[3,]  0.1  0.1  0.2  0.0  0.0    0    0
[4,]  0.1  0.1  0.0  0.2  0.0    0    0
[5,]  0.0  0.1  0.0  0.0  0.1    0    0
[6,]  0.0  0.0  0.0  0.0  0.0    0    0
[7,]  0.0  0.0  0.0  0.0  0.0    0    0
> rhs
     [,1]
[1,]  1.3
[2,]  2.2
[3,]  1.2
[4,]  1.4
[5,]  0.9
[6,]  0.0
[7,]  0.0
> 
> # process random effect
> for (i in 1:neff) {
+     if (i == addeff) {
+ 
+         if (random == "add") {
+             
+             # add the inverse of NRM to lhs
+             ainv(i)
+             
+         } else if (random == "diag") {
+ 
+             # add the inverse of var_a to the diagonal of lhs
+             diag(i)
+             
+         } else {
+             warning("Choose add or diag as a type of random effect")
+         }
+     }
+ }
> 
> # print
> lhs
     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,]  0.2  0.0  0.1  0.1  0.0  0.0  0.0
[2,]  0.0  0.3  0.1  0.1  0.1  0.0  0.0
[3,]  0.1  0.1  0.7  0.0  0.0  0.0  0.0
[4,]  0.1  0.1  0.0  0.7  0.0  0.0  0.0
[5,]  0.0  0.1  0.0  0.0  0.6  0.0  0.0
[6,]  0.0  0.0  0.0  0.0  0.0  0.5  0.0
[7,]  0.0  0.0  0.0  0.0  0.0  0.0  0.5
> rhs
     [,1]
[1,]  1.3
[2,]  2.2
[3,]  1.2
[4,]  1.4
[5,]  0.9
[6,]  0.0
[7,]  0.0
> 
> # generalised inverse of lhs
> gi_lhs = ginv(lhs)
> 
> # print
> gi_lhs
           [,1]       [,2]       [,3]       [,4]       [,5] [,6] [,7]
[1,]  5.9444444  0.6666667 -0.9444444 -0.9444444 -0.1111111    0    0
[2,]  0.6666667  4.0000000 -0.6666667 -0.6666667 -0.6666667    0    0
[3,] -0.9444444 -0.6666667  1.6587302  0.2301587  0.1111111    0    0
[4,] -0.9444444 -0.6666667  0.2301587  1.6587302  0.1111111    0    0
[5,] -0.1111111 -0.6666667  0.1111111  0.1111111  1.7777778    0    0
[6,]  0.0000000  0.0000000  0.0000000  0.0000000  0.0000000    2    0
[7,]  0.0000000  0.0000000  0.0000000  0.0000000  0.0000000    0    2
> 
> # solution
> sol = gi_lhs %*% rhs
> 
> # print
> sol
             [,1]
[1,]  6.638888889
[2,]  7.333333333
[3,] -0.281746032
[4,]  0.003968254
[5,]  0.277777778
[6,]  0.000000000
[7,]  0.000000000
> 

 

  • multiple traits least squares model

 

다형질 개체 모형을 다루어야 하는데 우선 최소 제곱 모형을 다루고 후에 다형질 개체 모형을 다루도록 하자

 

자료

2 3 2 3 9 1
2 2 2 2 6 5
2 1 2 1 7 3
1 2 1 2 8 4
1 1 1 1 5 2

 

1, 2열 : 첫째 형질의 2개의 fixed effects

3, 4열 : 둘째 형질의 2개의 fixed effects

5, 6열 : 첫째, 둘째 형질의 표현형 

 

프로그램

# multiple traits least squares model

# Date : 2020.08.06.

# Reference : Computational techneques in animal breeding, Ignacy Misztal

# MASS packages
if (!("MASS" %in% installed.packages())) {
    install.packages("MASS", dependencies = TRUE)
}
library(MASS)

# return data in indata
datum <- function(ef, tr) {
    return(indata[ef + (tr - 1) * neff])
}

find_rinv <- function() {
    tempr = r
    for (i in 1:ntrait) {
        if (y[i] == 0) {
            tempr[i, ] = 0
            tempr[, i] = 0
        }
    }
    rinv <<- ginv(tempr)
}

# function : find address
find_addresses <- function() {
    
    for (i in 1:neff) {
        for (j in 1:ntrait) {
            
            # i=2 j=1
            
            if (datum(i, j) == miss) {
                address[i, j] <<- 0
                weight_cov[i, j] <<- 0
                next
            }
            
            baseaddr = ifelse(i == 1, j, sum(nlev[1:i - 1]) * ntrait + j)
            
            if (effecttype[i] == "effcross") {
                weight_cov[i, j] <<- 1
                address[i, j] <<- baseaddr + (datum(i, j) - 1) * ntrait
            } else if (effecttype[i] == "effcov") {
                weight_cov[i, j] <<- datum(i, j)
                if (nestedcov[i] == 0) {
                    address[i, j] <<- baseaddr
                } else if (nestedcov[i] > 0 && nestedcov[i] < neff) {
                    address[i, j] <<- baseaddr + (datum(nestedcov[i], j) - 1) * ntrait
                } else {
                    warning("wrong description of nested covariable")
                }
            } else {
                warning("unimplemented effect")
            }
        }
    }

}


# parameters

# number of traits
ntrait = 2
ntrait

# number of effects
neff = 2
neff

# type of effects
effecttype = c("effcross", "effcross")
effecttype

# whether covariable effect is nested or not
nestedcov = c(0, 0)
nestedcov

# number of levels
nlev = c(2, 3)
nlev

# missing values
miss = 0
miss

# residual variace
r = matrix(c(1, 2, 2, 5), nrow = 2)
r

# empty inverse of r
rinv = matrix(c(0), nrow = ntrait, ncol = ntrait)
rinv

# number of equation
neq = ntrait * sum(nlev)
neq

# make empty lhs and rhs
lhs = matrix(c(0), nrow = neq, ncol = neq)
lhs

rhs = matrix(c(0), nrow = neq)
rhs

# addresses
address = matrix(c(0), nrow=neff, ncol=ntrait)
address

# weight of covariable
weight_cov = matrix(c(0), nrow=neff, ncol=ntrait)
weight_cov

# set working directory setwd(choose.dir())
setwd("D:/temp/00_prediction")

# print working directory
getwd()

# read data : t1e1, t1e2, t2e1, t2e2, y1, y2
data = read.table("06_mt_lsq_data.txt", header = FALSE, sep = "", col.names = c("t1e1", "t1e2", "t2e1", "t2e2", "y1", "y2"), stringsAsFactors = FALSE)
data

# number of data
ndata = nrow(data)
ndata


# loop data
for (di in 1:ndata) {
    # di = 5
    indata = as.numeric(data[di, 1:(ntrait * neff)])
    y = as.numeric(data[di, (ntrait * neff + 1):(ntrait * (neff + 1))])
    
    # address and weight_cov
    find_addresses()

    # inverse of r
    find_rinv()
    
    for (i in 1:neff) {
        for (j in 1:neff) {
            for (k in 1:ntrait) {
                for (l in 1:ntrait) {
                  lhs[address[i, k], address[j, l]] = lhs[address[i, k], address[j, l]] + weight_cov[i, k] * weight_cov[j, l] * rinv[k, l]
                }
            }
        }
        for (k in 1:ntrait) {
            for (l in 1:ntrait) {
                rhs[address[i, k]] = rhs[address[i, k]] + weight_cov[i, k] * rinv[k, l] * y[l]
            }
        }
    }
}

# print
lhs
rhs

# generalised inverse of lhs
gi_lhs = ginv(lhs)

# print
gi_lhs

# solution
sol = gi_lhs %*% rhs

# print
sol

 

실형 결과

> # MASS packages
> if (!("MASS" %in% installed.packages())) {
+     install.packages("MASS", dependencies = TRUE)
+ }
> library(MASS)
> 
> # return data in indata
> datum <- function(ef, tr) {
+     return(indata[ef + (tr - 1) * neff])
+ }
> 
> find_rinv <- function() {
+     tempr = r
+     for (i in 1:ntrait) {
+         if (y[i] == 0) {
+             tempr[i, ] = 0
+             tempr[, i] = 0
+         }
+     }
+     rinv <<- ginv(tempr)
+ }
> 
> # function : find address
> find_addresses <- function() {
+     
+     for (i in 1:neff) {
+         for (j in 1:ntrait) {
+             
+             # i=2 j=1
+             
+             if (datum(i, j) == miss) {
+                 address[i, j] <<- 0
+                 weight_cov[i, j] <<- 0
+                 next
+             }
+             
+             baseaddr = ifelse(i == 1, j, sum(nlev[1:i - 1]) * ntrait + j)
+             
+             if (effecttype[i] == "effcross") {
+                 weight_cov[i, j] <<- 1
+                 address[i, j] <<- baseaddr + (datum(i, j) - 1) * ntrait
+             } else if (effecttype[i] == "effcov") {
+                 weight_cov[i, j] <<- datum(i, j)
+                 if (nestedcov[i] == 0) {
+                     address[i, j] <<- baseaddr
+                 } else if (nestedcov[i] > 0 && nestedcov[i] < neff) {
+                     address[i, j] <<- baseaddr + (datum(nestedcov[i], j) - 1) * ntrait
+                 } else {
+                     warning("wrong description of nested covariable")
+                 }
+             } else {
+                 warning("unimplemented effect")
+             }
+         }
+     }
+ 
+ }
> 
> 
> # parameters
> 
> # number of traits
> ntrait = 2
> ntrait
[1] 2
> 
> # number of effects
> neff = 2
> neff
[1] 2
> 
> # type of effects
> effecttype = c("effcross", "effcross")
> effecttype
[1] "effcross" "effcross"
> 
> # whether covariable effect is nested or not
> nestedcov = c(0, 0)
> nestedcov
[1] 0 0
> 
> # number of levels
> nlev = c(2, 3)
> nlev
[1] 2 3
> 
> # missing values
> miss = 0
> miss
[1] 0
> 
> # residual variace
> r = matrix(c(1, 2, 2, 5), nrow = 2)
> r
     [,1] [,2]
[1,]    1    2
[2,]    2    5
> 
> # empty inverse of r
> rinv = matrix(c(0), nrow = ntrait, ncol = ntrait)
> rinv
     [,1] [,2]
[1,]    0    0
[2,]    0    0
> 
> # number of equation
> neq = ntrait * sum(nlev)
> neq
[1] 10
> 
> # make empty lhs and rhs
> lhs = matrix(c(0), nrow = neq, ncol = neq)
> lhs
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]    0    0    0    0    0    0    0    0    0     0
 [2,]    0    0    0    0    0    0    0    0    0     0
 [3,]    0    0    0    0    0    0    0    0    0     0
 [4,]    0    0    0    0    0    0    0    0    0     0
 [5,]    0    0    0    0    0    0    0    0    0     0
 [6,]    0    0    0    0    0    0    0    0    0     0
 [7,]    0    0    0    0    0    0    0    0    0     0
 [8,]    0    0    0    0    0    0    0    0    0     0
 [9,]    0    0    0    0    0    0    0    0    0     0
[10,]    0    0    0    0    0    0    0    0    0     0
> 
> rhs = matrix(c(0), nrow = neq)
> rhs
      [,1]
 [1,]    0
 [2,]    0
 [3,]    0
 [4,]    0
 [5,]    0
 [6,]    0
 [7,]    0
 [8,]    0
 [9,]    0
[10,]    0
> 
> # addresses
> address = matrix(c(0), nrow=neff, ncol=ntrait)
> address
     [,1] [,2]
[1,]    0    0
[2,]    0    0
> 
> # weight of covariable
> weight_cov = matrix(c(0), nrow=neff, ncol=ntrait)
> weight_cov
     [,1] [,2]
[1,]    0    0
[2,]    0    0
> 
> # set working directory setwd(choose.dir())
> setwd("D:/temp/00_prediction")
> 
> # print working directory
> getwd()
[1] "D:/temp/00_prediction"
> 
> # read data : t1e1, t1e2, t2e1, t2e2, y1, y2
> data = read.table("06_mt_lsq_data.txt", header = FALSE, sep = "", col.names = c("t1e1", "t1e2", "t2e1", "t2e2", "y1", "y2"), stringsAsFactors = FALSE)
> data
  t1e1 t1e2 t2e1 t2e2 y1 y2
1    2    3    2    3  9  1
2    2    2    2    2  6  5
3    2    1    2    1  7  3
4    1    2    1    2  8  4
5    1    1    1    1  5  2
> 
> # number of data
> ndata = nrow(data)
> ndata
[1] 5
> 
> 
> # loop data
> for (di in 1:ndata) {
+     # di = 5
+     indata = as.numeric(data[di, 1:(ntrait * neff)])
+     y = as.numeric(data[di, (ntrait * neff + 1):(ntrait * (neff + 1))])
+     
+     # address and weight_cov
+     find_addresses()
+ 
+     # inverse of r
+     find_rinv()
+     
+     for (i in 1:neff) {
+         for (j in 1:neff) {
+             for (k in 1:ntrait) {
+                 for (l in 1:ntrait) {
+                   lhs[address[i, k], address[j, l]] = lhs[address[i, k], address[j, l]] + weight_cov[i, k] * weight_cov[j, l] * rinv[k, l]
+                 }
+             }
+         }
+         for (k in 1:ntrait) {
+             for (l in 1:ntrait) {
+                 rhs[address[i, k]] = rhs[address[i, k]] + weight_cov[i, k] * rinv[k, l] * y[l]
+             }
+         }
+     }
+ }
> 
> # print
> lhs
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]   10   -4    0    0    5   -2    5   -2    0     0
 [2,]   -4    2    0    0   -2    1   -2    1    0     0
 [3,]    0    0   15   -6    5   -2    5   -2    5    -2
 [4,]    0    0   -6    3   -2    1   -2    1   -2     1
 [5,]    5   -2    5   -2   10   -4    0    0    0     0
 [6,]   -2    1   -2    1   -4    2    0    0    0     0
 [7,]    5   -2    5   -2    0    0   10   -4    0     0
 [8,]   -2    1   -2    1    0    0   -4    2    0     0
 [9,]    0    0    5   -2    0    0    0    0    5    -2
[10,]    0    0   -2    1    0    0    0    0   -2     1
> rhs
      [,1]
 [1,]   53
 [2,]  -20
 [3,]   92
 [4,]  -35
 [5,]   50
 [6,]  -19
 [7,]   52
 [8,]  -19
 [9,]   43
[10,]  -17
> 
> # generalised inverse of lhs
> gi_lhs = ginv(lhs)
> 
> # print
> gi_lhs
       [,1]  [,2]  [,3]  [,4]  [,5]  [,6]  [,7]  [,8]  [,9] [,10]
 [1,]  0.44  0.88 -0.16 -0.32 -0.04 -0.08 -0.04 -0.08  0.36  0.72
 [2,]  0.88  2.20 -0.32 -0.80 -0.08 -0.20 -0.08 -0.20  0.72  1.80
 [3,] -0.16 -0.32  0.24  0.48  0.06  0.12  0.06  0.12 -0.04 -0.08
 [4,] -0.32 -0.80  0.48  1.20  0.12  0.30  0.12  0.30 -0.08 -0.20
 [5,] -0.04 -0.08  0.06  0.12  0.39  0.78 -0.11 -0.22 -0.26 -0.52
 [6,] -0.08 -0.20  0.12  0.30  0.78  1.95 -0.22 -0.55 -0.52 -1.30
 [7,] -0.04 -0.08  0.06  0.12 -0.11 -0.22  0.39  0.78 -0.26 -0.52
 [8,] -0.08 -0.20  0.12  0.30 -0.22 -0.55  0.78  1.95 -0.52 -1.30
 [9,]  0.36  0.72 -0.04 -0.08 -0.26 -0.52 -0.26 -0.52  0.84  1.68
[10,]  0.72  1.80 -0.08 -0.20 -0.52 -1.30 -0.52 -1.30  1.68  4.20
> 
> # solution
> sol = gi_lhs %*% rhs
> 
> # print
> sol
      [,1]
 [1,]  4.4
 [2,]  1.0
 [3,]  4.4
 [4,]  2.0
 [5,]  1.6
 [6,]  1.0
 [7,]  2.6
 [8,]  3.0
 [9,]  4.6
[10,] -1.0
> 

 

  • multiple trait animal model

마지막으로 다형질 개체 모형이다. 이 프로그램은 missing record, unequal desing matrices 까지 처리 가능한다.

자료

2 3 2 3 9 1
2 2 2 2 6 5
2 1 2 1 7 3
1 2 1 2 8 4
1 1 1 1 5 2

 

1, 2열 : 첫째 형질의 2개의 fixed effects

3, 4열 : 둘째 형질의 2개의 fixed effects

5, 6열 : 첫째, 둘째 형질의 표현형 

 

혈통

1 3 4
2 3 4
3 5 0
4 0 0
5 0 0

 

프로그램

# multiple trait animal model

# Date : 2020.08.06.

# Reference : Computational techneques in animal breeding, Ignacy Misztal

# MASS packages
if (!("MASS" %in% installed.packages())) {
    install.packages("MASS", dependencies = TRUE)
}
library(MASS)

# function : find address
find_addresses <- function() {
    
    for (i in 1:neff) {
        for (j in 1:ntrait) {
            
            # i=2 j=1
            
            if (datum(i, j) == miss) {
                address[i, j] <<- 0
                weight_cov[i, j] <<- 0
                next
            }
            
            baseaddr = ifelse(i == 1, j, sum(nlev[1:i - 1]) * ntrait + j)
            
            if (effecttype[i] == "effcross") {
                weight_cov[i, j] <<- 1
                address[i, j] <<- baseaddr + (datum(i, j) - 1) * ntrait
            } else if (effecttype[i] == "effcov") {
                weight_cov[i, j] <<- datum(i, j)
                if (nestedcov[i] == 0) {
                    address[i, j] <<- baseaddr
                } else if (nestedcov[i] > 0 && nestedcov[i] < neff) {
                    address[i, j] <<- baseaddr + (datum(nestedcov[i], j) - 1) * ntrait
                } else {
                    warning("wrong description of nested covariable")
                }
            } else {
                warning("unimplemented effect")
            }
        }
    }
    
}

# return data in indata
datum <- function(ef, tr) {
    return(indata[ef + (tr - 1) * neff])
}

# inverse of residual variance and covariance matrix
find_rinv <- function() {
    tempr = r
    for (i in 1:ntrait) {
        if (y[i] == miss) {
            tempr[i, ] = 0
            tempr[, i] = 0
        }
    }
    rinv <<- ginv(tempr)
}

# address for given level l of effect e and trait t
address1 <- function(e, l, t){
    return(ifelse(e == 1, (l - 1) * ntrait + t, sum(nlev[1 : e - 1]) * ntrait + (l - 1) * ntrait + t))
}

# setup g
setup_g <- function(){
    for(i in 1 : neff){
        if (randomnumb[i] != 0){
            g[,,i] <<- ginv(g0[,,i])
        }
    }
}

# add a genetic variance to the diagonal of left hand side
add_g_diag <- function(eff){
    for(i in 1 : nlev[eff]){
        for(j in 0 : (randomnumb[eff] - 1)){
            for(k in 0 : (randomnumb[eff] - 1)){
                for(t1 in 1 : ntrait){
                    for(t2 in 1 : ntrait){
                        m = address1(eff + j, i, t1)
                        l = address1(eff + k, i, t2)
                        #print(paste("i=",i,"j=",j,"k=",k,"t1=",t1,"t2=",t2,"m=",m,"l=",l))
                        lhs[m, l] <<- lhs[m, l] + g[t1 + j * ntrait, t2 + k * ntrait, eff]
                    }
                }
            }
        }
    }
}

# add genetic variacne matrix * NRN to left hand side
add_g_add <- function(type, eff){

    if(type == 'g_A'){
        w = c(1, -0.5, -0.5)
        res = c(2, 4/3, 1, 0)
    } else if(type == 'g_As'){
        w = c(1, -0.5, -0.25)
        res = c(16/11, 4/3, 16/15, 1)
    }
    
    for (di in 1:nped) {
        
        p = as.numeric(pedi[di,])
        
        ri = 1
        if(p[2] == 0){  ri = ri + 1 }
        if(p[3] == 0){  ri = ri + 1 }
        
        mendel = res[ri]
        
        for(i in 0 : (randomnumb[eff] - 1)){
            for(j in 0 : (randomnumb[eff] - 1)){
                for(t1 in 1 : ntrait){
                    for(t2 in 1 : ntrait){
                        for (k in 1 : 3) {
                            for (l in 1 : 3) {
                                if (p[k] != 0 && p[l] != 0) {
                                    m = address1(eff + i, p[k], t1)
                                    n = address1(eff + j, p[l], t2)
                                    a[p[k], p[l]] <<- a[p[k], p[l]] + w[k] * w[l] * mendel
                                    lhs[m, n] <<- lhs[m, n] + g[t1 + i * ntrait, t2 + j * ntrait, eff] * w[k] * w[l] * mendel 
                                }
                            }
                        }
                    }
                }
            }
        }
                        
    }
    
}


# parameters

# number of traits
ntrait = 2
ntrait

# number of effects
neff = 2
neff

# type of effects
effecttype = c("effcross", "effcross")
effecttype

# whether covariable effect is nested or not
nestedcov = c(0, 0)
nestedcov

# number of levels
nlev = c(2, 5)
nlev

# missing values
miss = 0
miss

# type of random effect : g_fixed, g_diag, g_A, g_As
randomtype = c("g_fixed", "g_A")
randomtype

# number of correlated effects per effect
randomnumb = c(0, 1)
randomnumb

# genetic varinace and covariance matrix
g0 = array(c(0), dim =c(ntrait, ntrait, neff))
g0[,,2] = matrix(c(2, -1, -1, 1), nrow = ntrait)
g0

# matrix for inverse of genetic variance matrix
g = array(c(0), dim =c(ntrait, ntrait, neff))
g

setup_g()

# residual variace
r = matrix(c(1, 0, 0, 1), nrow = 2)
r

# empty inverse of r
rinv = matrix(c(0), nrow = ntrait, ncol = ntrait)
rinv

# number of equations
neq = ntrait * sum(nlev)
neq

# make empty lhs and rhs
lhs = matrix(c(0), nrow = neq, ncol = neq)
lhs

rhs = matrix(c(0), nrow = neq)
rhs

# addresses
address = matrix(c(0), nrow=neff, ncol=ntrait)
address

# weight of covariable
weight_cov = matrix(c(0), nrow=neff, ncol=ntrait)
weight_cov

# set working directory setwd(choose.dir())
setwd("D:/temp/00_prediction")

# print working directory
getwd()

# read data : t1e1, t1e2, t2e1, t2e2, y1, y2
data = read.table("06_mt_lsq_data.txt", header = FALSE, sep = "", col.names = c("t1e1", "t1e2", "t2e1", "t2e2", "y1", "y2"), stringsAsFactors = FALSE)
data

# number of data
ndata = nrow(data)
ndata

# read pedigree : animal, sire, dam
pedi = read.table("04_stam_pedi.txt", header = FALSE, sep = "", col.names = c("animal", 
                                                                              "sire", "dam"), stringsAsFactors = FALSE)
pedi

# number of pedigree
nped = nrow(pedi)
nped

# inverse matrix of NRM(Nemerator Relationship Matrix)
a = matrix(c(0), nrow = nped, ncol = nped)
a

# loop data
for (di in 1:ndata) {
    # di = 5
    indata = as.numeric(data[di, 1:(ntrait * neff)])
    y = as.numeric(data[di, (ntrait * neff + 1):(ntrait * (neff + 1))])
    
    # address and weight_cov
    find_addresses()

    # inverse of r
    find_rinv()
    
    for (i in 1:neff) {
        for (j in 1:neff) {
            for (k in 1:ntrait) {
                for (l in 1:ntrait) {
                  lhs[address[i, k], address[j, l]] = lhs[address[i, k], address[j, l]] + weight_cov[i, k] * weight_cov[j, l] * rinv[k, l]
                }
            }
        }
        for (k in 1:ntrait) {
            for (l in 1:ntrait) {
                rhs[address[i, k]] = rhs[address[i, k]] + weight_cov[i, k] * rinv[k, l] * y[l]
            }
        }
    }
}

# print
lhs
rhs

# random effects' contributions
for(i in 1 : neff){
    if(randomtype[i] == 'g_fixed'){
        next
    } else if(randomtype[i] == 'g_diag'){
        add_g_diag(i)
    } else if(randomtype[i] == 'g_A' || randomtype[i] == 'g_As'){
        add_g_add(randomtype[i], i)
    } else {
        warning("unimplemented random type")
    }
}

# print lhs
lhs

# generalised inverse of lhs
gi_lhs = ginv(lhs)

# print
gi_lhs

# solution
sol = gi_lhs %*% rhs

# print
sol

 

실행 결과

> # MASS packages
> if (!("MASS" %in% installed.packages())) {
+     install.packages("MASS", dependencies = TRUE)
+ }
> library(MASS)
> 
> # function : find address
> find_addresses <- function() {
+     
+     for (i in 1:neff) {
+         for (j in 1:ntrait) {
+             
+             # i=2 j=1
+             
+             if (datum(i, j) == miss) {
+                 address[i, j] <<- 0
+                 weight_cov[i, j] <<- 0
+                 next
+             }
+             
+             baseaddr = ifelse(i == 1, j, sum(nlev[1:i - 1]) * ntrait + j)
+             
+             if (effecttype[i] == "effcross") {
+                 weight_cov[i, j] <<- 1
+                 address[i, j] <<- baseaddr + (datum(i, j) - 1) * ntrait
+             } else if (effecttype[i] == "effcov") {
+                 weight_cov[i, j] <<- datum(i, j)
+                 if (nestedcov[i] == 0) {
+                     address[i, j] <<- baseaddr
+                 } else if (nestedcov[i] > 0 && nestedcov[i] < neff) {
+                     address[i, j] <<- baseaddr + (datum(nestedcov[i], j) - 1) * ntrait
+                 } else {
+                     warning("wrong description of nested covariable")
+                 }
+             } else {
+                 warning("unimplemented effect")
+             }
+         }
+     }
+     
+ }
> 
> # return data in indata
> datum <- function(ef, tr) {
+     return(indata[ef + (tr - 1) * neff])
+ }
> 
> # inverse of residual variance and covariance matrix
> find_rinv <- function() {
+     tempr = r
+     for (i in 1:ntrait) {
+         if (y[i] == miss) {
+             tempr[i, ] = 0
+             tempr[, i] = 0
+         }
+     }
+     rinv <<- ginv(tempr)
+ }
> 
> # address for given level l of effect e and trait t
> address1 <- function(e, l, t){
+     return(ifelse(e == 1, (l - 1) * ntrait + t, sum(nlev[1 : e - 1]) * ntrait + (l - 1) * ntrait + t))
+ }
> 
> # setup g
> setup_g <- function(){
+     for(i in 1 : neff){
+         if (randomnumb[i] != 0){
+             g[,,i] <<- ginv(g0[,,i])
+         }
+     }
+ }
> 
> # add a genetic variance to the diagonal of left hand side
> add_g_diag <- function(eff){
+     for(i in 1 : nlev[eff]){
+         for(j in 0 : (randomnumb[eff] - 1)){
+             for(k in 0 : (randomnumb[eff] - 1)){
+                 for(t1 in 1 : ntrait){
+                     for(t2 in 1 : ntrait){
+                         m = address1(eff + j, i, t1)
+                         l = address1(eff + k, i, t2)
+                         #print(paste("i=",i,"j=",j,"k=",k,"t1=",t1,"t2=",t2,"m=",m,"l=",l))
+                         lhs[m, l] <<- lhs[m, l] + g[t1 + j * ntrait, t2 + k * ntrait, eff]
+                     }
+                 }
+             }
+         }
+     }
+ }
> 
> # add genetic variacne matrix * NRN to left hand side
> add_g_add <- function(type, eff){
+ 
+     if(type == 'g_A'){
+         w = c(1, -0.5, -0.5)
+         res = c(2, 4/3, 1, 0)
+     } else if(type == 'g_As'){
+         w = c(1, -0.5, -0.25)
+         res = c(16/11, 4/3, 16/15, 1)
+     }
+     
+     for (di in 1:nped) {
+         
+         p = as.numeric(pedi[di,])
+         
+         ri = 1
+         if(p[2] == 0){  ri = ri + 1 }
+         if(p[3] == 0){  ri = ri + 1 }
+         
+         mendel = res[ri]
+         
+         for(i in 0 : (randomnumb[eff] - 1)){
+             for(j in 0 : (randomnumb[eff] - 1)){
+                 for(t1 in 1 : ntrait){
+                     for(t2 in 1 : ntrait){
+                         for (k in 1 : 3) {
+                             for (l in 1 : 3) {
+                                 if (p[k] != 0 && p[l] != 0) {
+                                     m = address1(eff + i, p[k], t1)
+                                     n = address1(eff + j, p[l], t2)
+                                     a[p[k], p[l]] <<- a[p[k], p[l]] + w[k] * w[l] * mendel
+                                     lhs[m, n] <<- lhs[m, n] + g[t1 + i * ntrait, t2 + j * ntrait, eff] * w[k] * w[l] * mendel 
+                                 }
+                             }
+                         }
+                     }
+                 }
+             }
+         }
+                         
+     }
+     
+ }
> 
> 
> # parameters
> 
> # number of traits
> ntrait = 2
> ntrait
[1] 2
> 
> # number of effects
> neff = 2
> neff
[1] 2
> 
> # type of effects
> effecttype = c("effcross", "effcross")
> effecttype
[1] "effcross" "effcross"
> 
> # whether covariable effect is nested or not
> nestedcov = c(0, 0)
> nestedcov
[1] 0 0
> 
> # number of levels
> nlev = c(2, 5)
> nlev
[1] 2 5
> 
> # missing values
> miss = 0
> miss
[1] 0
> 
> # type of random effect : g_fixed, g_diag, g_A, g_As
> randomtype = c("g_fixed", "g_A")
> randomtype
[1] "g_fixed" "g_A"    
> 
> # number of correlated effects per effect
> randomnumb = c(0, 1)
> randomnumb
[1] 0 1
> 
> # genetic varinace and covariance matrix
> g0 = array(c(0), dim =c(ntrait, ntrait, neff))
> g0[,,2] = matrix(c(2, -1, -1, 1), nrow = ntrait)
> g0
, , 1

     [,1] [,2]
[1,]    0    0
[2,]    0    0

, , 2

     [,1] [,2]
[1,]    2   -1
[2,]   -1    1

> 
> # matrix for inverse of genetic variance matrix
> g = array(c(0), dim =c(ntrait, ntrait, neff))
> g
, , 1

     [,1] [,2]
[1,]    0    0
[2,]    0    0

, , 2

     [,1] [,2]
[1,]    0    0
[2,]    0    0

> 
> setup_g()
> 
> # residual variace
> r = matrix(c(1, 0, 0, 1), nrow = 2)
> r
     [,1] [,2]
[1,]    1    0
[2,]    0    1
> 
> # empty inverse of r
> rinv = matrix(c(0), nrow = ntrait, ncol = ntrait)
> rinv
     [,1] [,2]
[1,]    0    0
[2,]    0    0
> 
> # number of equations
> neq = ntrait * sum(nlev)
> neq
[1] 14
> 
> # make empty lhs and rhs
> lhs = matrix(c(0), nrow = neq, ncol = neq)
> lhs
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14]
 [1,]    0    0    0    0    0    0    0    0    0     0     0     0     0     0
 [2,]    0    0    0    0    0    0    0    0    0     0     0     0     0     0
 [3,]    0    0    0    0    0    0    0    0    0     0     0     0     0     0
 [4,]    0    0    0    0    0    0    0    0    0     0     0     0     0     0
 [5,]    0    0    0    0    0    0    0    0    0     0     0     0     0     0
 [6,]    0    0    0    0    0    0    0    0    0     0     0     0     0     0
 [7,]    0    0    0    0    0    0    0    0    0     0     0     0     0     0
 [8,]    0    0    0    0    0    0    0    0    0     0     0     0     0     0
 [9,]    0    0    0    0    0    0    0    0    0     0     0     0     0     0
[10,]    0    0    0    0    0    0    0    0    0     0     0     0     0     0
[11,]    0    0    0    0    0    0    0    0    0     0     0     0     0     0
[12,]    0    0    0    0    0    0    0    0    0     0     0     0     0     0
[13,]    0    0    0    0    0    0    0    0    0     0     0     0     0     0
[14,]    0    0    0    0    0    0    0    0    0     0     0     0     0     0
> 
> rhs = matrix(c(0), nrow = neq)
> rhs
      [,1]
 [1,]    0
 [2,]    0
 [3,]    0
 [4,]    0
 [5,]    0
 [6,]    0
 [7,]    0
 [8,]    0
 [9,]    0
[10,]    0
[11,]    0
[12,]    0
[13,]    0
[14,]    0
> 
> # addresses
> address = matrix(c(0), nrow=neff, ncol=ntrait)
> address
     [,1] [,2]
[1,]    0    0
[2,]    0    0
> 
> # weight of covariable
> weight_cov = matrix(c(0), nrow=neff, ncol=ntrait)
> weight_cov
     [,1] [,2]
[1,]    0    0
[2,]    0    0
> 
> # set working directory setwd(choose.dir())
> setwd("D:/temp/00_prediction")
> 
> # print working directory
> getwd()
[1] "D:/temp/00_prediction"
> 
> # read data : t1e1, t1e2, t2e1, t2e2, y1, y2
> data = read.table("06_mt_lsq_data.txt", header = FALSE, sep = "", col.names = c("t1e1", "t1e2", "t2e1", "t2e2", "y1", "y2"), stringsAsFactors = FALSE)
> data
  t1e1 t1e2 t2e1 t2e2 y1 y2
1    2    3    2    3  9  1
2    2    2    2    2  6  5
3    2    1    2    1  7  3
4    1    2    1    2  8  4
5    1    1    1    1  5  2
> 
> # number of data
> ndata = nrow(data)
> ndata
[1] 5
> 
> # read pedigree : animal, sire, dam
> pedi = read.table("04_stam_pedi.txt", header = FALSE, sep = "", col.names = c("animal", 
+                                                                               "sire", "dam"), stringsAsFactors = FALSE)
> pedi
  animal sire dam
1      5    0   0
2      1    3   4
3      2    3   4
4      3    5   0
5      4    0   0
> 
> # number of pedigree
> nped = nrow(pedi)
> nped
[1] 5
> 
> # inverse matrix of NRM(Nemerator Relationship Matrix)
> a = matrix(c(0), nrow = nped, ncol = nped)
> a
     [,1] [,2] [,3] [,4] [,5]
[1,]    0    0    0    0    0
[2,]    0    0    0    0    0
[3,]    0    0    0    0    0
[4,]    0    0    0    0    0
[5,]    0    0    0    0    0
> 
> # loop data
> for (di in 1:ndata) {
+     # di = 5
+     indata = as.numeric(data[di, 1:(ntrait * neff)])
+     y = as.numeric(data[di, (ntrait * neff + 1):(ntrait * (neff + 1))])
+     
+     # address and weight_cov
+     find_addresses()
+ 
+     # inverse of r
+     find_rinv()
+     
+     for (i in 1:neff) {
+         for (j in 1:neff) {
+             for (k in 1:ntrait) {
+                 for (l in 1:ntrait) {
+                   lhs[address[i, k], address[j, l]] = lhs[address[i, k], address[j, l]] + weight_cov[i, k] * weight_cov[j, l] * rinv[k, l]
+                 }
+             }
+         }
+         for (k in 1:ntrait) {
+             for (l in 1:ntrait) {
+                 rhs[address[i, k]] = rhs[address[i, k]] + weight_cov[i, k] * rinv[k, l] * y[l]
+             }
+         }
+     }
+ }
> 
> # print
> lhs
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14]
 [1,]    2    0    0    0    1    0    1    0    0     0     0     0     0     0
 [2,]    0    2    0    0    0    1    0    1    0     0     0     0     0     0
 [3,]    0    0    3    0    1    0    1    0    1     0     0     0     0     0
 [4,]    0    0    0    3    0    1    0    1    0     1     0     0     0     0
 [5,]    1    0    1    0    2    0    0    0    0     0     0     0     0     0
 [6,]    0    1    0    1    0    2    0    0    0     0     0     0     0     0
 [7,]    1    0    1    0    0    0    2    0    0     0     0     0     0     0
 [8,]    0    1    0    1    0    0    0    2    0     0     0     0     0     0
 [9,]    0    0    1    0    0    0    0    0    1     0     0     0     0     0
[10,]    0    0    0    1    0    0    0    0    0     1     0     0     0     0
[11,]    0    0    0    0    0    0    0    0    0     0     0     0     0     0
[12,]    0    0    0    0    0    0    0    0    0     0     0     0     0     0
[13,]    0    0    0    0    0    0    0    0    0     0     0     0     0     0
[14,]    0    0    0    0    0    0    0    0    0     0     0     0     0     0
> rhs
      [,1]
 [1,]   13
 [2,]    6
 [3,]   22
 [4,]    9
 [5,]   12
 [6,]    5
 [7,]   14
 [8,]    9
 [9,]    9
[10,]    1
[11,]    0
[12,]    0
[13,]    0
[14,]    0
> 
> # random effects' contributions
> for(i in 1 : neff){
+     if(randomtype[i] == 'g_fixed'){
+         next
+     } else if(randomtype[i] == 'g_diag'){
+         add_g_diag(i)
+     } else if(randomtype[i] == 'g_A' || randomtype[i] == 'g_As'){
+         add_g_add(randomtype[i], i)
+     } else {
+         warning("unimplemented random type")
+     }
+ }
> 
> # print lhs
> lhs
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]       [,9]      [,10] [,11] [,12]      [,13]      [,14]
 [1,]    2    0    0    0    1    0    1    0  0.0000000  0.0000000     0     0  0.0000000  0.0000000
 [2,]    0    2    0    0    0    1    0    1  0.0000000  0.0000000     0     0  0.0000000  0.0000000
 [3,]    0    0    3    0    1    0    1    0  1.0000000  0.0000000     0     0  0.0000000  0.0000000
 [4,]    0    0    0    3    0    1    0    1  0.0000000  1.0000000     0     0  0.0000000  0.0000000
 [5,]    1    0    1    0    4    2    0    0 -1.0000000 -1.0000000    -1    -1  0.0000000  0.0000000
 [6,]    0    1    0    1    2    6    0    0 -1.0000000 -2.0000000    -1    -2  0.0000000  0.0000000
 [7,]    1    0    1    0    0    0    4    2 -1.0000000 -1.0000000    -1    -1  0.0000000  0.0000000
 [8,]    0    1    0    1    0    0    2    6 -1.0000000 -2.0000000    -1    -2  0.0000000  0.0000000
 [9,]    0    0    1    0   -1   -1   -1   -1  3.3333333  2.3333333     1     1 -0.6666667 -0.6666667
[10,]    0    0    0    1   -1   -2   -1   -2  2.3333333  5.6666667     1     2 -0.6666667 -1.3333333
[11,]    0    0    0    0   -1   -1   -1   -1  1.0000000  1.0000000     2     2  0.0000000  0.0000000
[12,]    0    0    0    0   -1   -2   -1   -2  1.0000000  2.0000000     2     4  0.0000000  0.0000000
[13,]    0    0    0    0    0    0    0    0 -0.6666667 -0.6666667     0     0  1.3333333  1.3333333
[14,]    0    0    0    0    0    0    0    0 -0.6666667 -1.3333333     0     0  1.3333333  2.6666667
> 
> # generalised inverse of lhs
> gi_lhs = ginv(lhs)
> 
> # print
> gi_lhs
            [,1]       [,2]       [,3]       [,4]       [,5]       [,6]       [,7]       [,8]       [,9]      [,10]      [,11]
 [1,]  1.9090909 -0.6969697  1.3333333 -0.6666667 -1.4090909  0.6969697 -1.4090909  0.6969697 -1.1818182  0.6060606 -0.8181818
 [2,] -0.6969697  1.2121212 -0.6666667  0.6666667  0.6969697 -0.7121212  0.6969697 -0.7121212  0.6060606 -0.5757576  0.3939394
 [3,]  1.3333333 -0.6666667  1.6666667 -0.6666667 -1.3333333  0.6666667 -1.3333333  0.6666667 -1.3333333  0.6666667 -0.6666667
 [4,] -0.6666667  0.6666667 -0.6666667  1.0000000  0.6666667 -0.6666667  0.6666667 -0.6666667  0.6666667 -0.6666667  0.3333333
 [5,] -1.4090909  0.6969697 -1.3333333  0.6666667  1.5590909 -0.7469697  1.2590909 -0.6469697  1.1818182 -0.6060606  0.8181818
 [6,]  0.6969697 -0.7121212  0.6666667 -0.6666667 -0.7469697  0.8121212 -0.6469697  0.6121212 -0.6060606  0.5757576 -0.3939394
 [7,] -1.4090909  0.6969697 -1.3333333  0.6666667  1.2590909 -0.6469697  1.5590909 -0.7469697  1.1818182 -0.6060606  0.8181818
 [8,]  0.6969697 -0.7121212  0.6666667 -0.6666667 -0.6469697  0.6121212 -0.7469697  0.8121212 -0.6060606  0.5757576 -0.3939394
 [9,] -1.1818182  0.6060606 -1.3333333  0.6666667  1.1818182 -0.6060606  1.1818182 -0.6060606  1.6363636 -0.7878788  0.3636364
[10,]  0.6060606 -0.5757576  0.6666667 -0.6666667 -0.6060606  0.5757576 -0.6060606  0.5757576 -0.7878788  0.8484848 -0.2121212
[11,] -0.8181818  0.3939394 -0.6666667  0.3333333  0.8181818 -0.3939394  0.8181818 -0.3939394  0.3636364 -0.2121212  1.6363636
[12,]  0.3939394 -0.4242424  0.3333333 -0.3333333 -0.3939394  0.4242424 -0.3939394  0.4242424 -0.2121212  0.1515152 -0.7878788
[13,] -0.5909091  0.3030303 -0.6666667  0.3333333  0.5909091 -0.3030303  0.5909091 -0.3030303  0.8181818 -0.3939394  0.1818182
[14,]  0.3030303 -0.2878788  0.3333333 -0.3333333 -0.3030303  0.2878788 -0.3030303  0.2878788 -0.3939394  0.4242424 -0.1060606
            [,12]      [,13]       [,14]
 [1,]  0.39393939 -0.5909091  0.30303030
 [2,] -0.42424242  0.3030303 -0.28787879
 [3,]  0.33333333 -0.6666667  0.33333333
 [4,] -0.33333333  0.3333333 -0.33333333
 [5,] -0.39393939  0.5909091 -0.30303030
 [6,]  0.42424242 -0.3030303  0.28787879
 [7,] -0.39393939  0.5909091 -0.30303030
 [8,]  0.42424242 -0.3030303  0.28787879
 [9,] -0.21212121  0.8181818 -0.39393939
[10,]  0.15151515 -0.3939394  0.42424242
[11,] -0.78787879  0.1818182 -0.10606061
[12,]  0.84848485 -0.1060606  0.07575758
[13,] -0.10606061  1.9090909 -0.94696970
[14,]  0.07575758 -0.9469697  0.96212121
> 
> # solution
> sol = gi_lhs %*% rhs
> 
> # print
> sol
            [,1]
 [1,]  7.0606061
 [2,]  2.5757576
 [3,]  7.3333333
 [4,]  3.0000000
 [5,] -0.6606061
 [6,]  0.1242424
 [7,] -0.4606061
 [8,]  0.7242424
 [9,]  1.1212121
[10,] -0.8484848
[11,] -1.1212121
[12,]  0.8484848
[13,]  0.5606061
[14,] -0.4242424

 

  • 기본적인 가축 육종 모형의 육종가를 구하는 프로그램

복잡한 것은 모르겠고, 다형질 임의회귀 모형(multiple trait random regression model)의 육종가까지는 구할 수 있다. 임의회귀 모형에서는 개체별로 회귀식을 추정하므로(개체별로 nested된 회귀식) MME에는 들어가지 않지만 어느 개체에 nested 할지를 알려 주어야 하므로 그에 따른 처리가 필요하다.

프로그램

# Best Linear Unbiase Prediction of Breeding Values

# Date : 2020.08.06.

# Reference : Computational techneques in animal breeding, Ignacy Misztal

# MASS packages
if (!("MASS" %in% installed.packages())) {
    install.packages("MASS", dependencies = TRUE)
}
library(MASS)

# function : find address
find_addresses <- function() {
    
    for (i in 1:neff) {
        for (j in 1:ntrait) {

            if (datum(i, j) == miss) {
                address[i, j] <<- 0
                weight_cov[i, j] <<- 0
                next
            }
            
            baseaddr = ifelse(i == 1, j, sum(nlev[1:i - 1]) * ntrait + j)
            
            if (effecttype[i] == "effcross") {
                weight_cov[i, j] <<- 1
                address[i, j] <<- baseaddr + (datum(i, j) - 1) * ntrait
            } else if (effecttype[i] == "effcov") {
                weight_cov[i, j] <<- datum(i, j)
                if (nestedcov[i] == 0) {
                    address[i, j] <<- baseaddr
                } else if (nestedcov[i] > 0 && nestedcov[i] < neff) {
                    address[i, j] <<- baseaddr + (datum(nestedcov[i], j) - 1) * ntrait
                } else {
                    warning("wrong description of nested covariable")
                }
            } else if(effecttype[i] == "effnone") {
                
            } else {
                warning("unimplemented effect")
            }
        }
    }
    
}

# return data in indata
datum <- function(ef, tr) {
    return(indata[ef + (tr - 1) * neff])
}

# inverse of residual variance and covariance matrix
find_rinv <- function() {
    tempr = r
    for (i in 1:ntrait) {
        if (y[i] == miss) {
            tempr[i, ] = 0
            tempr[, i] = 0
        }
    }
    rinv <<- ginv(tempr)
}

# address for given level l of effect e and trait t
address1 <- function(e, l, t){
    return(ifelse(e == 1, (l - 1) * ntrait + t, sum(nlev[1 : e - 1]) * ntrait + (l - 1) * ntrait + t))
}

# setup g
setup_g <- function(){
    for(i in 1 : neff){
        if (randomnumb[i] != 0){
            g[,,i] <<- ginv(g0[,,i])
        }
    }
}

# add a genetic variance to the diagonal of left hand side
add_g_diag <- function(eff){
    
    for(i in 1 : nlev[eff]){
        for(j in 0 : (randomnumb[eff] - 1)){
            for(k in 0 : (randomnumb[eff] - 1)){
                for(t1 in 1 : ntrait){
                    for(t2 in 1 : ntrait){
                        m = address1(eff + j, i, t1)
                        l = address1(eff + k, i, t2)
                        #print(paste("i=",i,"j=",j,"k=",k,"t1=",t1,"t2=",t2,"m=",m,"l=",l))
                        lhs[m, l] <<- lhs[m, l] + g[t1 + j * ntrait, t2 + k * ntrait, eff]
                    }
                }
            }
        }
    }
    
}

# add genetic variacne matrix * NRN to left hand side
add_g_add <- function(type, eff){

    if(type == 'g_A'){
        w = c(1, -0.5, -0.5)
        res = c(2, 4/3, 1, 0)
    } else if(type == 'g_As'){
        w = c(1, -0.5, -0.25)
        res = c(16/11, 4/3, 16/15, 1)
    }
    
    for (di in 1:nped) {
        
        p = as.numeric(pedi[di,])
        
        ri = 1
        if(p[2] == 0){  ri = ri + 1 }
        if(p[3] == 0){  ri = ri + 1 }
        
        mendel = res[ri]
        
        for(i in 0 : (randomnumb[eff] - 1)){
            for(j in 0 : (randomnumb[eff] - 1)){
                for(t1 in 1 : ntrait){
                    for(t2 in 1 : ntrait){
                        for (k in 1 : 3) {
                            for (l in 1 : 3) {
                                if (p[k] != 0 && p[l] != 0) {
                                    m = address1(eff + i, p[k], t1)
                                    n = address1(eff + j, p[l], t2)
                                    a[p[k], p[l]] <<- a[p[k], p[l]] + w[k] * w[l] * mendel
                                    lhs[m, n] <<- lhs[m, n] + g[t1 + i * ntrait, t2 + j * ntrait, eff] * w[k] * w[l] * mendel 
                                }
                            }
                        }
                    }
                }
            }
        }
                        
    }
    
}


# parameters

# number of traits
ntrait = 2
ntrait

# number of effects
neff = 2
neff

# type of effects : cross-classified or covariable
effecttype = c("effcross", "effcross")
effecttype

# 0 means cross-classified or not nested, 1 means # of effect within which covariable is nested
nestedcov = c(0, 0)
nestedcov

# level of effect, level of covariable depends on if it is nested or not
nlev = c(2, 5)
nlev

# missing values trait/effect
miss = 0
miss

# type of random effect : g_fixed, g_diag, g_A, g_As
randomtype = c("g_fixed", "g_A")
randomtype

# number of correlated effects per effect
randomnumb = c(0, 1)
randomnumb

# genetic varinace and covariance matrix for each trait
vardim = ntrait * max(randomnumb)
g0 = array(c(0), dim =c(vardim, vardim, neff))
# genetic variance matrix for effect 2
g0[,,2] = matrix(c(2, -1, -1, 1), nrow = vardim)
g0

# matrix for inverse of genetic variance matrix
g = array(c(0), dim =c(vardim, vardim, neff))

setup_g()

g

# residual variace
r = matrix(c(1, 0, 0, 1), nrow = ntrait)
r

# empty inverse of r
rinv = matrix(c(0), nrow = ntrait, ncol = ntrait)
rinv

# number of equations
neq = ntrait * sum(nlev)
neq

# make empty lhs and rhs
lhs = matrix(c(0), nrow = neq, ncol = neq)
lhs

rhs = matrix(c(0), nrow = neq)
rhs

# addresses
address = matrix(c(0), nrow=neff, ncol=ntrait)
address

# weight of covariable
weight_cov = matrix(c(0), nrow=neff, ncol=ntrait)
weight_cov

# set working directory setwd(choose.dir())
setwd("D:/temp/00_prediction")

# print working directory
getwd()

# read data : t1e1, t1e2, t2e1, t2e2, y1, y2
data = read.table("06_mt_lsq_data.txt", header = FALSE, sep = "", col.names = c("t1e1", "t1e2", "t2e1", "t2e2", "y1", "y2"), stringsAsFactors = FALSE)
data

# number of data
ndata = nrow(data)
ndata

# read pedigree : animal, sire, dam
pedi = read.table("04_stam_pedi.txt", header = FALSE, sep = "", col.names = c("animal", 
                                                                              "sire", "dam"), stringsAsFactors = FALSE)
pedi

# number of pedigree
nped = nrow(pedi)
nped

# inverse matrix of NRM(Nemerator Relationship Matrix)
a = matrix(c(0), nrow = nped, ncol = nped)
a

# loop data
for (di in 1:ndata) {

    indata = as.numeric(data[di, 1:(ntrait * neff)])
    y = as.numeric(data[di, (ntrait * neff + 1):(ntrait * (neff + 1))])
    
    # address and weight_cov
    find_addresses()

    # inverse of r
    find_rinv()
    
    for (i in 1:neff) {
        for (j in 1:neff) {
            for (k in 1:ntrait) {
                for (l in 1:ntrait) {
                  lhs[address[i, k], address[j, l]] = lhs[address[i, k], address[j, l]] + weight_cov[i, k] * weight_cov[j, l] * rinv[k, l]
                }
            }
        }
        for (k in 1:ntrait) {
            for (l in 1:ntrait) {
                rhs[address[i, k]] = rhs[address[i, k]] + weight_cov[i, k] * rinv[k, l] * y[l]
            }
        }
    }
}

# print
lhs
rhs

# random effects' contributions
for(i in 1 : neff){
    if(randomtype[i] == 'g_fixed'){
        next
    } else if(randomtype[i] == 'g_diag'){
        add_g_diag(i)
    } else if(randomtype[i] == 'g_A' || randomtype[i] == 'g_As'){
        add_g_add(randomtype[i], i)
    } else {
        warning("unimplemented random type")
    }
}

# print lhs
lhs

# generalised inverse of lhs
gi_lhs = ginv(lhs)

# print
gi_lhs

# solution
sol = gi_lhs %*% rhs

# print
sol

# write a solution by effect, level and trait
# copy the continuous variances to the original effects
for(i in 1 : neff){
    if (randomnumb[i] > 1){
        for(j in 2 : randomnumb[i]){
            first = ntrait * (j - 1) + 1
            last = ntrait * j
            print(paste(i, j, first, last, (neff + j - 1)))
            g0[1 : ntrait, 1 : ntrait, (i + j - 1)] = g0[first : last, first : last, i]
        }
    }
}
line = c("effect level trait solution sep rel")
write(line, file = "solutions")
for(e in 1 : neff){
    # when the effect is used
    if(nlev[e] > 0){
        for(l in 1 : nlev[e]){
            for(t in 1 : ntrait){
                j = address1(e, l, t)
                sep2 = gi_lhs[j, j]
                # when the effect is random
                rel = ifelse(randomtype[e] != 'g_fixed',1 - sep2 / g0[t, t, e], 0)
                line = paste(e, l, t, sol[j], sqrt(sep2), rel)
                write(line, file = "solutions", append = TRUE)
            }
        }
    }
}

 

마지막 solution을 출력하는 부분은 개선이 필요하다.

 

+ Recent posts