회사에서 멘토링 프로그램을위한 멘티 / 멘토 경기를 만들기 위해 JMP 스크립트를 작성하려고합니다. 멘티 및 멘토 순위 환경 설정을 설명하는 부분이 각 멘티에 대해 선호하는 멘토 매트릭스를 순위별로 표시합니다 (1은 최고, 10은 최악). 내가 겪고있는 문제는 주어진 순위에 동일한 멘토가있는 여러 멘티가있는 경우이를 처리하는 방법입니다 (예 : 멘티 1, 멘티 4 및 멘티 7은 모두 멘토 2가 순위 1에 있음). 의사 결정은 수동으로 수행하기 어렵지 않지만 스크립트를 작성하는 방법을 알 수는 없습니다. 수동 결정은 소수의 테스트 참가자 그룹과 함께 초기 파일럿에 적용되지만 프로그램이 확장 될 때 가능한 경우 스크립트를 작성하고 싶습니다. JMP에서 가능합니까?
매트릭스 매칭 테이블의 구조는 첨부 된 표를 참조하십시오. 표에서 나는 M #을 사용하여 멘토를 지정하고, E #을 사용하여 멘티를 지정하고, R #을 사용하여 순위를 지정했습니다.
그것은 가능한 일처럼 들리지만 아마도 사용자가 쉽게 할 수 있다고 표시 한 모든 단계를 정의해야 할 것입니다. '의사 코드'또는 스크립트의 주석을 사용하여 멘토 및 멘티를 일치시키는 데 사용하는 방법을 작성하여 시작한 다음 각 프로세스에 대해 JSL 코드를 작성하기 전에 해당 프로세스를 몇 번 수행 할 수 있는지 확인하는 것이 좋습니다. 단계. 다음은 일부 (매우 불완전한) 의사 코드의 예입니다.
//Find the highest ranked requests by mentees
//for each one
//check if any other mentee request the same person
//if so see if any mentors requested the same mentee
//if so...
//if not....
//if no mentors requested the same mentee then randomly pick a match
....
이 기술의 한 가지 장점은 각 주석 아래에 코드를 작성하면 해당 코드의 기능에 대한 설명을 그대로 두는 것입니다.
@ih 내가 한 일을 정확하게 설명합니다. 수동으로 코드를 작성하십시오.
테스트가 더 필요한 스크립트가 있습니다. 맨 위 섹션에서는 테이블을 문자 데이터와 함께 사용하거나 일부 테스트 데이터를 생성 할 수 있습니다. 더 아래로, 비용 멘토를 잘못 선택하는 비용을 설명하는 두 가지 변형 (평균, rms)입니다. 표는 최종 과제로 채색됩니다. JSL이 스왑이 모든 경우에 가능한 최상의 답변을 찾기에 충분하지 않다고 확신합니다 (쌍이 아니라 3 개 이상의 행이 바뀌어야 할 수도 있습니다). 그러나 그것은 아주 가깝습니다.
멘티는 파란색, 멘토는 노란색
If( 1, // use original file?
dt = Open( "z:/match lists.jmp" );
// load the numeric mentee names
e = J( N Rows( dt ), 1, . );// matrix to hold numeric names
Parallel Assign( {charnames = dt[0, 1]}, e[r] = Num( Substr( charnames[r], 2 ) ) );
// load the numeric mentor names
m = J( N Rows( dt ), N Cols( dt ) - 1, . );// matrix to hold numeric names
Parallel Assign( {charnames = dt[0, 2 :: N Cols( dt )]}, m[r, c] = Num( Substr( charnames[r][c], 2 ) ) );
, // else make up some test data
n = 50;// N^2...1000 takes 2 minutes
m = J( n, n, . );
For( i = 1, i <= N Rows( m ), i += 1,
m[i, 0] = Random Shuffle( 1 :: N Rows( m ) )
);
e = (1 :: N Rows( m ))`;
dt = As Table( e || m );
);
// check:
If( !Min( e ) == 1 | !Min( m ) == 1 | !Max( e ) == N Rows( e ) | !Max( m ) == N Rows( e ),
Throw( "the E and M suffixes are not 1..nrows" )
);
// make an initial assignment of mentors to mentees
cost = J( N Rows( e ), 1, . );// 1..nMentors, index into this mentee's ranked list of mentors
used = J( N Rows( e ), 1, . );// for initial assignment, has this mentor been used?
For( menteeIndex = 1, menteeIndex <= N Rows( e ), menteeIndex += 1,
For( candidateIndex = 1, candidateIndex <= N Cols( m ), candidateIndex += 1,
candidate = m[menteeIndex, candidateIndex];
If( Is Missing( used[candidate] ), //
used[candidate] = 1;
cost[menteeIndex] = candidateIndex;
candidateIndex = 9e99;// terminate the loop AND indicate found
);
);
If( candidateIndex < 9e99,
Throw( "no candidate found for row " || Char( menteeIndex ) )
);
);
If( !All( used == 1 ),
Throw( "some mentors were not used" )
);// this might be acceptable, test carefully
// rms error cost function means first+third choices is worse than second+second choices
// ... you might not agree and might want a different cost function
//cost=[2,2]; // -> 2
//cost=[1,3]; // -> 2.236
// in particular, you might not like...
//cost=[1,10]; // -> 7.1
//cost=[4,9]; // -> 6.96
// maybe you want a simpler mean of the individual costs?
costfun = Function( {c}, Sqrt( Mean( c :*</img> c ) ) );
//costfun = Function( {c}, Mean( c ) );
// try doing some swaps to improve the costs
// this gets really close to a best answer but may not
// be perfect if a 3-swap is needed; also there may
// be two equal scores (esp with simple mean) that have
// different worst case assignments (1,3 vs 2,2 for example).
gotBetter = 1;
While( gotBetter,
gotBetter = 0;
Show( costfun( cost ) );
For( myMenteeIndex = 1, myMenteeIndex <= N Rows( e ), myMenteeIndex += 1,
myCandidateIndex = cost[myMenteeIndex];
If( myCandidateIndex > 1,
myCandidate = m[myMenteeIndex, myCandidateIndex];
oldcost = costfun( cost );
// look for a swap
For( hisMenteeIndex = 1, hisMenteeIndex <= N Rows( e ), hisMenteeIndex += 1,
If( myMenteeIndex != hisMenteeIndex,
hisCandidateIndex = cost[hisMenteeIndex];
hisCandidate = m[hisMenteeIndex, hisCandidateIndex];
hisSwap = Loc( m[hisMenteeIndex, 0] == myCandidate );
mySwap = Loc( m[myMenteeIndex, 0] == hisCandidate );
// trial:
cost[myMenteeIndex] = mySwap;
cost[hisMenteeIndex] = hisSwap;
newcost = costfun( cost );
If( newcost < oldcost,
gotBetter = 1;// another round might get even better
//show(costfun(cost));wait(0);
Break();// resets myCandidate
, // revert
cost[myMenteeIndex] = myCandidateIndex;
cost[hisMenteeIndex] = hisCandidateIndex;
//
);
)
);
);
);
);
//worstMentee = 1;
Column( dt, 1 ) << colorcells( "cyan" );
For( menteeIndex = 1, menteeIndex <= N Rows( e ), menteeIndex += 1,
Column( dt, cost[menteeIndex] + 1 ) << colorcells( "yellow", menteeIndex );
// If( cost[worstMentee] < cost[menteeIndex],
// worstMentee = menteeIndex
// );// well, one of the worst, could be ties
);
//worstMentor = m[worstMentee, cost[worstMentee]];
//For( mentorIndex = 1, mentorIndex <= N Cols( m ), mentorIndex += 1,
// col = Column( dt, mentorIndex + 1 );
// For( menteeIndex = 1, menteeIndex <= N Rows( e ), menteeIndex += 1,
// If( menteeIndex != worstMentee,
// If( col[menteeIndex] == worstMentor,
// col << colorcells( "lightred", menteeIndex )
// )
// )
// );
//); JSL에는 나쁜 N ^ 2 동작이 있습니다. 모든 행마다 모든 행을 연구합니다. 약 1000 명의 멘토 / 멘토 쌍이 실제로 느려지기 시작합니다. 실제로 작동해야 할 때.
팁 고마워! 나는 전에 psuedocoding을 시도했지만 다시 돌아가 프로세스를 다시 생각하게 만들었고 가장 문제가 많은 부분에 대한 해결책을 찾았습니다.