Exercise2

Gale-Shapley Algorithmを実装する. 詳細: https://github.com/OyamaZemi/exercises2016/tree/master/ex02

imports


In [1]:
using DataStructures
include("matching_tools.jl")


Out[1]:
_randperm2d! (generic function with 1 method)

Argsort

まず, 1次元のargsort関数を実装する


In [2]:
function argsort{T<:Int}(array::AbstractVector{T})
    #=1次元配列をArgument Sortする
    
    配列をSortした後, その要素が元あった場所のIndexを返す
    例: [1, 3, 4, 2, 0] -> [5, 1, 4, 2, 3]
    タイの順位には非対応
    =#
    
    array_with_index = Array{T}(length(array), 2)
    for i in 1:length(array)
        array_with_index[i, 1] = array[i]
        array_with_index[i, 2] = i
    end
    
    sorted_array_with_index = sortrows(array_with_index, by=x->x[1])
    return sorted_array_with_index[:, 2]
end

array = [1, 3, 4, 2, 0]
println(argsort(array))


[5,1,4,2,3]

次に, 2次元に対応させる


In [3]:
function argsort{T<:Int}(array::AbstractArray{T, 2})
    #=2次元配列をArgument Sortする
    
    それぞれの行毎にargsortする.
    例: [1 3 4 2 0;
           1 2 0 4 3]
    
     -> [5 1 4 2 3;
           3 1 2 5 4]
    =#
    
    row = size(array)[1]
    col = size(array)[2]
    argsorted = Array{T}(size(array))
    for i in 1:row
        out = argsort(squeeze(array[i, :], 1))
        for j in 1:col
            argsorted[i, j] = out[j]
        end
    end
    
    return argsorted
end

array = [1 3 4 2 0; 1 2 0 4 3]
println(argsort(array))


[5 1 4 2 3
 3 1 2 5 4]

1 to 1 Gale Shapley

を書く. ここでは man-optimal matchingを出力する.


In [4]:
type RowMajorMatrix{T} <: AbstractMatrix{T}
    data::AbstractMatrix{T}
end

Base.getindex(a::RowMajorMatrix, i::Int, j::Int) = a.data[j, i]

function Base.size(a::RowMajorMatrix)
    col_size = size(a.data)[1]
    row_size = size(a.data)[2]
    return (row_size, col_size)
end


Out[4]:
size (generic function with 65 methods)

Stackを使う


In [5]:
function gale_shapley_T{T<:Int64}(m_prefs::AbstractArray{T, 2}, f_prefs::AbstractArray{T, 2})
    m_prefs_T = RowMajorMatrix(m_prefs)
    f_prefs_T = RowMajorMatrix(f_prefs)
    return gale_shapley(m_prefs_T, f_prefs_T)
end

function gale_shapley{T<:Int64}(m_prefs::AbstractArray{T, 2}, f_prefs::AbstractArray{T, 2})

    # 第1次元(行)のサイズ = 男, 女の人数 を取得
    m_size = size(m_prefs, 1)
    f_size = size(f_prefs, 1)
    
    # 仮マッチング済相手を入れる(0をunmatch)
    m_matched = zeros(Int64, m_size)
    f_matched = zeros(Int64, f_size)
    
    # 未処理の男を入れておくスタック
    stack = Stack(Int)
    for i in m_size:-1:1
        push!(stack, i)
    end
    
    # 女の選好を[男1の順位, 男2の順位,...] -> [1位の男の番号, 2位の男の番号,...] に変える
    male_rankings = argsort(f_prefs)

    # それぞれの男が何番目の女まで告白したかを保存するリスト
    proposed = zeros(Int64, m_size)
    
    while length(stack) != 0
        male = pop!(stack)
        
        for i in proposed[male]+1:f_size
            proposed[male] += 1

            # 順位表が終わりまで来たら探索終了
            if m_prefs[male, i] == 0
                break
            end
            
            female = m_prefs[male, i]
            # 女性が誰ともマッチしていない場合, 女性にとって男性がacceptableならマッチ
            if f_matched[female] == 0 && male_rankings[female, male+1] < male_rankings[female, 1]
                m_matched[male] = female
                f_matched[female] = male
                break
            # 誰かとマッチしている場合, 男性が現在のパートナーよりもランクが高ければマッチ
            else
                current_partner = f_matched[female]
                if male_rankings[female, male+1] < male_rankings[female, current_partner+1]
                    m_matched[male] = female
                    f_matched[female] = male
                    m_matched[current_partner] = 0
                    push!(stack, current_partner)
                    break
                end
            end
        end
    end
    return m_matched, f_matched
