score <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((5.1) - (input[1])) ^ (2.0)) + (((3.3) - (input[2])) ^ (2.0))) + (((1.7) - (input[3])) ^ (2.0))) + (((0.5) - (input[4])) ^ (2.0))))
    var1 <- exp((-0.06389634699048878) * ((((((5.7) - (input[1])) ^ (2.0)) + (((2.6) - (input[2])) ^ (2.0))) + (((3.5) - (input[3])) ^ (2.0))) + (((1.0) - (input[4])) ^ (2.0))))
    return(c((subroutine0(input)) + ((var0) * (0.8898986041811555)), (subroutine1(input)) + ((var0) * (0.37953658977037247)), (subroutine2(input)) + ((var1) * (0.0))))
}
subroutine0 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((5.1) - (input[1])) ^ (2.0)) + (((3.8) - (input[2])) ^ (2.0))) + (((1.9) - (input[3])) ^ (2.0))) + (((0.4) - (input[4])) ^ (2.0))))
    return((subroutine3(input)) + ((var0) * (0.8898986041811555)))
}
subroutine1 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((5.1) - (input[1])) ^ (2.0)) + (((3.8) - (input[2])) ^ (2.0))) + (((1.9) - (input[3])) ^ (2.0))) + (((0.4) - (input[4])) ^ (2.0))))
    return((subroutine4(input)) + ((var0) * (0.37953658977037247)))
}
subroutine2 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((5.9) - (input[1])) ^ (2.0)) + (((3.2) - (input[2])) ^ (2.0))) + (((4.8) - (input[3])) ^ (2.0))) + (((1.8) - (input[4])) ^ (2.0))))
    return((subroutine5(input)) + ((var0) * (110.34516826676301)))
}
subroutine3 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((5.7) - (input[1])) ^ (2.0)) + (((4.4) - (input[2])) ^ (2.0))) + (((1.5) - (input[3])) ^ (2.0))) + (((0.4) - (input[4])) ^ (2.0))))
    return((subroutine6(input)) + ((var0) * (0.0)))
}
subroutine4 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((5.7) - (input[1])) ^ (2.0)) + (((4.4) - (input[2])) ^ (2.0))) + (((1.5) - (input[3])) ^ (2.0))) + (((0.4) - (input[4])) ^ (2.0))))
    return((subroutine7(input)) + ((var0) * (0.05610417372785803)))
}
subroutine5 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((6.0) - (input[1])) ^ (2.0)) + (((2.7) - (input[2])) ^ (2.0))) + (((5.1) - (input[3])) ^ (2.0))) + (((1.6) - (input[4])) ^ (2.0))))
    return((subroutine8(input)) + ((var0) * (110.34516826676301)))
}
subroutine6 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((4.5) - (input[1])) ^ (2.0)) + (((2.3) - (input[2])) ^ (2.0))) + (((1.3) - (input[3])) ^ (2.0))) + (((0.3) - (input[4])) ^ (2.0))))
    return((subroutine9(input)) + ((var0) * (0.8898986041811555)))
}
subroutine7 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((4.5) - (input[1])) ^ (2.0)) + (((2.3) - (input[2])) ^ (2.0))) + (((1.3) - (input[3])) ^ (2.0))) + (((0.3) - (input[4])) ^ (2.0))))
    return((subroutine10(input)) + ((var0) * (0.3044555865539922)))
}
subroutine8 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((5.0) - (input[1])) ^ (2.0)) + (((2.3) - (input[2])) ^ (2.0))) + (((3.3) - (input[3])) ^ (2.0))) + (((1.0) - (input[4])) ^ (2.0))))
    return((subroutine11(input)) + ((var0) * (0.0)))
}
subroutine9 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((4.8) - (input[1])) ^ (2.0)) + (((3.4) - (input[2])) ^ (2.0))) + (((1.9) - (input[3])) ^ (2.0))) + (((0.2) - (input[4])) ^ (2.0))))
    return((subroutine12(input)) + ((var0) * (0.8898986041811555)))
}
subroutine10 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((4.8) - (input[1])) ^ (2.0)) + (((3.4) - (input[2])) ^ (2.0))) + (((1.9) - (input[3])) ^ (2.0))) + (((0.2) - (input[4])) ^ (2.0))))
    return((subroutine13(input)) + ((var0) * (0.37953658977037247)))
}
subroutine11 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((6.7) - (input[1])) ^ (2.0)) + (((3.0) - (input[2])) ^ (2.0))) + (((5.0) - (input[3])) ^ (2.0))) + (((1.7) - (input[4])) ^ (2.0))))
    return((subroutine14(input)) + ((var0) * (110.34516826676301)))
}
subroutine12 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((5.7) - (input[1])) ^ (2.0)) + (((3.8) - (input[2])) ^ (2.0))) + (((1.7) - (input[3])) ^ (2.0))) + (((0.3) - (input[4])) ^ (2.0))))
    return((subroutine15(input)) + ((var0) * (0.0)))
}
subroutine13 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((5.7) - (input[1])) ^ (2.0)) + (((3.8) - (input[2])) ^ (2.0))) + (((1.7) - (input[3])) ^ (2.0))) + (((0.3) - (input[4])) ^ (2.0))))
    return((subroutine16(input)) + ((var0) * (0.37953658977037247)))
}
subroutine14 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((5.6) - (input[1])) ^ (2.0)) + (((2.9) - (input[2])) ^ (2.0))) + (((3.6) - (input[3])) ^ (2.0))) + (((1.3) - (input[4])) ^ (2.0))))
    return((subroutine17(input)) + ((var0) * (0.0)))
}
subroutine15 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((5.4) - (input[1])) ^ (2.0)) + (((3.4) - (input[2])) ^ (2.0))) + (((1.7) - (input[3])) ^ (2.0))) + (((0.2) - (input[4])) ^ (2.0))))
    return((subroutine18(input)) + ((var0) * (0.7142250613852136)))
}
subroutine16 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((5.4) - (input[1])) ^ (2.0)) + (((3.4) - (input[2])) ^ (2.0))) + (((1.7) - (input[3])) ^ (2.0))) + (((0.2) - (input[4])) ^ (2.0))))
    return((subroutine19(input)) + ((var0) * (0.0)))
}
subroutine17 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((6.2) - (input[1])) ^ (2.0)) + (((2.2) - (input[2])) ^ (2.0))) + (((4.5) - (input[3])) ^ (2.0))) + (((1.5) - (input[4])) ^ (2.0))))
    return((subroutine20(input)) + ((var0) * (37.19509025661546)))
}
subroutine18 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((5.0) - (input[1])) ^ (2.0)) + (((3.0) - (input[2])) ^ (2.0))) + (((1.6) - (input[3])) ^ (2.0))) + (((0.2) - (input[4])) ^ (2.0))))
    return((subroutine21(input)) + ((var0) * (0.04218875216876044)))
}
subroutine19 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((5.0) - (input[1])) ^ (2.0)) + (((3.0) - (input[2])) ^ (2.0))) + (((1.6) - (input[3])) ^ (2.0))) + (((0.2) - (input[4])) ^ (2.0))))
    return((subroutine22(input)) + ((var0) * (0.0)))
}
subroutine20 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((5.4) - (input[1])) ^ (2.0)) + (((3.0) - (input[2])) ^ (2.0))) + (((4.5) - (input[3])) ^ (2.0))) + (((1.5) - (input[4])) ^ (2.0))))
    return((subroutine23(input)) + ((var0) * (62.115561183470184)))
}
subroutine21 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((5.7) - (input[1])) ^ (2.0)) + (((2.6) - (input[2])) ^ (2.0))) + (((3.5) - (input[3])) ^ (2.0))) + (((1.0) - (input[4])) ^ (2.0))))
    return((subroutine24(input)) + ((var0) * (-0.8898986041811555)))
}
subroutine22 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((6.3) - (input[1])) ^ (2.0)) + (((2.8) - (input[2])) ^ (2.0))) + (((5.1) - (input[3])) ^ (2.0))) + (((1.5) - (input[4])) ^ (2.0))))
    return((subroutine25(input)) + ((var0) * (-0.0)))
}
subroutine23 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((6.3) - (input[1])) ^ (2.0)) + (((2.5) - (input[2])) ^ (2.0))) + (((4.9) - (input[3])) ^ (2.0))) + (((1.5) - (input[4])) ^ (2.0))))
    return((subroutine26(input)) + ((var0) * (110.34516826676301)))
}
subroutine24 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((5.9) - (input[1])) ^ (2.0)) + (((3.2) - (input[2])) ^ (2.0))) + (((4.8) - (input[3])) ^ (2.0))) + (((1.8) - (input[4])) ^ (2.0))))
    return((subroutine27(input)) + ((var0) * (-0.0)))
}
subroutine25 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((6.0) - (input[1])) ^ (2.0)) + (((2.2) - (input[2])) ^ (2.0))) + (((5.0) - (input[3])) ^ (2.0))) + (((1.5) - (input[4])) ^ (2.0))))
    return((subroutine28(input)) + ((var0) * (-0.10077618026650095)))
}
subroutine26 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((4.9) - (input[1])) ^ (2.0)) + (((2.4) - (input[2])) ^ (2.0))) + (((3.3) - (input[3])) ^ (2.0))) + (((1.0) - (input[4])) ^ (2.0))))
    return((subroutine29(input)) + ((var0) * (0.0)))
}
subroutine27 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((6.0) - (input[1])) ^ (2.0)) + (((2.7) - (input[2])) ^ (2.0))) + (((5.1) - (input[3])) ^ (2.0))) + (((1.6) - (input[4])) ^ (2.0))))
    return((subroutine30(input)) + ((var0) * (-0.0)))
}
subroutine28 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((6.2) - (input[1])) ^ (2.0)) + (((2.8) - (input[2])) ^ (2.0))) + (((4.8) - (input[3])) ^ (2.0))) + (((1.8) - (input[4])) ^ (2.0))))
    var1 <- exp((-0.06389634699048878) * ((((((7.2) - (input[1])) ^ (2.0)) + (((3.0) - (input[2])) ^ (2.0))) + (((5.8) - (input[3])) ^ (2.0))) + (((1.6) - (input[4])) ^ (2.0))))
    var2 <- exp((-0.06389634699048878) * ((((((6.1) - (input[1])) ^ (2.0)) + (((3.0) - (input[2])) ^ (2.0))) + (((4.9) - (input[3])) ^ (2.0))) + (((1.8) - (input[4])) ^ (2.0))))
    var3 <- exp((-0.06389634699048878) * ((((((6.0) - (input[1])) ^ (2.0)) + (((3.0) - (input[2])) ^ (2.0))) + (((4.8) - (input[3])) ^ (2.0))) + (((1.8) - (input[4])) ^ (2.0))))
    var4 <- exp((-0.06389634699048878) * ((((((4.9) - (input[1])) ^ (2.0)) + (((2.5) - (input[2])) ^ (2.0))) + (((4.5) - (input[3])) ^ (2.0))) + (((1.7) - (input[4])) ^ (2.0))))
    var5 <- exp((-0.06389634699048878) * ((((((7.9) - (input[1])) ^ (2.0)) + (((3.8) - (input[2])) ^ (2.0))) + (((6.4) - (input[3])) ^ (2.0))) + (((2.0) - (input[4])) ^ (2.0))))
    var6 <- exp((-0.06389634699048878) * ((((((5.6) - (input[1])) ^ (2.0)) + (((2.8) - (input[2])) ^ (2.0))) + (((4.9) - (input[3])) ^ (2.0))) + (((2.0) - (input[4])) ^ (2.0))))
    return((((((((-0.04261957451303831) + ((var0) * (-0.37953658977037247))) + ((var1) * (-0.0))) + ((var2) * (-0.0))) + ((var3) * (-0.37953658977037247))) + ((var4) * (-0.37953658977037247))) + ((var5) * (-0.26472396872040066))) + ((var6) * (-0.3745962010653211)))
}
subroutine29 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((5.1) - (input[1])) ^ (2.0)) + (((2.5) - (input[2])) ^ (2.0))) + (((3.0) - (input[3])) ^ (2.0))) + (((1.1) - (input[4])) ^ (2.0))))
    return((subroutine31(input)) + ((var0) * (0.0)))
}
subroutine30 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((5.0) - (input[1])) ^ (2.0)) + (((2.3) - (input[2])) ^ (2.0))) + (((3.3) - (input[3])) ^ (2.0))) + (((1.0) - (input[4])) ^ (2.0))))
    return((subroutine32(input)) + ((var0) * (-0.8898986041811555)))
}
subroutine31 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((6.3) - (input[1])) ^ (2.0)) + (((2.8) - (input[2])) ^ (2.0))) + (((5.1) - (input[3])) ^ (2.0))) + (((1.5) - (input[4])) ^ (2.0))))
    return((subroutine33(input)) + ((var0) * (-110.34516826676301)))
}
subroutine32 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((5.1) - (input[1])) ^ (2.0)) + (((2.5) - (input[2])) ^ (2.0))) + (((3.0) - (input[3])) ^ (2.0))) + (((1.1) - (input[4])) ^ (2.0))))
    var1 <- exp((-0.06389634699048878) * ((((((4.9) - (input[1])) ^ (2.0)) + (((2.4) - (input[2])) ^ (2.0))) + (((3.3) - (input[3])) ^ (2.0))) + (((1.0) - (input[4])) ^ (2.0))))
    var2 <- exp((-0.06389634699048878) * ((((((6.3) - (input[1])) ^ (2.0)) + (((2.5) - (input[2])) ^ (2.0))) + (((4.9) - (input[3])) ^ (2.0))) + (((1.5) - (input[4])) ^ (2.0))))
    var3 <- exp((-0.06389634699048878) * ((((((5.4) - (input[1])) ^ (2.0)) + (((3.0) - (input[2])) ^ (2.0))) + (((4.5) - (input[3])) ^ (2.0))) + (((1.5) - (input[4])) ^ (2.0))))
    var4 <- exp((-0.06389634699048878) * ((((((6.2) - (input[1])) ^ (2.0)) + (((2.2) - (input[2])) ^ (2.0))) + (((4.5) - (input[3])) ^ (2.0))) + (((1.5) - (input[4])) ^ (2.0))))
    var5 <- exp((-0.06389634699048878) * ((((((5.6) - (input[1])) ^ (2.0)) + (((2.9) - (input[2])) ^ (2.0))) + (((3.6) - (input[3])) ^ (2.0))) + (((1.3) - (input[4])) ^ (2.0))))
    var6 <- exp((-0.06389634699048878) * ((((((6.7) - (input[1])) ^ (2.0)) + (((3.0) - (input[2])) ^ (2.0))) + (((5.0) - (input[3])) ^ (2.0))) + (((1.7) - (input[4])) ^ (2.0))))
    return((((((((0.11172510039290856) + ((var0) * (-0.8898986041811555))) + ((var1) * (-0.8898986041811555))) + ((var2) * (-0.0))) + ((var3) * (-0.0))) + ((var4) * (-0.0))) + ((var5) * (-0.756413813553974))) + ((var6) * (-0.0)))
}
subroutine33 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((6.0) - (input[1])) ^ (2.0)) + (((2.2) - (input[2])) ^ (2.0))) + (((5.0) - (input[3])) ^ (2.0))) + (((1.5) - (input[4])) ^ (2.0))))
    return((subroutine34(input)) + ((var0) * (-65.00217641452454)))
}
subroutine34 <- function(input) {
    var0 <- exp((-0.06389634699048878) * ((((((6.2) - (input[1])) ^ (2.0)) + (((2.8) - (input[2])) ^ (2.0))) + (((4.8) - (input[3])) ^ (2.0))) + (((1.8) - (input[4])) ^ (2.0))))
    var1 <- exp((-0.06389634699048878) * ((((((7.2) - (input[1])) ^ (2.0)) + (((3.0) - (input[2])) ^ (2.0))) + (((5.8) - (input[3])) ^ (2.0))) + (((1.6) - (input[4])) ^ (2.0))))
    var2 <- exp((-0.06389634699048878) * ((((((6.1) - (input[1])) ^ (2.0)) + (((3.0) - (input[2])) ^ (2.0))) + (((4.9) - (input[3])) ^ (2.0))) + (((1.8) - (input[4])) ^ (2.0))))
    var3 <- exp((-0.06389634699048878) * ((((((6.0) - (input[1])) ^ (2.0)) + (((3.0) - (input[2])) ^ (2.0))) + (((4.8) - (input[3])) ^ (2.0))) + (((1.8) - (input[4])) ^ (2.0))))
    var4 <- exp((-0.06389634699048878) * ((((((4.9) - (input[1])) ^ (2.0)) + (((2.5) - (input[2])) ^ (2.0))) + (((4.5) - (input[3])) ^ (2.0))) + (((1.7) - (input[4])) ^ (2.0))))
    var5 <- exp((-0.06389634699048878) * ((((((7.9) - (input[1])) ^ (2.0)) + (((3.8) - (input[2])) ^ (2.0))) + (((6.4) - (input[3])) ^ (2.0))) + (((2.0) - (input[4])) ^ (2.0))))
    var6 <- exp((-0.06389634699048878) * ((((((5.6) - (input[1])) ^ (2.0)) + (((2.8) - (input[2])) ^ (2.0))) + (((4.9) - (input[3])) ^ (2.0))) + (((2.0) - (input[4])) ^ (2.0))))
    return((((((((1.8136162062461285) + ((var0) * (-110.34516826676301))) + ((var1) * (-13.999391039896215))) + ((var2) * (-108.44329471899991))) + ((var3) * (-110.34516826676301))) + ((var4) * (-22.21095753342801))) + ((var5) * (-0.0))) + ((var6) * (-0.0)))
}


