スクリプト

シンプレックス法を行ったlp.assign関数とlpSolveパッケージ。

lp.assign
function (cost.mat, direction = "min", presolve = 0, compute.sens = 0) 
{
    if (!is.matrix(cost.mat)) 
        stop("Matrix of costs required.")
    if (is.data.frame(cost.mat)) 
        cost.mat <- as.matrix(cost.mat)
    nr <- nrow(cost.mat)
    nc <- ncol(cost.mat)
    rnum.signs <- rep(3, nr)
    row.rhs <- rep(1, nr)
    cnum.signs <- rep(3, nc)
    col.rhs <- rep(1, nc)
    if (direction == "min") 
        direction <- as.integer(0)
    else if (direction == "max") 
        direction <- as.integer(1)
    else stop("Direction must be 'min' or 'max'")
    varcount <- as.integer(nr * nc)
    objective <- as.double(c(0, c(t(cost.mat))))
    const.count <- as.integer(nr + nc)
    intcount <- as.integer(varcount)
    intvec <- as.integer(1:varcount)
    objval <- as.double(0)
    int.count <- nc * nr
    integers <- as.integer(numeric(int.count))
    solution <- as.double(numeric(nc * nr))
    status <- as.integer(0)
    sens.coef.from <- sens.coef.to <- 0
    duals <- duals.from <- duals.to <- 0
    if (compute.sens) {
        sens.coef.from <- sens.coef.to <- numeric(varcount)
        duals <- duals.from <- duals.to <- numeric(varcount + 
            const.count)
    }
    lps.out <- .C("lp_transbig", direction = direction, rcount = as.integer(nr), 
        ccount = as.integer(nc), costs = objective, rsigns = as.integer(rnum.signs), 
        rrhs = as.double(row.rhs), csigns = as.integer(cnum.signs), 
        crhs = as.double(col.rhs), objval = objval, int.count = int.count, 
        integers = integers, solution = solution, presolve = as.integer(presolve), 
        compute.sens = as.integer(compute.sens), sens.coef.from = as.double(sens.coef.from), 
        sens.coef.to = as.double(sens.coef.to), duals = as.double(duals), 
        duals.from = as.double(duals.from), duals.to = as.double(duals.to), 
        status = status, PACKAGE = "lpSolve")
    lps.out$solution = matrix(lps.out$solution, nr, nc, byrow = TRUE)
    if (length(duals) > 0) {
        lps.out$sens.coef.from <- matrix(lps.out$sens.coef.from, 
            nr, nc, byrow = TRUE)
        lps.out$sens.coef.to <- matrix(lps.out$sens.coef.to, 
            nr, nc, byrow = TRUE)
        lps.out$duals <- matrix(lps.out$duals, nr, nc, byrow = TRUE)
        lps.out$duals.from <- matrix(lps.out$duals.from, nr, 
            nc, byrow = TRUE)
        lps.out$duals.to <- matrix(lps.out$duals.to, nr, nc, 
            byrow = TRUE)
    }
    lps.out$costs <- cost.mat
    if (any(names(version) == "language")) 
        class(lps.out) <- "lp"
    else oldClass(lps.out) <- "lp"
    lps.out
}
<environment: namespace:lpSolve>

データの準備

studentid <- c("RA", "NA", "MA", "MA", "YA", "HA", "TI", "YI", "KI", "HI", "YI", "YI", "YI", "EI", "KI", "YI", "HI", "YU", "YO", "KO", "KO", "YO", "SO", "YO", "JO", "TO", "NO", "SO", "YO", "TO", "MO", "TK", "TK", "RK", "KK", "YK", "RK", "MK", "YK", "KG", "KS", "YS", "KS", "KS",  "YS", "YS", "ES", "KS", "SS", "MD", "KT", "AT", "YT", "ST", "TN", "TN", "KN", "YN", "TN", "MN", "RN", "KH", "YH", "AH", "YH", "MH", "GF", "YF", "HF", "MF", "RF", "KH", "TM", "TM", "KM", "NM", "SM", "HM", "AM", "YM", "HM", "YM", "NM", "TY", "TY", "NY", "AY", "TY", "FY", "NY", "RY", "AY", "KW", "KY", "TA", "MO", "HO", "YO", "HK", "HK", "NS", "MS", "KT", "TH", "JF", "HH", "YK", "KD", "HF", "TY")
studentid <- paste(1:length(studentid), studentid, sep="")
finalexpect <- as.matrix(read.csv("simplexexpectdata.csv"))
sscourse <- as.matrix(read.csv("sscourse.csv"))[, -1]
ssgroup <- as.matrix(read.csv("ssgroup.csv"))[, -1]
ssexpect <- as.matrix(read.csv("ssexpect.csv"))[, -1]
niter <- ncol(sscourse)
#上位者
highscorer <- c(74, 27, 102, 92, 42, 7, 80, 72, 35, 94, 81, 46)
#行が学生、列がシミュレーション回数、割当コース、希望、小グループ
simplexarray <- array(0, c(110, niter, 3))
dimnames(simplexarray) <- list(studentid, 1:niter, c("course", "expect", "group"))
simplexarray[ highscorer, , "course"] <- c(10, 14, 16, 21, 24, 38, 47, 75, 77, 79, 98, 101)
simplexarray[-highscorer, , "course"] <- sscourse
simplexarray[ highscorer, , "expect"] <- 3
simplexarray[-highscorer, , "expect"] <- ssexpect
simplexarray[ highscorer, , "group"] <- c(2, 3, 3, 4, 4, 7, 9, 14, 14, 15, 18, 19)
simplexarray[-highscorer, , "group"] <- ssgroup