end


Out[5]:
gale_shapley (generic function with 1 method)

In [6]:
m_prefs = [2 1 3 4 0; 1 3 2 4 0; 2 3 4 1 0]'
f_prefs = [2 1 3 0; 3 2 1 0; 1 3 2 0; 2 3 1 0]'
println(m_prefs)
println(f_prefs)
println(gale_shapley_T(m_prefs, f_prefs))


[2 1 2
 1 3 3
 3 2 4
 4 4 1
 0 0 0]
[2 3 1 2
 1 2 3 3
 3 1 2 1
 0 0 0 0]
([3,1,2],[2,3,1,0])

In [7]:
srand(613)
m_prefs2, f_prefs2 = random_prefs(4, 3, allow_unmatched=true)
m_prefs2 = m_prefs2
f_prefs2 = f_prefs2
println(m_prefs2)
println(f_prefs2)
println(gale_shapley_T(m_prefs2, f_prefs2))


[2 2 1 1
 3 0 2 0
 0 3 3 2
 1 1 0 3]
[3 4 4
 2 1 3
 0 2 2
 1 0 1
 4 3 0]
([2,0,1,0],[3,1,0])

Stackを使わない


In [8]:
function gale_shapley2_T{T<:Int64}(m_prefs::AbstractArray{T, 2}, f_prefs::AbstractArray{T, 2})
    m_prefs_T = RowMajorMatrix(m_prefs)
    f_prefs_T = RowMajorMatrix(f_prefs)
    return gale_shapley2(m_prefs_T, f_prefs_T)
end

function gale_shapley2{T<:Int64}(m_prefs::AbstractArray{T, 2}, f_prefs::AbstractArray{T, 2})

    # 第1次元(行)のサイズ = 男, 女の人数 を取得
    m_size = size(m_prefs, 1)
    f_size = size(f_prefs, 1)
    
    # 仮マッチング済相手を入れる(0をunmatch)
    m_matched = zeros(Int64, m_size)
    f_matched = zeros(Int64, f_size)
    
    # 未処理の男を入れておくスタック
    unmatched = ones(Bool, m_size)
    
    # 女の選好を[男1の順位, 男2の順位,...] -> [1位の男の番号, 2位の男の番号,...] に変える
    male_rankings = argsort(f_prefs)

    # それぞれの男が何番目の女まで告白したかを保存するリスト
    proposed = zeros(Int64, m_size)
    
    while sum(unmatched) != 0
        for male in 1:m_size
            if unmatched[male]
                for i in proposed[male]+1:f_size
                    proposed[male] += 1

                    # 順位表が終わりまで来たら探索終了
                    if m_prefs[male, i] == 0
                        unmatched[male] = false
                        break
                    end

                    female = m_prefs[male, i]
                    # 女性が誰ともマッチしていない場合, 女性にとって男性がacceptableならマッチ
                    if f_matched[female] == 0 && male_rankings[female, male+1] < male_rankings[female, 1]
                        m_matched[male] = female
                        f_matched[female] = male
                        unmatched[male] = false
                        break
                    # 誰かとマッチしている場合, 男性が現在のパートナーよりもランクが高ければマッチ
                    else
                        current_partner = f_matched[female]
                        if male_rankings[female, male+1] < male_rankings[female, current_partner+1]
                            m_matched[male] = female
                            f_matched[female] = male
                            m_matched[current_partner] = 0
                            unmatched[male] = false
                            unmatched[current_partner] = true
                            break
                        end
                    end
                end
            end
        end
    end
    return m_matched, f_matched
end


Out[8]:
gale_shapley2 (generic function with 1 method)

In [9]:
m_prefs = [2 1 3 4 0; 1 3 2 4 0; 2 3 4 1 0]'
f_prefs = [2 1 3 0; 3 2 1 0; 1 3 2 0; 2 3 1 0]'
println(m_prefs)
println(f_prefs)
println(gale_shapley2_T(m_prefs, f_prefs))


