나는 승객과 택시를 맞추기 위해 Gale-Shapley 알고리즘을 구현 중이다. 지금까지는 현재 일치를 거부하거나 유지하기 위해 단일 기본 설정 구조 (거리)가 있습니다.Gale-Shapley 구현 다차원 배열 문제
모두 괜찮아 보이는군요. 나는 해결책에 가깝다고 생각합니다. 그러나 환경 설정 데이터 (multidim 배열)에 액세스 할 때 이상한 일이 발생합니다. 두 번째 인덱스 인 kTaxiIndex
은 올바른 값을 갖지만 인덱싱 할 때 같은 행의 다른 열에서 데이터를 가져옵니다! 나는 이미 변수를 옮겼다. 아무도 여기에 무슨 일이 일어나는지 조금씩 단서가 있습니까?
모든 도움을 환영합니다.
class TaxiScheduler {
ArrayList acceptorTaxis;
ArrayList proposorPassengers;
Integer [] waitingList; //index represent taxis, contents passengers
ArrayList<Integer> rejectionPool; //where unmatched passengers are kept
Integer [] rejectionCounter; //determines the KBest option for that passenger
Double [][] distancePreferences; //unique preference structure
public TaxiScheduler(){
}
public Integer[] doGaleShapley(ArrayList taxis, ArrayList passengers){
acceptorTaxis = taxis;
proposorPassengers = passengers;
waitingList = new Integer [acceptorTaxis.size()]; //keeps best current match
rejectionPool = new ArrayList<Integer>(); //rejected passengers' indexes
rejectionCounter = new Integer [proposorPassengers.size()]; //keeps track of rejections per passenger
distancePreferences = new Double[proposorPassengers.size()][acceptorTaxis.size()];
initPoolandCounter(); //No passenger has been rejected, but all are included in the rejecion (not matched) pool
calculatePreferences(); // distances between taxis and passengers
/*
* Every rejected passenger turns to its next (1st, 2nd, 3rd,...) closest taxi
* Every taxi with more than one proposal keeps the closest passenger in the waitingList and
* rejects other proposing passengers
*/
ListIterator<Integer> itrRejected = this.rejectionPool.listIterator();
while(!this.rejectionPool.isEmpty())
{
if(!itrRejected.hasNext()) //end of list
itrRejected = this.rejectionPool.listIterator();
int newPassengerIndex = (Integer) itrRejected.next().intValue();
int kTaxiIndex = getKBestOption(this.rejectionCounter[newPassengerIndex], newPassengerIndex); //Get K-best based on number of rejections
itrRejected.remove(); //remove current passenger from rejected list
if(waitingList[kTaxiIndex]== null){ //taxi is vacant!
waitingList[kTaxiIndex] = newPassengerIndex; //match w/ closest taxi
}else{ //compare, keep the best and pool rejected, update rejection counter
int currentPassengerIndex = waitingList[kTaxiIndex].intValue();
Double d1 = distancePreferences[currentPassengerIndex][kTaxiIndex];
Double d2 = distancePreferences[newPassengerIndex][kTaxiIndex];
if(d1.compareTo(d2) > 0){ //new passenger is closer i.e. d1 > d2
addToPool(currentPassengerIndex, itrRejected); //add current passenger to pool and update rejection counter
waitingList[kTaxiIndex] = new Integer(newPassengerIndex); //set new passenger as new match
}else{ //current passenger is preferred
addToPool(newPassengerIndex, itrRejected);
}
}
}
Logger.getLogger("data").log(Level.INFO, "rejectedList = "+printPool(), "");
return waitingList;
}
private void initPoolandCounter() {
rejectionCounter = new Integer[this.proposorPassengers.size()];
for(int i = 0;i< rejectionCounter.length;i++)
{
rejectionCounter[i]=0;
this.rejectionPool.add(i);
}
}
//Works with indexes, look up on preference structure
private Double getDistance(Integer passengerIndex, Integer taxiIndex) {
return distancePreferences[passengerIndex.intValue()][taxiIndex.intValue()];
}
/**
*Fills the preferences structure with distances between taxis and passengers
*
*/
private void calculatePreferences() {
double distance = -1;
StringBuffer buff = new StringBuffer();
try {
for (int iPass = 0; iPass < this.proposorPassengers.size(); iPass++){
PassengerMovement passMov = (PassengerMovement) this.proposorPassengers.get(iPass);
GeoPointExt passGeo = new GeoPointExt(passMov.getLatitude(),passMov.getLongitude());
buff.append(iPass+":\t");
for (int iTaxi = 0; iTaxi < this.acceptorTaxis.size(); iTaxi++){
TaxiMovement taxiMov = (TaxiMovement) this.acceptorTaxis.get(iTaxi);
GeoPointExt taxiGeo = new GeoPointExt(taxiMov.getLatitude(), taxiMov.getLongitude());
distance = Haversine.getDistance(taxiGeo, passGeo, DistanceUnit.Kilometers);
this.distancePreferences[iPass][iTaxi] = new Double(distance);
//TODO: Inverted distances!!!
buff.append(distancePreferences[iPass][iTaxi].toString().substring(0, 5) +"\t");
//Logger.getLogger(TaxiScheduler.class.getName()).log(Level.SEVERE, "PREFS = ["+passMov.getPassengerMovementPK().getMobileNo()+"]["+taxiMov.getTaxiMovementPK().getPlateNo()+"]");
//Logger.getLogger(TaxiScheduler.class.getName()).log(Level.SEVERE, "PREFS = ["+iPass+"]["+iTaxi+"]("+this.distancePreferences[iPass][iTaxi].toString().substring(0, 4));
}
buff.append("\n");
}
}catch(NullPointerException ex)
{
Logger.getLogger(TaxiScheduler.class.getName()).log(Level.SEVERE, "distance = "+distance, ex);
}
Logger.getLogger(TaxiScheduler.class.getName()).log(Level.SEVERE, "TOTAL PREF = \n"+buff.toString());
}
/*
* Returns index of the taxi that is k-best option for that passenger
*
* @param k The k-best (closest) taxi to be retrieved, 0 being the closest
* @param passIndex The passenger index
* @return K-closest taxi index for this passenger
*/
private int getKBestOption(int k, int passIndex){
Double [] passPreferences = this.distancePreferences[passIndex]; //Preferences for the taxi in that index
List<Double> pPreferences = Arrays.asList(passPreferences);
ArrayList originalOrder = new ArrayList(pPreferences);
Collections.sort(pPreferences); //sort taxi distances
Double kDistance = (Double) pPreferences.get(k); //get k-smallest distance
int ind = originalOrder.indexOf(kDistance); //find index of this value in the original array, even if repeated still KBest
return ind;
}
private String printPool() {
StringBuffer buff = new StringBuffer();
int c = 0;
for(Integer x:this.rejectionPool)
{
buff.append(x+"["+rejectionCounter[x]+"] ");
c++;
}
return buff.toString();
}
/*
* Add this element to rejection pool and updates its rejection counter
*
* @param passengerToPool Passenger index to add to the pool
* @param itrRejected iterator used in the rejectionPool
*/
private void addToPool(int passengerToPool, ListIterator<Integer> itrRejected) {
//check whether this passenger is already in the pool
int rIndex = rejectionPool.indexOf(passengerToPool);
if(rIndex == -1){ //not in the pool
this.rejectionCounter[passengerToPool]+=1;
if(this.rejectionCounter[passengerToPool] < this.acceptorTaxis.size()) //if has not been rejected by all taxis
itrRejected.add(passengerToPool);
}else{ //was already pooled, leave it there and increase counter
this.rejectionCounter[rIndex]+=1;
}
}
}
:-) 여기에 게시 할 수있는 코드의 작은 조각을 당신은 더 많은 것을 제공해야 할 수도 있어야한다 세부 묘사; 코드는 따라하기가 조금 어렵지만 일어날 일이 무엇인지, 그리고 그 일과는 다르게 진행되고 있습니다. –
@Dave Newton 이것은 http://en.wikipedia.org/wiki/Gale-Shapley_algorithm 알고리즘의 구현입니다. 나는이 의사 코드를 사용하지 않았다. 문제에 대한 내 자신의 이해와이 경우의 특성 (즉, 하나의 선호 구조 만 필요함)을 기반으로 구현됩니다. 언급했듯이 각 구조의 내용을 추적 했으므로 모두 정상적으로 작동하는 것 같습니다. – cevel
@DaveNewton 무슨 일이 일어나고 : distancePreferences 다차원 배열을 인덱싱 할 때 인덱스가 괜찮더라도 다른 셀의 내용을 가져 오는 중입니다. 정말 이상한데, 같은 열 (다른 열)에있는 위치를 검색하는 열 색인 만 잘못되었습니다. – cevel