各コースの希望の累計数

count.expect <- function(vec){
	exA <- sum(vec == 3)
	exB <- sum(vec == 2)
	exD <- sum(vec == -15)
	return(c(exA, exB, exD))
}
expect_res <- apply(finalexpect, 2, count.expect)
#png("No_course_expect.png", 1200, 300)
barplot(expect_res, col=c("red", "yellow", "green"), main="No of ")
xaxispoint <- barplot(expect_res, plot=FALSE)
axis(1, at=xaxispoint, labels=1:ncol(expect_res), tick=FALSE, pos=0.03, las=2, cex.axis=0.8)
#dev.off()

コースが確定してしまう人

#コースが確定してしまう人
d <- simplexarray[which(sapply(apply(simplexarray[, , "course"], 1, unique), length) == 1), 1, "course"]

どれくらいのシミュレーション回数で収束するか確認。
もっとも取りうるコース数が多い108番で確認。

#asymp.array <- array(0, c(niter, dim(simplexarray)[1], length(studentid))) #これはメモリ的に無理
asymp.array <- array(0, c(niter, dim(simplexarray)[1], 1)) 
for(who in 1){
	tempmat <- matrix(0, niter, dim(simplexarray)[1])
	for(ni in 1:niter){
		temp <- simplexarray[c(108)[who], ,"course"]
		tempmat[ni, temp[ni]] <- 1
		print(ni)
	}
	asymp.array[, , who] <- apply(tempmat, 2, cumsum) / (1:niter)
	matplot(asymp.array[, , who], type="l", xlab="No. simulation trials", ylab="probability")
	title(paste("course assign probability simulation"))
}

どのコースになるか、確率の収束

prob.course <- diag(0, dim(simplexarray)[1])
dimnames(prob.course) <- list(studentid, 1:dim(simplexarray)[1])
for(st in 1:dim(simplexarray)[1]){
	coursecountvec <- numeric(dim(simplexarray)[1])
	for(cs in 1:1:dim(simplexarray)[1]){
		coursecountvec[cs] <- sum(simplexarray[st, , "course"] == cs) / niter
		print(c(st, cs))
	}
	prob.course[st, ] <- coursecountvec
}
#write.csv(prob.course, file="prob.course.csv")

各個人が属するグループの確率

indvgroup <- matrix(0, nrow(simplexarray[, , "group"]), length(unique(c(simplexarray[, , "group"]))))
dimnames(indvgroup) <- list(studentid, 1:length(unique(c(simplexarray[, , "group"]))))
niter <- dim(simplexarray)[2]
for(st in 1:nrow(simplexarray[, , "group"])){
	for(gr in 1:length(unique(c(simplexarray[, , "group"])))){
		indvgroup[st, gr] <- sum(simplexarray[st, , "group"] == gr) / niter
		#print(c(st, gr))
	}
}

二人選んで、一緒のグループになる確率

partnerres <- diag(0, nrow(simplexarray[, , "group"]))
dimnames(partnerres) <- list(studentid, studentid)
niter <- dim(simplexarray)[2]
for(g in 1:nrow(simplexarray[, , "group"])){
	partnerres[, g] <- t(apply(t(t(simplexarray[, , "group"]) == simplexarray[g, , "group"]), 1, cumsum) / 1:niter)[, ncol(simplexarray[, , "group"])]
	#print(g)
}

A希望になる確率

expect.count <- function(vec, expect.score){
	return(sum(vec == expect.score))
}
resA <- apply(simplexarray[, , "expect"], 1, expect.count, expect.score=3)
resA <- resA / niter
#png("expect_probability.png", 1200, 300)
barplot(resA, col=rainbow(length(resA)), axisname=FALSE)
xaxispoint <- barplot(resA, plot=FALSE)
axis(1, at=xaxispoint, labels=rownames(simplexarray), tick=FALSE, pos=0.01, las=2, cex.axis=0.8)
#dev.off()

A希望の数と割当結果

NoA <- apply(finalexpect, 1, count.expect)[1,]
Acoef <- cbind(NoA[-highscorer], resA[-highscorer])

Alist <- lapply(mapply(rep, 0, 4:6), unique)
for(i in 4:6){
	if(i != 6){
		Alist[[i - 3]] <- Acoef[which(Acoef[, 1] == i), 2]
	}else{
		Alist[[i - 3]] <- Acoef[which(Acoef[, 1] >= i), 2]		
	}
}
Ag <- rep(1:length(sapply(Alist, length)), sapply(Alist, length))
pairwise.t.test(unlist(Alist), Ag, p.adj="bonf")

誰と同じになるかヒートマップ

library(gplots)
#png("heatmap_twopair.png", 1200, 1200)
heatmap.2(partnerres, scale="none", col=c(colorpanel(100, low="white", high="black"), "red"), symkey=FALSE, key=TRUE, keysize=0.3, density.info="none", tracecol=NULL, cexRow=1, cexCol=1, 
distfun=function(a){dist(a, method="maximum")},
hclustfun=function(b){hclust(b, method="complete")})
#dev.off()

#png("heatmap_group.png", 300, 1200)
heatmap.2(indvgroup, scale="none", col=c(colorpanel(100, low="white", high="black"), "red"), symkey=FALSE, key=FALSE, keysize=0.2, density.info="none", trace="none", dendrogram="none", cexRow=1, cexCol=1.5, 
distfun=function(a){dist(a, method="maximum")},
hclustfun=function(b){hclust(b, method="complete")})
#dev.off()