[2 1 2
 1 3 3
 3 2 4
 4 4 1
 0 0 0]
[2 3 1 2
 1 2 3 3
 3 1 2 1
 0 0 0 0]
([3,1,2],[2,3,1,0])

Stack使用版と未使用版, どちらが速いか


In [10]:
function make_preferences(loop::Int=1000, m_size::Int=1000, f_size::Int=1000, seed::Int64=617)
    srand(seed)
    m_prefs = Array{Int64}(loop, f_size+1, m_size)
    f_prefs = Array{Int64}(loop, m_size+1, f_size)
    for i in 1:loop
        m_pref, f_pref = random_prefs(m_size, f_size, allow_unmatched=true)
        m_prefs[i, :, :] = m_pref
        f_prefs[i, :, :] = f_pref
    end
    
    return m_prefs, f_prefs
end

function speedtest(func::Function, m_prefs, f_prefs, loop)
    m_size = size(m_prefs, 3)
    f_size = size(f_prefs, 3)
    for i in 1:loop
        m_pref = reshape(m_prefs[i, :, :], f_size+1, m_size)
        f_pref = reshape(f_prefs[i, :, :], m_size+1, f_size)
    end
end


Out[10]:
speedtest (generic function with 1 method)

In [12]:
m_size = 1000
f_size = 1000
loop = 100

@time m_prefs, f_prefs = make_preferences(loop, m_size, f_size) 
@time speedtest(gale_shapley_T, m_prefs, f_prefs, loop)
@time speedtest(gale_shapley2_T, m_prefs, f_prefs, loop)


  9.245303 seconds (603.51 k allocations: 3.009 GB, 4.18% gc time)
  3.576678 seconds (1.40 k allocations: 1.492 GB, 6.44% gc time)
  3.078178 seconds (1.40 k allocations: 1.492 GB, 6.75% gc time)

Stackの方が遅いかと思ったが, ほとんど誤差の範囲


In [15]:
srand(613)
m_prefs2, f_prefs2 = random_prefs(1000, 1000, allow_unmatched=true)

Profile.clear()
@profile gale_shapley_T(m_prefs2, f_prefs2)
Profile.print()


