私の会社でメンタープログラムのメンティー/メンターマッチを作成するJMPスクリプトを作成しようとしています。メンティーとメンターの優先順位を説明する部分があり、ランクごとに各メンティーの優先メンターのマトリックスになります(1が最高、10が最低)。私が遭遇している問題は、特定のランクで同じメンターを持つ複数のメンティーがいる場合の対処方法です(例:メンティー1、メンティー4、メンティー7はすべて、ランク1にメンター2があります)。決定を手動で行うことは難しくありませんが、それらをスクリプト化する方法を理解できません。手動の決定は、テスト参加者の小さなグループでの最初のパイロットでは機能しますが、プログラムが拡張されたときのために、可能であれば何かをスクリプト化したいと思います。これは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
....
この手法の利点の1つは、各コメントの下にコードを記述すれば、そのコードの機能を適切に説明できることです。
@ih 私がしたことを正確に説明します:手動で実行してから、コード化してみてください。
これは、さらにテストが必要なスクリプトです。上のセクションでは、文字データを含むテーブルを使用したり、テストデータを生成したりできます。さらに下には、コストファン 、2つのバリエーション(平均、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は実際に減速し始めています...本当に機能させる必要があるときだけです。
先端をありがとう!以前に疑似コード化を試しましたが、これでプロセスを見直し、最も問題のある場所の解決策を見つけました。