# If you use this code or parts of it, please cite the following paper
# Bruhin A., E. Fehr, D. Schunk (2018): "The Many Faces of Human Sociality: Uncovering the Distribution and Stability of Social Preferences",
# Journal of the European Economic Association, forthcoming.
# ===========================================================================================================================================

rm(list=ls()) # Clear the memory
library(compiler)
set.seed(51)

# Data-Preparation-Function
f.dataprep <- function(dat, persid, label_choice_x, label_indicators_x, label_indicators_y, label_self_x, label_other_x, label_self_y, label_other_y, nafiller=1) {
	tid <- table(dat[,persid])    #Table of individuals
	pid <- as.numeric(names(tid)) #Vector of individual identifiers
	j   <- length(tid)            #Number of individuals
	n   <- max(tid)               #Maximum number of choices per individual
	lk  <- length(label_indicators_x)        #Number of "left" regressors
	rk  <- length(label_indicators_y)        #Number of "right" regressors
	{if (lk != rk) {stop("Length of label_indicators_x and label_indicators_y differ!")}}
	k   <- lk                     #Number of regressors

	indicators_x  <- matrix(1, n*j, k)  #"left" regressor matrix
	indicators_y <- matrix(1, n*j, k)  #"right" regressor matrix

	nlist      <- list(c(), pid)
	self_x     <- matrix(0, n, j, dimnames=nlist) # Payoff matrix, player A, "X"
	other_x    <- matrix(0, n, j, dimnames=nlist) # Payoff matrix, player B, "X"
	self_y     <- matrix(0, n, j, dimnames=nlist) # Payoff matrix, player A, "Y"
	other_y    <- matrix(0, n, j, dimnames=nlist) # Payoff matrix, player B, "Y"
	choice_x <- matrix(0, n, j, dimnames=nlist) # Matrix indicating the choice (1=left, 0=right)
	sel        <- matrix(0, n, j, dimnames=nlist) # Matrix indicating whether an observation is present (panel may be unbalanced!)
	rm(nlist)

	#Fill the data and selection matrices individual by individual (could handle an unbalanced panel)
	for (i in 1:j) {
		sel[,i]        <- c(rep(1, tid[i]), rep(0, n-tid[i]))

		idx            <- dat[,persid] == pid[i]
		self_x[,i]     <- c(dat[idx, label_self_x],   rep(nafiller, n-tid[i]))
		other_x[,i]    <- c(dat[idx, label_other_x],  rep(nafiller, n-tid[i]))
		self_y[,i]     <- c(dat[idx, label_self_y],   rep(nafiller, n-tid[i]))
		other_y[,i]    <- c(dat[idx, label_other_y],  rep(nafiller, n-tid[i]))
		choice_x[,i] <- c(dat[idx, label_choice_x], rep(nafiller, n-tid[i]))

		{if (k > 1) {
			m1 <- as.matrix(dat[idx, label_indicators_x])
			m2 <- matrix(0, n-nrow(m1), ncol(m1))
			m  <- rbind(m1, m2)
			indicators_x[(n*(i-1)+1):(i*n),] <- m
			rm (m1,m2)

			m1 <- as.matrix(dat[idx, label_indicators_y])
			m2 <- matrix(0, n-nrow(m1), ncol(m1))
			m  <- rbind(m1, m2)
			indicators_y[(n*(i-1)+1):(i*n),] <- m
			rm(m1,m2)
		}}
	}
	list(tid=tid, pid=pid, n=n, j=j, k=k, indicators_x=indicators_x, indicators_y=indicators_y, self_x=self_x, other_x=other_x, self_y=self_y, other_y=other_y, choice_x=choice_x, sel=sel)
}
f.dataprep <- cmpfun(f.dataprep)