4    In[2]; anonymous; line: 15
1    ordering.jl; lt; line: 54
2901 task.jl; anonymous; line: 447
 2901 .../IJulia/src/IJulia.jl; eventloop; line: 142
  2901 ...rc/execute_request.jl; execute_request_0x535c5df2; line: 182
   2901 loading.jl; include_string; line: 266
    2900 profile.jl; anonymous; line: 16
     2900 In[5]; gale_shapley_T; line: 4
      2884 In[5]; gale_shapley; line: 24
       2    In[3]; argsort; line: 15
       2685 In[3]; argsort; line: 16
        3    In[2]; argsort; line: 11
        3    In[2]; argsort; line: 12
        2577 In[2]; argsort; line: 15
         37   sort.jl; sortrows; line: 503
          2  subarray.jl; _sub; line: 90
          28 subarray.jl; _sub; line: 91
           26 subarray.jl; _sub_unsafe; line: 125
          1  subarray.jl; _sub_unsafe; line: 125
         2536 sort.jl; sortrows; line: 504
          3    ...b/julia/sys.dylib; vcat; (unknown line)
          2527 sort.jl; sort!; line: 402
           16  sort.jl; sort!; line: 292
            16 sort.jl; sort!; line: 221
             15 ordering.jl; lt; line: 55
              10 In[2]; anonymous; line: 15
               4 subarray.jl; getindex; line: 543
           742 sort.jl; sort!; line: 293
            5   sort.jl; partition!; line: 272
             5 ordering.jl; lt; line: 55
              1 ...b/julia/sys.dylib; isless; (unknown line)
              2 In[2]; anonymous; line: 15
            390 sort.jl; partition!; line: 277
             2   ...b/julia/sys.dylib; !; (unknown line)
             5   ordering.jl; lt; line: 53
             8   ordering.jl; lt; line: 54
             354 ordering.jl; lt; line: 55
              2   .../julia/sys.dylib; !; (unknown line)
              1   .../julia/sys.dylib; &; (unknown line)
              1   .../julia/sys.dylib; isless; (unknown line)
              1   .../julia/sys.dylib; |; (unknown line)
              204 In[2]; anonymous; line: 15
               45 subarray.jl; getindex; line: 543
              1   subarray.jl; getindex; line: 543
            344 sort.jl; partition!; line: 278
             1   In[2]; anonymous; line: 15
             3   ordering.jl; lt; line: 53
             7   ordering.jl; lt; line: 54
             315 ordering.jl; lt; line: 55
              2   ...b/julia/sys.dylib; isless; (unknown line)
              2   ...b/julia/sys.dylib; |; (unknown line)
              181 In[2]; anonymous; line: 15
               31 subarray.jl; getindex; line: 543
            3   sort.jl; partition!; line: 280
           831 sort.jl; sort!; line: 298
            78  sort.jl; sort!; line: 292
             78 sort.jl; sort!; line: 221
              1  ordering.jl; lt; line: 53
              1  ordering.jl; lt; line: 54
              76 ordering.jl; lt; line: 55
               28 In[2]; anonymous; line: 15
                4 subarray.jl; getindex; line: 543
            261 sort.jl; sort!; line: 293
             9   sort.jl; partition!; line: 272
              9 ordering.jl; lt; line: 55
               7 In[2]; anonymous; line: 15
                3 subarray.jl; getindex; line: 543
             135 sort.jl; partition!; line: 277
              4   ordering.jl; lt; line: 53
              128 ordering.jl; lt; line: 55
               1  ...b/julia/sys.dylib; isless; (unknown line)
               76 In[2]; anonymous; line: 15
                14 subarray.jl; getindex; line: 543
             115 sort.jl; partition!; line: 278
              1  ...b/julia/sys.dylib; !; (unknown line)
              4  ordering.jl; lt; line: 53
              3  ordering.jl; lt; line: 54
              96 ordering.jl; lt; line: 55
               53 In[2]; anonymous; line: 15
                12 subarray.jl; getindex; line: 543
             2   sort.jl; partition!; line: 280
            251 sort.jl; sort!; line: 298
             85 sort.jl; sort!; line: 292
              85 sort.jl; sort!; line: 221
               3  ordering.jl; lt; line: 54
               82 ordering.jl; lt; line: 55
                1  .../julia/sys.dylib; !; (unknown line)
                1  .../julia/sys.dylib; isless; (unknown line)
                38 In[2]; anonymous; line: 15
                 6 subarray.jl; getindex; line: 543
             61 sort.jl; sort!; line: 293
              3  sort.jl; partition!; line: 272
               1 ordering.jl; lt; line: 53
               2 ordering.jl; lt; line: 55
                1 In[2]; anonymous; line: 15
              28 sort.jl; partition!; line: 277
               2  ordering.jl; lt; line: 54
               26 ordering.jl; lt; line: 55
                10 In[2]; anonymous; line: 15
                 3 subarray.jl; getindex; line: 543
              30 sort.jl; partition!; line: 278
               1  ...b/julia/sys.dylib; !; (unknown line)
               1  In[2]; anonymous; line: 15
               1  ordering.jl; lt; line: 53
               26 ordering.jl; lt; line: 55
                13 In[2]; anonymous; line: 15
                 1 subarray.jl; getindex; line: 543
             49 sort.jl; sort!; line: 298
              39 sort.jl; sort!; line: 292
               39 sort.jl; sort!; line: 221
                3  In[2]; anonymous; line: 15
                36 ordering.jl; lt; line: 55
                 21 In[2]; anonymous; line: 15
                  1 subarray.jl; getindex; line: 543
              5  sort.jl; sort!; line: 293
               1 sort.jl; partition!; line: 277
                1 ordering.jl; lt; line: 55
                 1 In[2]; anonymous; line: 15
                  1 subarray.jl; getindex; line: 543
               4 sort.jl; partition!; line: 278
                3 ordering.jl; lt; line: 55
                 2 In[2]; anonymous; line: 15
                  1 subarray.jl; getindex; line: 543
              3  sort.jl; sort!; line: 298
               3 sort.jl; sort!; line: 292
                3 sort.jl; sort!; line: 221
                 3 ordering.jl; lt; line: 55
                  1 In[2]; anonymous; line: 15
              2  sort.jl; sort!; line: 301
               2 sort.jl; sort!; line: 292
                2 sort.jl; sort!; line: 221
                 2 ordering.jl; lt; line: 55
             56 sort.jl; sort!; line: 301
              46 sort.jl; sort!; line: 292
               46 sort.jl; sort!; line: 221
                46 ordering.jl; lt; line: 55
                 23 In[2]; anonymous; line: 15
                  5 subarray.jl; getindex; line: 543
              5  sort.jl; sort!; line: 293
               1 sort.jl; partition!; line: 277
                1 ordering.jl; lt; line: 55
                 1 In[2]; anonymous; line: 15
               4 sort.jl; partition!; line: 278
                1 In[2]; anonymous; line: 15
                3 ordering.jl; lt; line: 55
                 2 In[2]; anonymous; line: 15
              2  sort.jl; sort!; line: 298
               2 sort.jl; sort!; line: 292
                2 sort.jl; sort!; line: 221
                 2 ordering.jl; lt; line: 55
                  1 In[2]; anonymous; line: 15
              3  sort.jl; sort!; line: 301
               3 sort.jl; sort!; line: 292
                3 sort.jl; sort!; line: 221
                 3 ordering.jl; lt; line: 55
                  2 In[2]; anonymous; line: 15
                   1 subarray.jl; getindex; line: 543
            241 sort.jl; sort!; line: 301
             93 sort.jl; sort!; line: 292
              90 sort.jl; sort!; line: 221
               2  ordering.jl; lt; line: 54
               88 ordering.jl; lt; line: 55
                1  .../julia/sys.dylib; isless; (unknown line)
                51 In[2]; anonymous; line: 15
                 11 subarray.jl; getindex; line: 543
              1  sort.jl; sort!; line: 222
              2  sort.jl; sort!; line: 228
             59 sort.jl; sort!; line: 293
              4  sort.jl; partition!; line: 272
               4 ordering.jl; lt; line: 55
                2 In[2]; anonymous; line: 15
              30 sort.jl; partition!; line: 277
               28 ordering.jl; lt; line: 55
                14 In[2]; anonymous; line: 15
                 2 subarray.jl; getindex; line: 543
              25 sort.jl; partition!; line: 278
               25 ordering.jl; lt; line: 55
                18 In[2]; anonymous; line: 15
                 7 subarray.jl; getindex; line: 543
             44 sort.jl; sort!; line: 298
              32 sort.jl; sort!; line: 292
               32 sort.jl; sort!; line: 221
                32 ordering.jl; lt; line: 55
                 15 In[2]; anonymous; line: 15
                  2 subarray.jl; getindex; line: 543
              7  sort.jl; sort!; line: 293
               2 sort.jl; partition!; line: 277
                2 ordering.jl; lt; line: 55
                 1 In[2]; anonymous; line: 15
                  1 subarray.jl; getindex; line: 543
               5 sort.jl; partition!; line: 278
                5 ordering.jl; lt; line: 55
                 4 In[2]; anonymous; line: 15
              4  sort.jl; sort!; line: 298
               3 sort.jl; sort!; line: 292
                3 sort.jl; sort!; line: 221
                 3 ordering.jl; lt; line: 55
                  2 In[2]; anonymous; line: 15
               1 sort.jl; sort!; line: 298
                1 sort.jl; sort!; line: 292
                 1 sort.jl; sort!; line: 221
                  1 ordering.jl; lt; line: 55
              1  sort.jl; sort!; line: 301
               1 sort.jl; sort!; line: 292
                1 sort.jl; sort!; line: 221
                 1 ordering.jl; lt; line: 55
                  1 In[2]; anonymous; line: 15
                   1 subarray.jl; getindex; line: 543
             45 sort.jl; sort!; line: 301
              32 sort.jl; sort!; line: 292
               30 sort.jl; sort!; line: 221
                2  ordering.jl; lt; line: 54
                28 ordering.jl; lt; line: 55
                 15 In[2]; anonymous; line: 15
                  3 subarray.jl; getindex; line: 543
               1  sort.jl; sort!; line: 222
               1  sort.jl; sort!; line: 228
              8  sort.jl; sort!; line: 293
               1 sort.jl; partition!; line: 272
                1 ordering.jl; lt; line: 55
                 1 In[2]; anonymous; line: 15
               4 sort.jl; partition!; line: 277
                4 ordering.jl; lt; line: 55
                 4 In[2]; anonymous; line: 15
                  1 subarray.jl; getindex; line: 543
               3 sort.jl; partition!; line: 278
                1 ordering.jl; lt; line: 53
                2 ordering.jl; lt; line: 55
              2  sort.jl; sort!; line: 298
               1 sort.jl; sort!; line: 292
                1 sort.jl; sort!; line: 221
                 1 ordering.jl; lt; line: 55
                  1 In[2]; anonymous; line: 15
               1 sort.jl; sort!; line: 298
                1 sort.jl; sort!; line: 292
                 1 sort.jl; sort!; line: 221
                  1 ordering.jl; lt; line: 55
                   1 In[2]; anonymous; line: 15
                    1 subarray.jl; getindex; line: 543
              3  sort.jl; sort!; line: 301
               3 sort.jl; sort!; line: 292
                3 sort.jl; sort!; line: 221
                 3 ordering.jl; lt; line: 55
                  3 In[2]; anonymous; line: 15
           938 sort.jl; sort!; line: 301
            94  sort.jl; sort!; line: 292
             93 sort.jl; sort!; line: 221
              2  ordering.jl; lt; line: 53
              1  ordering.jl; lt; line: 54
              90 ordering.jl; lt; line: 55
               45 In[2]; anonymous; line: 15
                8 subarray.jl; getindex; line: 543
             1  sort.jl; sort!; line: 222
            330 sort.jl; sort!; line: 293
             8   sort.jl; partition!; line: 272
              8 ordering.jl; lt; line: 55
               4 In[2]; anonymous; line: 15
                2 subarray.jl; getindex; line: 543
             162 sort.jl; partition!; line: 277
              1   ordering.jl; lt; line: 53
              1   ordering.jl; lt; line: 54
              145 ordering.jl; lt; line: 55
               1  .../julia/sys.dylib; !; (unknown line)
               1  .../julia/sys.dylib; isless; (unknown line)
               80 In[2]; anonymous; line: 15
                22 subarray.jl; getindex; line: 543
               1  subarray.jl; getindex; line: 543
             160 sort.jl; partition!; line: 278
              2   ordering.jl; lt; line: 53
              6   ordering.jl; lt; line: 54
              147 ordering.jl; lt; line: 55
               2  ...b/julia/sys.dylib; &; (unknown line)
               75 In[2]; anonymous; line: 15
                16 subarray.jl; getindex; line: 543
            268 sort.jl; sort!; line: 298
             96 sort.jl; sort!; line: 292
              96 sort.jl; sort!; line: 221
               1  In[2]; anonymous; line: 15
               1  ordering.jl; lt; line: 53
               94 ordering.jl; lt; line: 55
                2  .../julia/sys.dylib; isless; (unknown line)
                1  .../julia/sys.dylib; |; (unknown line)
                43 In[2]; anonymous; line: 15
                 10 subarray.jl; getindex; line: 543
                2  subarray.jl; getindex; line: 543
             85 sort.jl; sort!; line: 293
              9  sort.jl; partition!; line: 272
               9 ordering.jl; lt; line: 55
                6 In[2]; anonymous; line: 15
                 1 subarray.jl; getindex; line: 543
              40 sort.jl; partition!; line: 277
               2  ordering.jl; lt; line: 53
               2  ordering.jl; lt; line: 54
               32 ordering.jl; lt; line: 55
                1  .../julia/sys.dylib; |; (unknown line)
                17 In[2]; anonymous; line: 15
                 4 subarray.jl; getindex; line: 543
                1  subarray.jl; getindex; line: 543
              36 sort.jl; partition!; line: 278
               1  ...b/julia/sys.dylib; !; (unknown line)
               1  ordering.jl; lt; line: 54
               32 ordering.jl; lt; line: 55
                19 In[2]; anonymous; line: 15
                 4 subarray.jl; getindex; line: 543
             42 sort.jl; sort!; line: 298
              26 sort.jl; sort!; line: 292
               26 sort.jl; sort!; line: 221
                1  ordering.jl; lt; line: 53
                25 ordering.jl; lt; line: 55
                 1  .../julia/sys.dylib; isless; (unknown line)
                 11 In[2]; anonymous; line: 15
                  2 subarray.jl; getindex; line: 543
              9  sort.jl; sort!; line: 293
               2 sort.jl; partition!; line: 272
                1 ordering.jl; lt; line: 54
                1 ordering.jl; lt; line: 55
               4 sort.jl; partition!; line: 277
                3 ordering.jl; lt; line: 55
                 1 In[2]; anonymous; line: 15
                 1 subarray.jl; getindex; line: 543
               3 sort.jl; partition!; line: 278
                3 ordering.jl; lt; line: 55
                 2 In[2]; anonymous; line: 15
              3  sort.jl; sort!; line: 298
               3 sort.jl; sort!; line: 292
                3 sort.jl; sort!; line: 221
                 3 ordering.jl; lt; line: 55
                  3 In[2]; anonymous; line: 15
              4  sort.jl; sort!; line: 301
               4 sort.jl; sort!; line: 292
                4 sort.jl; sort!; line: 221
                 4 ordering.jl; lt; line: 55
                  3 In[2]; anonymous; line: 15
                   2 subarray.jl; getindex; line: 543
             45 sort.jl; sort!; line: 301
              31 sort.jl; sort!; line: 292
               1  sort.jl; sort!; line: 217
               30 sort.jl; sort!; line: 221
                30 ordering.jl; lt; line: 55
                 20 In[2]; anonymous; line: 15
                  5 subarray.jl; getindex; line: 543
              9  sort.jl; sort!; line: 293
               2 sort.jl; partition!; line: 272
                2 ordering.jl; lt; line: 55
                 2 In[2]; anonymous; line: 15
                  1 subarray.jl; getindex; line: 543
               4 sort.jl; partition!; line: 277
                2 ordering.jl; lt; line: 55
                 1 In[2]; anonymous; line: 15
               3 sort.jl; partition!; line: 278
                3 ordering.jl; lt; line: 55
                 2 In[2]; anonymous; line: 15
              1  sort.jl; sort!; line: 298
               1 sort.jl; sort!; line: 292
                1 sort.jl; sort!; line: 221
                 1 ordering.jl; lt; line: 55
                  1 In[2]; anonymous; line: 15
              4  sort.jl; sort!; line: 301
               3 sort.jl; sort!; line: 292
                3 sort.jl; sort!; line: 221
                 3 ordering.jl; lt; line: 55
                  1 In[2]; anonymous; line: 15
               1 sort.jl; sort!; line: 298
                1 sort.jl; sort!; line: 292
                 1 sort.jl; sort!; line: 221
                  1 ordering.jl; lt; line: 55
            246 sort.jl; sort!; line: 301
             78 sort.jl; sort!; line: 292
              77 sort.jl; sort!; line: 221
               1  ordering.jl; lt; line: 53
               3  ordering.jl; lt; line: 54
               72 ordering.jl; lt; line: 55
                42 In[2]; anonymous; line: 15
                 14 subarray.jl; getindex; line: 543
              1  sort.jl; sort!; line: 228
             72 sort.jl; sort!; line: 293
              3  sort.jl; partition!; line: 272
               3 ordering.jl; lt; line: 55
                1 In[2]; anonymous; line: 15
                 1 subarray.jl; getindex; line: 543
              31 sort.jl; partition!; line: 277
               29 ordering.jl; lt; line: 55
                1  .../julia/sys.dylib; isless; (unknown line)
                15 In[2]; anonymous; line: 15
                 1 subarray.jl; getindex; line: 543
              38 sort.jl; partition!; line: 278
               1  ...b/julia/sys.dylib; !; (unknown line)
               1  ordering.jl; lt; line: 53
               35 ordering.jl; lt; line: 55
                19 In[2]; anonymous; line: 15
                 4 subarray.jl; getindex; line: 543
             42 sort.jl; sort!; line: 298
              28 sort.jl; sort!; line: 292
               28 sort.jl; sort!; line: 221
                1  ordering.jl; lt; line: 54
                27 ordering.jl; lt; line: 55
                 12 In[2]; anonymous; line: 15
                  3 subarray.jl; getindex; line: 543
              8  sort.jl; sort!; line: 293
               2 sort.jl; partition!; line: 272
                2 ordering.jl; lt; line: 55
               3 sort.jl; partition!; line: 277
                3 ordering.jl; lt; line: 55
                 2 In[2]; anonymous; line: 15
               3 sort.jl; partition!; line: 278
                3 ordering.jl; lt; line: 55
                 1 In[2]; anonymous; line: 15
              5  sort.jl; sort!; line: 298
               4 sort.jl; sort!; line: 292
                4 sort.jl; sort!; line: 221
                 4 ordering.jl; lt; line: 55
                  4 In[2]; anonymous; line: 15
                   2 subarray.jl; getindex; line: 543
               1 sort.jl; sort!; line: 293
                1 sort.jl; partition!; line: 277
                 1 ordering.jl; lt; line: 55
                  1 In[2]; anonymous; line: 15
              1  sort.jl; sort!; line: 301
               1 sort.jl; sort!; line: 292
                1 sort.jl; sort!; line: 221
                 1 ordering.jl; lt; line: 55
             54 sort.jl; sort!; line: 301
              39 sort.jl; sort!; line: 292
               39 sort.jl; sort!; line: 221
                39 ordering.jl; lt; line: 55
                 24 In[2]; anonymous; line: 15
                  10 subarray.jl; getindex; line: 543
              5  sort.jl; sort!; line: 293
               3 sort.jl; partition!; line: 277
                2 ordering.jl; lt; line: 55
               2 sort.jl; partition!; line: 278
                2 ordering.jl; lt; line: 55
                 1 In[2]; anonymous; line: 15
              5  sort.jl; sort!; line: 298
               5 sort.jl; sort!; line: 292
                5 sort.jl; sort!; line: 221
                 4 ordering.jl; lt; line: 55
                  4 In[2]; anonymous; line: 15
              5  sort.jl; sort!; line: 301
               5 sort.jl; sort!; line: 292
                5 sort.jl; sort!; line: 221
                 5 ordering.jl; lt; line: 55
                  4 In[2]; anonymous; line: 15
                   1 subarray.jl; getindex; line: 543
          1    tuple.jl; indexed_next; line: 21
         3    sort.jl; sortrows; line: 505
          1 multidimensional.jl; _unsafe_getindex; line: 193
          1 multidimensional.jl; _unsafe_getindex; line: 195
        9    In[2]; argsort; line: 16
         9 multidimensional.jl; _unsafe_getindex; line: 193
        3    abstractarraymath.jl; squeeze; line: 38
         1 abstractarraymath.jl; squeeze; line: 31
         2 abstractarraymath.jl; squeeze; line: 32
        3    multidimensional.jl; _getindex; line: 185
         1 abstractarray.jl; checkbounds; line: 159
        87   multidimensional.jl; _getindex; line: 186
         1  multidimensional.jl; _unsafe_getindex; line: 193
          1 abstractarray.jl; similar; line: 203
         3  multidimensional.jl; _unsafe_getindex; line: 194
         83 multidimensional.jl; _unsafe_getindex; line: 195
          1  cartesian.jl; _unsafe_getindex!; line: 31
          1  cartesian.jl; _unsafe_getindex!; line: 32
          1  cartesian.jl; _unsafe_getindex!; line: 34
          33 multidimensional.jl; _unsafe_getindex!; line: 259
           12 array.jl; getindex; line: 283
          43 multidimensional.jl; _unsafe_getindex!; line: 260
       73   In[3]; argsort; line: 17
       122  In[3]; argsort; line: 18
        1  ...lib/julia/sys.dylib; !; (unknown line)
        1  array.jl; getindex; line: 282
        18 array.jl; setindex!; line: 314
      3    In[5]; gale_shapley; line: 32
      3    In[5]; gale_shapley; line: 33
      4    In[5]; gale_shapley; line: 36
       1 In[4]; getindex; line: 5
        1 array.jl; getindex; line: 283
      2    In[5]; gale_shapley; line: 42
       2 array.jl; getindex; line: 283
      1    In[5]; gale_shapley; line: 48
      2    In[5]; gale_shapley; line: 49
       1 array.jl; getindex; line: 283
      1    In[5]; gale_shapley; line: 54

In [ ]: