blob: 848350e510c31a922a7445d780f170c54f11256a [file] [log] [blame]
#-------------------------------------------------------------
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
#-------------------------------------------------------------
# This script computes a solution for the hospital residency match problem.
#
# Residents.mtx:
# 2.0,1.0,3.0
# 1.0,2.0,3.0
# 1.0,2.0,0.0
#
# Since it is an ORDERED matrix, this means that Resident 1 (row 1) likes hospital 2 the most, followed by hospital 1 and hospital 3.
# If it was UNORDERED, this would mean that resident 1 (row 1) likes hospital 3 the most (since the value at [1,3] is the row max),
# followed by hospital 1 (2.0 preference value) and hospital 2 (1.0 preference value).
#
# Hospitals.mtx:
# 2.0,1.0,0.0
# 0.0,1.0,2.0
# 1.0,2.0,0.0
#
# Since it is an UNORDERED matrix this means that Hospital 1 (row 1) likes Resident 1 the most (since the value at [1,1] is the row max).
#
# capacity.mtx
# 1.0
# 1.0
# 1.0
#
# residencyMatch.mtx
# 2.0,0.0,0.0
# 1.0,0.0,0.0
# 0.0,2.0,0.0
#
# hospitalMatch.mtx
# 0.0,1.0,0.0
# 0.0,0.0,2.0
# 1.0,0.0,0.0
#
# Resident 1 has matched with Hospital 3 (since [1,3] is non-zero) at a preference level of 2.0.
# Resident 2 has matched with Hospital 1 (since [2,1] is non-zero) at a preference level of 1.0.
# Resident 3 has matched with Hospital 2 (since [3,2] is non-zero) at a preference level of 2.0.
#
# INPUT:
# ----------------------------------------------------------------------------------
# R Residents matrix R.
# It must be an ORDERED matrix.
# H Hospitals matrix H.
# It must be an UNORDRED matrix.
# capacity capacity of Hospitals matrix C.
# It must be a [n*1] matrix with non zero values.
# i.e. the leftmost value in a row is the most preferred partner's index.
# i.e. the leftmost value in a row in P is the preference value for the acceptor
# with index 1 and vice-versa (higher is better).
# verbose If the operation is verbose
# ----------------------------------------------------------------------------------
#
# OUTPUT:
# -----------------------------------------------------------------------------------------
# residencyMatch Result Matrix
# If cell [i,j] is non-zero, it means that Resident i has matched with Hospital j.
# Further, if cell [i,j] is non-zero, it holds the preference value that led to the match.
# hospitalMatch Result Matrix
# If cell [i,j] is non-zero, it means that Resident i has matched with Hospital j.
# Further, if cell [i,j] is non-zero, it holds the preference value that led to the match.
# -----------------------------------------------------------------------------------------
m_hospitalResidencyMatch = function(Matrix[Double] R, Matrix[Double] H, Matrix[Double] capacity, Boolean verbose = FALSE)
return (Matrix[Double] residencyMatch, Matrix[Double] hospitalMatch)
{
# in this step we consider that Residents Matrix is ORDERED.
# in this step we consider that Hospital Matrix is UNORDERED.
# in the next implementation can consider number of choices for every resident.
#TODO set a finite number of maximum iterations so that the execution terminates after maximum iterations.
print("STARTING RESIDENCY MATCH ALGORITHM");
print("READING R as residents AND H as Hospitals and capacity...");
m = nrow(R)
n = ncol(R)
residencyMatch = matrix(0.0, rows=m, cols=n)
hospitalMatch = matrix(0.0, rows=n, cols=m)
resultmMatrix = matrix(0.0, rows=nrow(R), cols=ncol(R))
if(nrow(capacity) != nrow(H))
print("ERROR: Missing capacity info for some hospitals")
startM = matrix(1.0, rows=m, cols=1) ### for checking while
hIndex =matrix(1.0, rows=m, cols=1)
proposer_pointers = matrix(1.0, rows=m, cols=1)
prev_Residents_vector = matrix(1.0, rows=n, cols=1)
prevIndex_Residents_vector = matrix(1.0, rows=n, cols=1)
prev_Residents_vector = rowMins(hospitalMatch)
prevIndex_Residents_vector = rowIndexMin(hospitalMatch)
# TODO remove the nested looping by vectorizing
while(sum(startM) > 0) {
for(i in 1:m) {
if(as.scalar(startM[i]) == 1) {
secondIndex = as.scalar (proposer_pointers[i])
hIndex[i] = as.scalar (R[i,secondIndex])
#the minimum value means most preference.
prev_Residents_vector = rowMaxs(hospitalMatch)
prevIndex_Residents_vector = rowIndexMax(hospitalMatch)
if (as.scalar(hIndex[i]) != 0) {
hosValue = as.scalar (H[as.scalar(hIndex[i]),i])
if (hosValue > 0) {
# if this hospital likes this resident and has the capacity ...
if(as.scalar(capacity[as.scalar (hIndex[i]),1]) >= 1) {
capacity[as.scalar(hIndex[i]),1] = as.scalar(capacity[as.scalar (hIndex[i]),1]) - 1
residencyMatch [i,as.scalar(hIndex[i])] = as.scalar(proposer_pointers[i])
hospitalMatch [as.scalar(hIndex[i]), i] = hosValue
#Disable freshly Matched resident to search for a new Hospital in the next round
startM[i] = 0
proposer_pointers[i] = as.scalar(proposer_pointers[i]) + 1
if (as.scalar(proposer_pointers[i]) > n)
proposer_pointers[i] = n
}
else if(as.scalar(prev_Residents_vector[as.scalar(hIndex[i])]) >= secondIndex) {
#in this step we check that if the hospital capacity is 0
# but the preference value of prev residents is lower than
#the preference value of current resident.
# we should replace the prev resident with current resident.
resPrev= as.scalar(prevIndex_Residents_vector[as.scalar (hIndex[i]),1])
hospitalMatch [as.scalar(hIndex[i]) ,resPrev] = 0
residencyMatch[resPrev,as.scalar(hIndex[i])] = 0
hospitalMatch [as.scalar(hIndex[i]),i ] = as.scalar(proposer_pointers[i])
residencyMatch [i,as.scalar(hIndex[i])] = as.scalar(proposer_pointers[i])
startM[i] = 0
prevResIndex =as.scalar(prevIndex_Residents_vector[as.scalar(hIndex[i]),1])
if(prevResIndex > 0){
startM[prevResIndex ] =1
proposer_pointers[i] = as.scalar(proposer_pointers[i]) + 1
if (as.scalar(proposer_pointers[i]) > n)
proposer_pointers[i] = n
}
}
}
if ( as.scalar (startM[i]) == 1 ) {
proposer_pointers[i] = as.scalar(proposer_pointers[i]) + 1
if (as.scalar(proposer_pointers[i]) > n)
proposer_pointers[i] = n
}
}
}
}
}
if(verbose) {
print("residencyMatch")
print(toString(residencyMatch))
print("hospitalMatch")
print(toString(hospitalMatch))
}
}