# Component Density Function
f.compdens <- function(theta.v, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc ,k, n, j) {
	theta.m <- matrix(theta.v, k+1, nc)

	linindex_x <- indicators_x  %*% theta.m[1:k,] # Linear index of X-choice, a (n*j x nc)-matrix
	linindex_y <- indicators_y %*% theta.m[1:k,]  # Linear index of Y-choice, a (n*j x nc)-matrix

	ret     <- matrix(0, j, nc)

	# Loop over all nc preference types
	for (c in 1:nc) {
		li_x   <- matrix(linindex_x[,c], n, j)
		li_y   <- matrix(linindex_y[,c], n, j)
		choicesens <- theta.m[k+1,c]
		cs_li_x   <- choicesens * ((1-li_x)*self_x + li_x*other_x)  #Type-specific deterministic utility of chosing "X" times choice sensitivity
		cs_li_y   <- choicesens * ((1-li_y)*self_y + li_y*other_y)  #Type-specific deterministic utility of chosing "Y" times choice sensitivity

		probs <- ( (exp(cs_li_x)/(exp(cs_li_x)+exp(cs_li_y)))^choice_x * (exp(cs_li_y)/(exp(cs_li_x)+exp(cs_li_y)))^(1-choice_x) )^sel

		for (i in 1:j) {
			ret[i,c] <- prod(probs[,i])
		}
	}
	ret
}
f.compdens <- cmpfun(f.compdens)

# Log Likelihood of the Mixture Model and its Gradient
f.totloglik <- function(psi, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc, k, n, j) {
	lpsi    <- length(psi)
	theta.v <- psi[1:(lpsi-nc+1)]
	mix     <- psi[(lpsi-nc+2):lpsi]
	mix     <- c(mix, 1-sum(mix))
	m       <- matrix(mix, j, nc, byrow=T)

	sum(log(rowSums( m*f.compdens(theta.v, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc, k, n, j))))
}
f.totloglik <- cmpfun(f.totloglik)

f.totloglik.gradient <- function(psi, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc, k, n, j) {
	lpsi    <- length(psi)
	theta.v <- psi[1:(lpsi-nc+1)]
	theta.m <- matrix(theta.v, k+1, nc)
	mix     <- psi[(lpsi-nc+2):lpsi]
	mix     <- c(mix, 1-sum(mix))
	m       <- matrix(mix, j, nc, byrow=T)

	nj           <- n*j
	choice_x.k   <- matrix(as.vector(choice_x), nj, k)
	sel.k        <- matrix(as.vector(sel)     , nj, k)
	self_x.k     <- matrix(as.vector(self_x)  , nj, k)
	other_x.k    <- matrix(as.vector(other_x) , nj, k)
	self_y.k     <- matrix(as.vector(self_y)  , nj, k)
	other_y.k    <- matrix(as.vector(other_y) , nj, k)

	cdens.m <- f.compdens(theta.v, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc ,k, n, j)
	denom.outerderiv   <- 1/matrix(rowSums(m*cdens.m), n, j, byrow=T)
	denom.outerderiv.k <- matrix(as.vector(denom.outerderiv), nj, k)

	ret.theta <- rep(0, nc*(k+1))
	ret.mix   <- rep(0, nc)

	for (c in 1:nc) {
		choicesens <- theta.m[k+1, c]
		beta  <- theta.m[1:k, c]

		li_x   <- matrix(as.vector(indicators_x %*% beta), n, j) # linear index X-choice
		li_y   <- matrix(as.vector(indicators_y %*% beta), n, j) # linear index Y-choice

		ul    <- (1-li_x)*self_x + li_x*other_x # Deterministic utility from X-choice
		ur    <- (1-li_y)*self_y + li_y*other_y # Deterministic utility from Y-choice
		ul.k  <- matrix(as.vector(ul), nj, k)
		ur.k  <- matrix(as.vector(ur), nj, k)

		innerderiv   <- mix[c]*matrix(cdens.m[,c],n,j,byrow=T)/((exp(choicesens*ul)/(exp(choicesens*ul)+exp(choicesens*ur)))^choice_x * (exp(choicesens*ur)/(exp(choicesens*ul)+exp(choicesens*ur)))^(1-choice_x))
		innerderiv.k <- matrix(as.vector(innerderiv), nj, k)

		choicesens.grad <- sel * denom.outerderiv * innerderiv * ((1/(exp(choicesens*ul)+exp(choicesens*ur))^2) * ( (exp(choicesens*ul)/(exp(choicesens*ul)+exp(choicesens*ur)))^choice_x * exp(choicesens*(ul + 2*ur))*(-ur + ul) * (exp(choicesens*ur)/(exp(choicesens*ul)+exp(choicesens*ur)))^(-choice_x) * (choice_x * exp(-choicesens*ul) - exp(-choicesens*ur) + choice_x * exp(-choicesens*ur)) ))
		choicesens.grad <- sum(choicesens.grad)

		beta.grad <- sel.k * denom.outerderiv.k * innerderiv.k * ((-1/(exp(choicesens*ul.k)+exp(choicesens*ur.k))^2) * ( (exp(choicesens*ul.k)/(exp(choicesens*ul.k)+exp(choicesens*ur.k)))^choice_x.k * choicesens*exp(choicesens*(ul.k + 2*ur.k))*(indicators_x*(self_x.k-other_x.k) + indicators_y*(other_y.k-self_y.k)) * (exp(choicesens*ur.k)/(exp(choicesens*ul.k)+exp(choicesens*ur.k)))^(-choice_x.k) * (choice_x.k * exp(-choicesens*ul.k) - exp(-choicesens*ur.k) + choice_x.k * exp(-choicesens*ur.k)) ))
		beta.grad <- colSums(beta.grad)

		mix.grad  <- sum(cdens.m[,c] * denom.outerderiv[1,])

		ret.theta[((c-1)*(k+1)+1):(c*(k+1))] <- c(beta.grad, choicesens.grad)
		ret.mix[c]                           <- mix.grad
	}
	ret.mix <- ret.mix - ret.mix[nc]
	ret     <- c(ret.theta, ret.mix[1:(nc-1)])

	ret
}
f.totloglik.gradient <- cmpfun(f.totloglik.gradient)

# Log Likelihood Part in the M-Step and its Gradient
f.mloglik <- function(theta.v, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc, k, n, j, tau) {
	sum(tau * log(f.compdens(theta.v, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc, k, n, j)))
}
f.mloglik <- cmpfun(f.mloglik)

f.mloglik.pregrad <- function(theta.c, weight, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc, k, n, j) {
	choicesens <- theta.c[k+1]
	beta       <- theta.c[1:k]

	weights <- matrix(weight, n, j, byrow=T) #The individual weights (used for the taus)

	li_x   <- matrix(as.vector(indicators_x %*% beta), n, j) # linear index X-choice
	li_y   <- matrix(as.vector(indicators_y %*% beta), n, j) # linear index Y-choice

	ul    <- (1-li_x)*self_x + li_x*other_x # Deterministic utility from X-choice
	ur    <- (1-li_y)*self_y + li_y*other_y # Deterministic utility from Y-choice

	denom <- 1/((exp(choicesens*ul)/(exp(choicesens*ul)+exp(choicesens*ur)))^choice_x * (exp(choicesens*ur)/(exp(choicesens*ul)+exp(choicesens*ur)))^(1-choice_x))

	#The gradient of choicesens (scalar)
	choicesens.grad <- sel * weights * denom * ((1/(exp(choicesens*ul)+exp(choicesens*ur))^2) * ( (exp(choicesens*ul)/(exp(choicesens*ul)+exp(choicesens*ur)))^choice_x * exp(choicesens*(ul + 2*ur))*(-ur + ul) * (exp(choicesens*ur)/(exp(choicesens*ul)+exp(choicesens*ur)))^(-choice_x) * (choice_x * exp(-choicesens*ul) - exp(-choicesens*ur) + choice_x * exp(-choicesens*ur)) ))
	choicesens.grad <- sum(choicesens.grad)

	#The gradient (k x 1)-vector of beta
	nj           <- n*j
	choice_x.k <- matrix(as.vector(choice_x), nj, k)
	denom.k      <- matrix(as.vector(denom)     , nj, k)
	weights.k    <- matrix(as.vector(weights)   , nj, k)
	ul.k         <- matrix(as.vector(ul)        , nj, k)
	ur.k         <- matrix(as.vector(ur)        , nj, k)
	sel.k        <- matrix(as.vector(sel)       , nj, k)
	self_x.k   <- matrix(as.vector(self_x)  , nj, k)
	other_x.k   <- matrix(as.vector(other_x)  , nj, k)
	self_y.k  <- matrix(as.vector(self_y) , nj, k)
	other_y.k  <- matrix(as.vector(other_y) , nj, k)

	beta.grad <- sel.k * weights.k * denom.k * ((-1/(exp(choicesens*ul.k)+exp(choicesens*ur.k))^2) * ( (exp(choicesens*ul.k)/(exp(choicesens*ul.k)+exp(choicesens*ur.k)))^choice_x.k * choicesens*exp(choicesens*(ul.k + 2*ur.k))*(indicators_x*(self_x.k-other_x.k) + indicators_y*(other_y.k-self_y.k)) * (exp(choicesens*ur.k)/(exp(choicesens*ul.k)+exp(choicesens*ur.k)))^(-choice_x.k) * (choice_x.k * exp(-choicesens*ul.k) - exp(-choicesens*ur.k) + choice_x.k * exp(-choicesens*ur.k)) ))
	beta.grad <- colSums(beta.grad)

	c(beta.grad, choicesens.grad)
}
f.mloglik.pregrad <- cmpfun(f.mloglik.pregrad)

f.mloglik.grad <- function(theta.v, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc, k, n, j, tau) {
	ret <- rep(0, (k+1)*nc)

	for (c in 1:nc) {
		ret[((k+1)*(c-1)+1):((k+1)*c)] <- f.mloglik.pregrad(theta.v[((c-1)*(k+1)+1):(c*(k+1))], tau[,c], choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc, k, n, j)
	}

	ret
}
f.mloglik.grad <- cmpfun(f.mloglik.grad)

# E-Step Function
f.estep <- function(theta.v, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc, k, n, j, mix) {
	m <- matrix(mix, j, nc, byrow=T)

	numerator   <- m * f.compdens(theta.v, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc, k, n, j)
	denominator <- matrix(rowSums(numerator), j, nc)

	ret <- matrix(numerator/denominator, j, nc, dimnames=list(colnames(sel), paste("comp",1:nc,sep="")))
	ret
}
f.estep <- cmpfun(f.estep)

# S-Step-Function
f.sstep <- function(em.tau,j,nc){
	sem.tau <- matrix(0,j,nc)
	for (i in 1:j){
		sem.tau[i,] <- t(rmultinom(1,1,em.tau[i,]))
	}
	sem.tau
}
f.sstep <- cmpfun(f.sstep)

# M-Step Function
f.mstep <- function(theta.v0, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc, k, n, j, tau) {
	ret <- optim(theta.v0, f.mloglik, f.mloglik.grad, method="BFGS", control=list(maxit=10000, trace=0, fnscale=-1), hessian=F, choice_x=choice_x, self_x=self_x, other_x=other_x, self_y=self_y, other_y=other_y, indicators_x=indicators_x, indicators_y=indicators_y, sel=sel, nc=nc, k=k, n=n, j=j, tau=tau)

	mix <- colMeans(tau)

	list(mix=mix, theta.v=ret$par)
}
f.mstep <- cmpfun(f.mstep)

# Annealing-Part-Function for the SAEM-Algorithm
f.annealing <- function(em.mix, em.vm, sem.mix, sem.vm, iter, b=20){
	{if (iter <= b)
		{q <- cos((iter/b)*acos(b/100))}
	 else
		{q <- (b/100)*sqrt(b/iter)}
	}

	mix <- q*sem.mix+(1-q)*em.mix
	vm  <- q*sem.vm+(1-q)*em.vm

	list(mix=mix, vm=vm)
}
f.annealing <- cmpfun(f.annealing)

# Sandwitch part of the clustered standard errors
f.sandwich <- function(psi, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc, k, n, j) {
	lpsi    <- length(psi);
	theta.v <- psi[1:(lpsi-nc+1)];
	theta.m <- matrix(theta.v, k+1, nc);
	mix     <- psi[(lpsi-nc+2):lpsi];
	mix     <- c(mix, 1-sum(mix));
	m       <- matrix(mix, j, nc, byrow=T);

	# Individual gradient
	nj           <- n*j;
	choice_x.k <- matrix(as.vector(choice_x), nj, k);
	sel.k        <- matrix(as.vector(sel)       , nj, k);
	self_x.k   <- matrix(as.vector(self_x)  , nj, k);
	other_x.k   <- matrix(as.vector(other_x)  , nj, k);
	self_y.k  <- matrix(as.vector(self_y) , nj, k);
	other_y.k  <- matrix(as.vector(other_y) , nj, k);

	cdens.m <- f.compdens(theta.v, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc ,k, n, j);
	denom.outerderiv   <- 1/matrix(rowSums(m*cdens.m), n, j, byrow=T);
	denom.outerderiv.k <- matrix(as.vector(denom.outerderiv), nj, k);

	ret.theta <- matrix(0, nj, nc*(k+1));
	ret.mix   <- matrix(0, nj, nc);

	for (c in 1:nc) {
		gamma <- theta.m[k+1, c];
		beta  <- theta.m[1:k, c];

		lli   <- matrix(as.vector(indicators_x  %*% beta), n, j); #Left linear index
		rli   <- matrix(as.vector(indicators_y %*% beta), n, j); #Right linear index

		ul    <- (1-lli)*self_x  + lli*other_x;  #Utility from "left" choice
		ur    <- (1-rli)*self_y + rli*other_y; #Utility from "right" choice
		ul.k  <- matrix(as.vector(ul), nj, k);
		ur.k  <- matrix(as.vector(ur), nj, k);

		innerderiv   <- mix[c]*matrix(cdens.m[,c],n,j,byrow=T)/((exp(gamma*ul)/(exp(gamma*ul)+exp(gamma*ur)))^choice_x * (exp(gamma*ur)/(exp(gamma*ul)+exp(gamma*ur)))^(1-choice_x));
		innerderiv.k <- matrix(as.vector(innerderiv), nj, k);

		gamma.grad <- sel * denom.outerderiv * innerderiv * ((1/(exp(gamma*ul)+exp(gamma*ur))^2) * ( (exp(gamma*ul)/(exp(gamma*ul)+exp(gamma*ur)))^choice_x * exp(gamma*(ul + 2*ur))*(-ur + ul) * (exp(gamma*ur)/(exp(gamma*ul)+exp(gamma*ur)))^(-choice_x) * (choice_x * exp(-gamma*ul) - exp(-gamma*ur) + choice_x * exp(-gamma*ur)) ));

		beta.grad <- sel.k * denom.outerderiv.k * innerderiv.k * ((-1/(exp(gamma*ul.k)+exp(gamma*ur.k))^2) * ( (exp(gamma*ul.k)/(exp(gamma*ul.k)+exp(gamma*ur.k)))^choice_x.k * gamma*exp(gamma*(ul.k + 2*ur.k))*(indicators_x*(self_x.k-other_x.k) + indicators_y*(other_y.k-self_y.k)) * (exp(gamma*ur.k)/(exp(gamma*ul.k)+exp(gamma*ur.k)))^(-choice_x.k) * (choice_x.k * exp(-gamma*ul.k) - exp(-gamma*ur.k) + choice_x.k * exp(-gamma*ur.k)) ));

		mix.grad  <- cdens.m[,c] * denom.outerderiv[1,]

		ret.theta[,((c-1)*(k+1)+1):(c*(k+1))] <- cbind(beta.grad, as.vector(gamma.grad));
		ret.mix[,c]                           <- as.vector(matrix(mix.grad/n,n,j,byrow=T));
	};

	ret.mix <- ret.mix - matrix(ret.mix[,nc], nj, nc)
	ret     <- cbind(ret.theta, ret.mix[,1:(nc-1)]);

	#Sandwich part
	sandwich <- matrix(0, lpsi, lpsi)
	for (i in 1:j) {
		gradi <- colSums(ret[((i-1)*n+1):(i*n),])
		sandwich <- sandwich + (gradi %o% gradi)
	}

	qc <- (nj-1) / (nj-lpsi) * j/(j-1) #df adjustment

	list(qc=qc, sandwich=sandwich)
}
f.sandwich <- cmpfun(f.sandwich)

# Function to compute clustered standard errors, relies on f.sandwich
f.clusterse <- function(estobj, dat, persid, label_choice_x, label_indicators_x, label_indicators_y, self_x, other_x, self_y, other_y, nc, sortrow=1) {
	prep         <- f.dataprep(dat, persid, label_choice_x, label_indicators_x, label_indicators_y, self_x, other_x, self_y, other_y, nafiller=1);
	n            <- prep$n;
	j            <- prep$j;
	k            <- prep$k;
	indicators_x <- prep$indicators_x;
	indicators_y <- prep$indicators_y;
	self_x       <- prep$self_x;
	other_x      <- prep$other_x;
	self_y       <- prep$self_y;
	other_y      <- prep$other_y;
	choice_x     <- prep$choice_x;
	sel          <- prep$sel;
	rm(prep);

	ll1 <- f.totloglik(estobj$ret$par, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc, k, n, j)
	if (abs(ll1 - estobj$ret$value)>0.001) stop(paste("Saved loglik", ll1, "and computed loglik", estobj$value, "differ"))

	sandwich <- f.sandwich(estobj$ret$par, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc, k, n, j)

	lpsi <- length(estobj$ret$par)
	vcm <- solve(-estobj$ret$hessian)
	vcm <- sandwich$qc * (vcm %*% sandwich$sandwich %*% vcm)

	se <- sqrt(diag(vcm))
	lastmix.se <- sqrt( rep(1,nc-1) %*% vcm[(lpsi-(nc-2)):lpsi, (lpsi-(nc-2)):lpsi] %*% rep(1,nc-1) )
	psi.se <- c(se,lastmix.se)
	psi    <- estobj$ret$par

	#Extract the point estimates
	theta.v    <- psi[1:(lpsi-nc+1)];
	mix        <- psi[(lpsi-nc+2):lpsi];
	mix        <- c(mix, 1-sum(mix));

	mix.m      <- matrix(mix,       1, nc, dimnames=list(c("mixture"), paste("comp",1:nc,sep="")));
	theta.m    <- matrix(theta.v, k+1, nc, dimnames=list(c(paste(label_indicators_x,label_indicators_y),"choicesens"), paste("comp",1:nc,sep="")));

	#Extract the standard errors
	theta.v.se <- psi.se[1:(lpsi-nc+1)];
	mix.se     <- psi.se[(lpsi-nc+2):(lpsi+1)];

	mix.m.se   <- matrix(mix.se,       1, nc, dimnames=list(c("mixture"), paste("comp",1:nc,sep="")));
	theta.m.se <- matrix(theta.v.se, k+1, nc, dimnames=list(c(paste(label_indicators_x,label_indicators_y),"choicesens"), paste("comp",1:nc,sep="")));

	pe.out <- rbind(mix.m,    theta.m);
	se.out <- rbind(mix.m.se, theta.m.se);

	#Sort the groups according to their size to avoid problems of label switching
	sortidx  <- order(pe.out[sortrow,]);
	pe.out   <- pe.out[, sortidx];
	se.out   <- se.out[, sortidx];

	p.out  <- 2*(1-pnorm(abs(pe.out)/se.out));

	cat("POINT ESTIMATES\n")
	print(round(pe.out,3));
	cat("\n------------------------------------------------\n");
	cat("ROBUST STANDARD ERRORS\n")
	print(round(se.out,3));
	cat("\n------------------------------------------------\n");
	cat("ROBUST P-VALUES\n")
	print(round(p.out,3));

	list(se=se.out, p=p.out, vcm=vcm)
}
f.clusterse <- cmpfun(f.clusterse)

# Main Estimation Function
f.estim <- function(dat, v0path, persid, nc, label_choice_x, label_indicators_x, label_indicators_y, label_self_x, label_other_x, label_self_y, label_other_y, saem=F, loglik1=NA, maxemiter=50, diffcrit=5e-3, sortrow=1) {

	# Prepares the data and stores it
	prep       <- f.dataprep(dat, persid, label_choice_x, label_indicators_x, label_indicators_y, label_self_x, label_other_x, label_self_y, label_other_y, nafiller=1)
	n          <- prep$n
	j          <- prep$j
	k          <- prep$k
	indicators_x      <- prep$indicators_x
	indicators_y     <- prep$indicators_y
	self_x   <- prep$self_x
	other_x   <- prep$other_x
	self_y  <- prep$self_y
	other_y  <- prep$other_y
	choice_x <- prep$choice_x
	sel        <- prep$sel
	rm(prep)

	# Prepares the start values
	v0      <- read.table(v0path, sep=",", header=F)[,1]
	theta.v <- runif(nc*(1+k),0.8,1.2) * rep(v0,nc) # Random variation of the start values from the pooled model
	aa      <- runif(nc, 0.5, 2)
	mix     <- aa/sum(aa) # Initial mixture
	rm(aa)

	# Initial EM control flow parameters
	iter  <- 1
	diff  <- 1
	llold <- 0
	llnew <- 1

	# EM/SAEM algorithm (see Dempster et al. (1977) and book by McLachlan (2000))
	cat("Starting EM type maximization...\n")
	while (iter < maxemiter+1 & abs(diff) > diffcrit) {
		cat("\n  EM-Type Iteration:", iter,"of max.",maxemiter,"\n")
		cat("\n     working on E-step.\n")
		tau.em <- f.estep(theta.v, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc, k, n, j, mix)
		cat("     working on M-step (EM algorithm).\n")
		mstep <- f.mstep(theta.v, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc, k, n, j, tau.em)
		theta.v.em <- mstep$theta.v
		mix.em     <- mstep$mix

		if (saem==T) {
			cat("\n     working on S-step.\n")
			tau.sem <- f.sstep(tau.em, j, nc)

			cat("     working on M-step (SEM algorithm).\n")
			mstep <- f.mstep(theta.v, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc, k, n, j, tau.sem)
			theta.v.sem <- mstep$theta.v
			mix.sem     <- mstep$mix

			ann <- f.annealing(mix.em, theta.v.em, mix.sem, theta.v.sem, iter, b=20)
			mix     <- ann$mix
			theta.v <- ann$v
		 } else {
		 	mix     <- mix.em
		 	theta.v <- theta.v.em
		 }

		# Update the control flow parameters
		iter  <- iter+1
		llold <- llnew
		psi   <- c(theta.v, mix[1:(length(mix)-1)])
		llnew <- f.totloglik(psi, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc, k, n, j)
		diff  <- llnew-llold
		cat("\n  Achieved Log Likelihood:", round(llnew,4),"\n\n  ----------\n")
	}
	cat("\n...done. Parameters after EM-type estimation:\n")
	mix.m   <- matrix(mix,       1, nc, dimnames=list(c("mixture"), paste("comp",1:nc,sep="")))
	theta.m <- matrix(theta.v, k+1, nc, dimnames=list(c(paste(label_indicators_x,label_indicators_y),"choicesens"), paste("comp",1:nc,sep="")))
	out     <- rbind(mix.m, theta.m)

	#Direct ML estimation
	ret  <- optim(psi,f.totloglik, f.totloglik.gradient, method="BFGS", control=list(maxit=100000,trace=1,REPORT=20, fnscale=-1), hessian=T, choice_x=choice_x, self_x=self_x, other_x=other_x, self_y=self_y, other_y=other_y, indicators_x=indicators_x, indicators_y=indicators_y, sel=sel, nc=nc, k=k, n=n, j=j)

	psi     <- ret$par #Extract the MLE
	lpsi    <- length(psi)
	psi.se <- sqrt(diag(solve(-ret$hessian))) #Standard errors

	#Extract the point estimates
	theta.v    <- psi[1:(lpsi-nc+1)]
	mix        <- psi[(lpsi-nc+2):lpsi]
	mix        <- c(mix, 1-sum(mix))

	mix.m      <- matrix(mix,       1, nc, dimnames=list(c("mixture"), paste("comp",1:nc,sep="")))
	theta.m    <- matrix(theta.v, k+1, nc, dimnames=list(c(paste(label_indicators_x,label_indicators_y),"choicesens"), paste("comp",1:nc,sep="")))

	#Extract the standard errors
	theta.v.se <- psi.se[1:(lpsi-nc+1)]
	mix.se   <- psi.se[(lpsi-nc+2):lpsi]
	mix.se   <- c(mix.se,NA)

	mix.m.se   <- matrix(mix.se,       1, nc, dimnames=list(c("mixture"), paste("comp",1:nc,sep="")))
	theta.m.se <- matrix(theta.v.se, k+1, nc, dimnames=list(c(paste(label_indicators_x,label_indicators_y),"choicesens"), paste("comp",1:nc,sep="")))

	tau     <- f.estep(theta.v, choice_x, self_x, other_x, self_y, other_y, indicators_x, indicators_y, sel, nc, k, n, j, mix)

	aic <- -2*ret$value + 2*lpsi
	bic <- -2*ret$value + log(sum(sel))*lpsi

	tauv   <- as.vector(tau)
	nec    <- sum(na.omit(-tauv*log(tauv)))/(ret$value-loglik1)

	i.out  <- matrix(c(ret$value, lpsi, sum(sel), sortrow, aic, bic, nec), , 1, dimnames=list(c("Loglik:", "# of parameters:", "# of observations:", "Sortrow (to avoid label switching):", "AIC:", "BIC:", "NEC:"), c()))
	pe.out <- rbind(mix.m,    theta.m)
	se.out <- rbind(mix.m.se, theta.m.se)

	#Sort the groups according to their size to avoid problems of label switching
	sortidx  <- order(pe.out[sortrow,])
	pe.out   <- pe.out[, sortidx]
	se.out   <- se.out[, sortidx]
	tau      <- tau[, sortidx]

	p.out  <- 2*(1-pnorm(abs(pe.out)/se.out))

	cat("\n------------------------------------------------\n")
	cat("GENERAL INFORMATION\n")
	print(round(i.out,3))
	cat("\n------------------------------------------------\n")
	cat("POINT ESTIMATES (NOT CLUSTERED)\n")
	print(round(pe.out,3))
	cat("\n------------------------------------------------\n")
	cat("STANDARD ERRORS (NOT CLUSTERED)\n")
	print(round(se.out,3))
	cat("\n------------------------------------------------\n")
	cat("P-VALUES\n")
	print(round(p.out,3))
	cat("\n------------------------------------------------\n")

	list(pe=pe.out, se=se.out, p=p.out, info=i.out, ret=ret, tau=tau, success=T)
}
f.estim <- cmpfun(f.estim)

# Load choice data from both experiments
dat1     <- read.table("choices_exp1.csv",  sep=",", header=T)
dat2     <- read.table("choices_exp2.csv",  sep=",", header=T)

# Remove erratic subjects (see 2nd paragraph of section 4; to replicate estimate individual parameters)
dropped  <- read.table("dropped_subjects_section4paragraph2.csv", sep=",", header=F)[,1]
dat1     <- dat1[(dat1$sid %in% dropped) == F, ]
dat2     <- dat2[(dat2$sid %in% dropped) == F, ]

# Estimating Finite Model with nc=3 Types using start values from aggregate estimation
cat("\n\n\n================== ESTIMATING SESSION 1 ================================\n")
pe1 <- f.estim(dat1, "svExp1_1cl.csv", "sid", nc=3, "choice_x", c("s_x","r_x","q","v"), c("s_y","r_y","q","v"), "self_x", "other_x", "self_y", "other_y", saem=T, loglik1=-5472.314, maxemiter=30, diffcrit=1e-3,sortrow=1)

cat("\n\n\n================== ESTIMATING SESSION 2 ================================\n")
pe2 <- f.estim(dat2, "svExp2_1cl.csv", "sid", nc=3, "choice_x", c("s_x","r_x","q","v"), c("s_y","r_y","q","v"), "self_x", "other_x", "self_y", "other_y", saem=T, loglik1=-4540.739, maxemiter=30, diffcrit=1e-3,sortrow=1)

cat("\n\nTo extract the individual ex-post probabilities of type membership type pe1$tau or pe2$tau.\n")

# Computing Robust Standard Errors
cat("\n\n\n================== ROBUST STANDARD ERRORS: SESSION 1 ===================\n")
rse1 <- f.clusterse(pe1, dat1, "sid", "choice_x", c("s_x","r_x","q","v"), c("s_y","r_y","q","v"), "self_x", "other_x", "self_y", "other_y", 3, sortrow=1)
cat("\n\n\n================== ROBUST STANDARD ERRORS: SESSION 2 ===================\n")
rse2 <- f.clusterse(pe2, dat2, "sid", "choice_x", c("s_x","r_x","q","v"), c("s_y","r_y","q","v"), "self_x", "other_x", "self_y", "other_y", 3, sortrow=1)

# Save the R workspace
save.image("finmix_est_3cl.RData")


\name{HilbertCurve}
\alias{HilbertCurve}
\title{
Initialize a Hilbert curve
}
\description{
Initialize a Hilbert curve
}
\usage{
HilbertCurve(s, e, level = 4, mode = c("normal", "pixel"),
    reference = FALSE, reference_gp = gpar(lty = 3, col = "#999999"),
    arrow = TRUE, zoom = NULL, newpage = TRUE,
    background_col = "transparent", background_border = NA,
    title = NULL, title_gp = gpar(fontsize = 16),
    start_from = c("bottomleft", "topleft", "bottomright", "topright"),
    first_seg = c("horizontal", "vertical"), legend = list(),
    padding = unit(2, "mm"))
}
\arguments{

  \item{s}{position that will be mapped as the start of the Hilbert curve. The value should a single numeric value. If it is a vector, the minimum is used.}
  \item{e}{position that will be mapped as the end of the Hilbert curve. The value should a single numeric value. If it is a vector, the maximum is used.}
  \item{level}{iteration level of the Hilbert curve. There will by \code{4^level - 1} segments in the curve.}
  \item{mode}{"normal" mode is used for low \code{level} value and "pixel" mode is always used for high \code{level} value, so the "normal" mode is always for low-resolution visualization while "pixel" mode is used for high-resolution visualization. See 'details' for explanation.}
  \item{reference}{whether add reference lines on the plot. Only works under 'normal' mode. The reference line is only used for illustrating how the curve folds.}
  \item{reference_gp}{graphic settings for the reference lines. It should be specified by \code{\link[grid]{gpar}}.}
  \item{arrow}{whether add arrows on the reference line. Only works under 'normal' mode.}
  \item{zoom}{Internally, position are stored as integer values. To better map the data to the Hilbert curve,  the original positions are zoomed according to the range and the level of Hilbert curve. E.g. if  the curve visualizes data ranging from 1 to 2 but level of the curve is set to 4, the positions will be zoomed by ~x2000 so that values like 1.5, 1.555 can be mapped to the curve with more accuracy. You don't need to care the zooming thing,  proper zooming factor is calculated automatically.}
  \item{newpage}{whether call \code{\link[grid]{grid.newpage}} to draw on a new graphic device.}
  \item{background_col}{background color.}
  \item{background_border}{background border border.}
  \item{title}{title of the plot.}
  \item{title_gp}{graphic parameters for the title. It should be specified by \code{\link[grid]{gpar}}.}
  \item{start_from}{which corner on the plot should the curve starts?}
  \item{first_seg}{the orientation of the first segment.}
  \item{legend}{a \code{\link[grid:grid.grob]{grob}} object, a \code{\link[ComplexHeatmap]{Legends-class}} object, or a list of them.}
  \item{padding}{padding around the Hilbert curve.}

}
\details{
This funciton initializes a Hilbert curve with level \code{level} which corresponds
to the range between \code{s} and \code{e}.

Under 'normal' mode, there is a visible Hilbert curve which plays like a folded axis and
different low-level graphics can be added afterwards according to the coordinates.
It works nice if the level of the Hilbert curve is small (say less than 6).

When the level is high (e.g. > 10), the whole 2D space will be almost completely filled by the curve and
it is impossible to add or visualize e.g. points on the curve. In this case, the 'pixel'
mode visualizes each tiny 'segment' as a pixel and maps values to colors. Internally, the whole plot
is represented as an RGB matrix and every time a new layer is added to the plot, the RGB matrix
will be updated according to the color overlay. When all the layers are added, normally a PNG figure is generated
directly from the RGB matrix. So the Hilbert
curve with level 11 will generate a PNG figure with 2048x2048 resolution. This is extremely
useful for visualize genomic data. E.g. If we make a Hilbert curve for human chromosome 1 with
level 11, then each pixel can represent 60bp (\code{249250621/2048/2048}) which is of very high resolution.

Under 'pixel' mode, if the current device is an interactive deivce, every time a new layer is added,
the image will be add to the interactive device as a rastered image. But still you can use \code{\link{hc_png,HilbertCurve-method}}
to export the plot as PNG file.

To make it short and clear, under "normal" mode, you can use following low-level graphic functions:

\itemize{
  \item \code{\link{hc_points,HilbertCurve-method}}
  \item \code{\link{hc_segments,HilbertCurve-method}}
  \item \code{\link{hc_rect,HilbertCurve-method}}
  \item \code{\link{hc_polygon,HilbertCurve-method}}
  \item \code{\link{hc_text,HilbertCurve-method}}
}

And under "pixel" mode, you can use following functions:

\itemize{
  \item \code{\link{hc_layer,HilbertCurve-method}}
  \item \code{\link{hc_png,HilbertCurve-method}}
  \item \code{\link{hc_polygon,HilbertCurve-method}}
  \item \code{\link{hc_text,HilbertCurve-method}}
}

Notice, \code{s} and \code{e} are not necessarily to be integers, it can be any values (e.g. numeric or even negative values).
}
\value{
A \code{\link{HilbertCurve-class}} object.
}
\author{
Zuguang Gu <z.gu@dkfz.de>
}
\examples{
HilbertCurve(1, 100, reference = TRUE)
HilbertCurve(1, 100, level = 5, reference = TRUE)
HilbertCurve(1, 100, title = "title", reference = TRUE)
HilbertCurve(1, 100, start_from = "topleft", reference = TRUE)

# plot with one legend
require(ComplexHeatmap)
legend = Legend(labels = c("a", "b"), title = "foo",
    legend_gp = gpar(fill = c("red", "blue")))
hc = HilbertCurve(1, 100, title = "title", legend = legend)
hc_segments(hc, x1 = 20, x2 = 40)

# plot with more than one legend
require(circlize)
legend1 = Legend(labels = c("a", "b"), title = "foo",
    legend_gp = gpar(fill = c("red", "blue")))
col_fun = colorRamp2(c(-1, 0, 1), c("green", "white", "red"))
legend2 = Legend(col_fun = col_fun, title = "bar")
hc = HilbertCurve(1, 100, title = "title", legend = list(legend1, legend2))
hc_segments(hc, x1 = 20, x2 = 40)
}


# Leap year calculator functions
# Author: Dainius Masiliunas, team Rython
# Date: 7th of January, 2016
# License: Apache License 2.0

# Calculates whether the year entered is a leap year or not.
is.leap = function(year)
{
    input = year

    # If characters, try coercing into a numeric
    if (is.character(year))
        year = suppressWarnings(as.numeric(year))

    # Sanity checks
    if (!is.numeric(year))
        stop("Error: argument of class numeric expected")
    if (is.na(year))
    {
        # If it's NA, then it might be due to the user entering NA or a failed coercion; but it could be a date
        year = try(as.numeric(strsplit(input, " ")[[1]][6]), TRUE)
        if (!is.numeric(year) || is.na(year) || class(year) == "try-error")
            stop("Error: failed to parse input argument")
    }
    if (year < 1582)
        warning(paste(year, "is out of the valid range"))

    # Make sure input is integer
    year = floor(year)

    if (year %% 4 > 0)
        return(FALSE)
    else if (year %% 100 > 0)
        return(TRUE)
    else if (year %% 400 > 0)
        return(FALSE)
    return(TRUE)
}


# This is a test/example rd file

Display "Beautiful Picture"  "Screen" "rgbobject"
Format 640 480

ObjectBegin "Pedestal"

XformPush # Pedestal Base
Scale 1 1 0.1
Translate 0 0 1
Cube
XformPop # Pedestal Base

# Column
XformPush
Translate 0 0 0.2
Scale 0.5 0.5 4
Cylinder 1.0 0.0 1.0 360.0
XformPop

XformPush # Pedestal Top
Translate 0 0 4.2
Scale 1 1 0.1
Translate 0 0 1
Cube
XformPop # Pedestal Top

ObjectEnd

ObjectBegin "Tetrahedron"
# Tetrahedron
PolySet "P"
4 # Vertices
4 # Faces

# Vertex points
 1.0  1.0  1.0
 1.0 -1.0 -1.0
-1.0  1.0 -1.0
-1.0 -1.0  1.0

# Face indices
3 2 1 -1
2 3 0 -1
1 0 3 -1
0 1 2 -1

ObjectEnd # Tetrahedron

ObjectBegin "Octahedron"

# Octahedron
PolySet "P"
6 # Vertices

8 # Faces

# Vertex points
 1.0  0.0  0.0
-1.0  0.0  0.0
 0.0  1.0  0.0
 0.0 -1.0  0.0
 0.0  0.0  1.0
 0.0  0.0 -1.0

# Face indices
0 2 4 -1
2 0 5 -1
3 0 4 -1
0 3 5 -1
2 1 4 -1
1 2 5 -1
1 3 4 -1
3 1 5 -1

ObjectEnd # Octahedron

ObjectBegin "Icosahedron"
# Icosahedron
PolySet "P"
12 # Vertices
20 # Faces

# Vertex points
 1.618034  1.0  0.0
-1.618034  1.0  0.0
 1.618034 -1.0  0.0
-1.618034 -1.0  0.0

 1.0  0.0  1.618034
 1.0  0.0 -1.618034
-1.0  0.0  1.618034
-1.0  0.0 -1.618034

 0.0  1.618034  1.0
 0.0 -1.618034  1.0
 0.0  1.618034 -1.0
 0.0 -1.618034 -1.0

# Face indices
 0  8  4 -1
 0  5 10 -1
 2  4  9 -1
 2 11  5 -1
 1  6  8 -1
 1 10  7 -1
 3  9  6 -1
 3  7 11 -1

 0 10  8 -1
 1  8 10 -1
 2  9 11 -1
 3 11  9 -1

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

 8  6  4 -1
 9  4  6 -1
10  5  7 -1
11  7  5 -1

ObjectEnd # Icosahedron

ObjectBegin "Dodecahedron"
# Dodecahedron
PolySet "P"
20 # Vertices
12 # Faces

# Vertex points
 1.0  1.0  1.0
 1.0  1.0 -1.0
 1.0 -1.0  1.0
 1.0 -1.0 -1.0
-1.0  1.0  1.0
-1.0  1.0 -1.0
-1.0 -1.0  1.0
-1.0 -1.0 -1.0

 0.618034  1.618034  0.0
-0.618034  1.618034  0.0
 0.618034 -1.618034  0.0
-0.618034 -1.618034  0.0

 1.618034  0.0  0.618034
 1.618034  0.0 -0.618034
-1.618034  0.0  0.618034
-1.618034  0.0 -0.618034

 0.0  0.618034  1.618034
 0.0 -0.618034  1.618034
 0.0  0.618034 -1.618034
 0.0 -0.618034 -1.618034

# Face indices
 1  8  0 12 13 -1
 4  9  5 15 14 -1
 2 10  3 13 12 -1
 7 11  6 14 15 -1

 2 12  0 16 17 -1
 1 13  3 19 18 -1
 4 14  6 17 16 -1
 7 15  5 18 19 -1

 4 16  0  8  9 -1
 2 17  6 11 10 -1
 1 18  5  9  8 -1
 7 19  3 10 11 -1

ObjectEnd # Dodecahdron

FrameBegin 1

CameraEye   -25.0 -30.0 20.0
CameraAt    0.0 0.0 3.0
CameraUp   0 0 1
CameraFOV  30.0

WorldBegin

# Lights
#FarLight  0 1 -1  1.0 1.0 0.9  1.0
PointLight 0 0  6  1.0 1.0 1.0  100
# Visual representation of light
Surface "matte"
Ka 1
Kd 0
Ks 0
XformPush
Translate 0 0 6
Scale 0.3 0.3 0.3
Sphere 1.0 -1.0 1.0 360.0
XformPop

# Put a point light in the middle of each displayed object to
# get a nice glow off of the pedastal surface
PointLight  0    10     6    1.0 0.0 0.0  5.0
PointLight -7.81  6.23  6    0.0 0.0 1.0  5.0
PointLight -9.75 -2.23  6    0.0 1.0 0.0  5.0
PointLight -4.34 -9.01  6    0.5 0.3 0.0  5.0
PointLight  4.34 -9.01  6    0.7 0.0 0.8  5.0
PointLight  9.75 -2.23  6    1.0 0.7 0.7  5.0
PointLight  7.81  6.23  6    1.0 1.0 0.0  5.0

XformPush # Star Pattern on Floor

Surface "matte"
Ka 1.0
Kd 0.0

Scale 8.5 8.5 1
Color 1.0 0.7 0.3
Line  0.000  1.000 0  0.975 -0.223 0
Line  0.975 -0.223 0 -0.434 -0.901 0
Line -0.434 -0.901 0 -0.782  0.623 0
Line -0.782  0.623 0  0.782  0.623 0
Line  0.782  0.623 0  0.434 -0.901 0
Line  0.434 -0.901 0 -0.975 -0.223 0
Line -0.975 -0.233 0  0.000  1.000 0

XformPop

Surface "plastic"
Ka 0.3
Kd 0.5
Ks 0.5

XformPush # Sphere 1.0 -1.0 1.0 360.0 on Pedestal

Rotate "Z" 0
Translate 0 10 0

Color 0.5 0.5 0.5

ObjectInstance "Pedestal"

Color 1.0 0.0 0.0
Translate 0 0 6
Sphere 1.0 -1.0 1.0 360.0

XformPop  # Sphere 1.0 -1.0 1.0 360.0 on Pedestal

XformPush # Cube on Pedestal
Rotate "Z" 51.43
Translate 0 10 0

Color 0.5 0.5 0.5

ObjectInstance "Pedestal"

Color 0.0 0.0 1.0
Translate 0 0 6.5
Rotate "X" 35.26
Rotate "Y" 45
Cube

XformPop  # Cube on Pedestal

XformPush # Cone on Pedestal
Rotate "Z" 102.86
Translate 0 10 0

Color 0.5 0.5 0.5

ObjectInstance "Pedestal"

Color 0.0 1.0 0.0
Translate 0 0 5
Scale 1 1 2
Cone 1.0 1.0 360.0

XformPop  # Cone on Pedestal

XformPush # Tetrahedron on Pedestal
Rotate "Z" 154.29
Translate 0 10 0

Color 0.5 0.5 0.5

ObjectInstance "Pedestal"

Color 0.5 0.3 0.0
Translate 0 0 6
Rotate "X" -35.2644
Rotate "Y" 45

ObjectInstance "Tetrahedron"

XformPop  # Tetrahedron on Pedestal

XformPush # Octahedron on Pedestal
Rotate "Z" 205.71
Translate 0 10 0

Color 0.5 0.5 0.5

ObjectInstance "Pedestal"

Color 0.7 0.0 0.8

Translate 0 0 6
Rotate "X" -35.2644
Rotate "Y" 45

ObjectInstance "Octahedron"

XformPop  # Octahedron on Pedestal

XformPush # Icosahedron on Pedestal
Rotate "Z" 257.14
Translate 0 10 0

Color 0.5 0.5 0.5

ObjectInstance "Pedestal"

Color 1.0 0.7 0.7
Translate 0 0 6
Rotate "X" -20.9051

ObjectInstance "Icosahedron"

XformPop  # Icosahedron on Pedestal

XformPush # Dodecahedron on Pedestal
Rotate "Z" 308.57
Translate 0 10 0

Color 0.5 0.5 0.5

ObjectInstance "Pedestal"

Color 1.0 1.0 0.0
Translate 0 0 6
Rotate "X" -58.2825

ObjectInstance "Dodecahedron"

XformPop  # Dodecahedron on Pedestal

WorldEnd
FrameEnd