argmax
는 최대값의 위치를, argmin
는 최소값의 위치를 리턴하는 함수다. 이와 유사하게, 부분순서배열 A
에서 n
번째로 큰 원소의 인덱스를 리턴하는 argnth(n, A)
를 작성하라.
julia> X = [0, -1, 7, 3, 9, 2, 11];
julia> argnth(2, X)
5
julia> argnth(3, X)
3
argnth(n, A) = sortperm(A, rev = true)[n]
randw(item, weight)
를 작성하라.
julia> randw(['a', 'b', 'c'], [1,2])
ERROR: AssertionError: length mismatch
julia> randw(['a', 'b', 'c'], [0,0,0])
ERROR: AssertionError: all weights are zero
julia> randw(['a', 'b', 'c'], [1,2,-1])
ERROR: AssertionError: there is a negative weight
julia> randw(['a', 'b', 'c'], [1,2,3])
'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
julia> abc = [randw(['a', 'b', 'c'], [1,2,3]) for _ in 1:6000];
julia> count.([abc .== 'a', abc .== 'b', abc .== 'c'])
3-element Vector{Int64}:
1029
1980
2991
선수문제: 002. 가중치 샘플링
randw
함수를 사용해서 가중치 샘플링을 n
번 반복하되, 비복원 샘플링(sample without replacement)을 할 수 있는 함수 randw(item, weight, n; replace = true)
를 재정의하라. replace
키워드의 디폴트는 true
로 주어지며, false
일 때 비복원 샘플링이 수행된다.
julia> randw(1:10, 1:10, 5)
5-element Vector{Any}:
9
7
6
6
6
julia> randw(1:10, 1:10, 5, replace = false)
5-element Vector{Int64}:
6
4
3
10
8
다음은 샘플 벡터가 제약조건을 만족시키지 못하면 폐기하고 원하는 결과가 나올때까지 반복하는 방법이다.
function randw(item, weight, n; replace = true)
@assert n ≤ length(item) "n = $n is larger than the length of item = $(length(item))"
while true
sample = [randw(item, weight) for _ in 1:n]
if allunique(sample) || replace
return sample
end
end
end
다음은 샘플된 아이템을 하나씩 금지 시켜가며 가중치를 업데이트하는 방법이다. 이 방법의 결과로 얻는 샘플 벡터의 원소들이 적법한 순서를 가지는지 논하라.
function randw(item, weight, n; replace = true)
@assert n ≤ length(item) "n = $n is larger than the length of item = $(length(item))"
N = length(item)
if replace
sample = [randw(item, weight) for _ in 1:n]
else
weight = deepcopy(collect(weight))
sample = []
for _ in 1:n
k = randw(1:N, weight)
weight[k] = 0
push!(sample, item[k])
end
end
return sample # OK with this order?
end
길버트 모델을 통해 에르되시-레니 그래프와 유사한 결과를 얻을 수 있다. 노드의 수 gilbert(n, p)
를 작성하라.
노드의 수 euclidean(n, δ)
를 작성하라.
선수문제: 003. 비복원 샘플링
최종 노드의 수 barabasi_albert(N, m = 1)
를 작성하라.
julia> ba = barabasi_albert(1000, 3)
1000-element Vector{Vector{Int64}}:
[2, 3, 4, 5, 6, 7, 9, 11, 15, 18 … 826, 860, 864, 872, 908, 913, 929, 942, 960, 961]
[1, 3, 4, 5, 9, 17, 18, 38, 46, 55 … 704, 710, 720, 829, 837, 846, 922, 962, 971, 999]
[1, 2, 4, 5, 6, 7, 8, 12, 14, 22 … 389, 402, 503, 551, 560, 565, 617, 735, 833, 897]
[2, 3, 1, 8, 10, 11, 14, 19, 20, 22 … 726, 779, 797, 820, 866, 894, 900, 926, 937, 984]
[1, 3, 2, 6, 7, 8, 9, 10, 13, 15 … 736, 762, 773, 848, 857, 922, 923, 926, 928, 979]
⋮
[53, 739, 342]
[83, 142, 87]
[447, 9, 19]
[495, 2, 236]
[530, 190, 359]
julia> degree = length.(ba)
1000-element Vector{Int64}:
96
42
36
63
72
⋮
3
3
3
3
3
julia> histogram(degree, xscale = :log10, yscale = :log10, xticks = 10.0 .^(-0:0.5:2), xlims = extrema(degree))
function randw(item, weight)
Σ = sum(weight)
if !isone(Σ)
weight = weight ./ Σ
end
return item[findfirst(rand() .≤ cumsum(weight))]
end
function randw(item, weight, n; replace = true)
while true
sample = [randw(item, weight) for _ in 1:n]
if (length(unique(sample)) == n) || replace
return sample
end
end
end
function barabasi_albert(N, m = 1)
G = [setdiff(1:m, k) for k in 1:m]
for new in (m+1):N
idxs = randw(1:(new-1), length.(G), m, replace = false)
push!(G, idxs)
push!.(G[idxs], new)
end
return G
end
ba = barabasi_albert(1000, 3)
degree = length.(ba)
using Plots
histogram(degree)
histogram(degree, xscale = :log10, yscale = :log10, xticks = 10.0 .^(-0:0.5:2), xlims = extrema(degree))
정사각행렬
위의 공식을 라플라스 전개Laplace expansion라 한다. 정사각행렬을 입력받아 라플라스 전개를 리턴하는 함수 laplace(A)
를 작성하라.
julia> B = [2 3; 4 6]
2×2 Matrix{Int64}:
2 3
4 6
julia> laplace(B)
0
julia> C = [7 1; 9 3]
2×2 Matrix{Int64}:
7 1
9 3
julia> laplace(C)
12
julia> M = rand(3,3)
3×3 Matrix{Float64}:
0.478437 0.779194 0.334746
0.342975 0.867767 0.0211038
0.733843 0.97752 0.331435
julia> laplace(M)
-0.04971335247679029
julia> using LinearAlgebra
julia> det(M)
-0.049713352476790304
julia> abs(det(M) - laplace(M))
1.3877787807814457e-17
주어진 행렬
다시 말해, 한켈 행렬이란 다음과 같이 반대각선의 성분이 모두 같은 행렬이다.
벡터 hankelizer(vec, m, n)
을 작성하라.
julia> elements = [8,2,0,6,5,1,5,4,0,1];
julia> hankelizer(elements, 3, 8)
3×8 Matrix{Int64}:
8 2 0 6 5 1 5 4
2 0 6 5 1 5 4 0
0 6 5 1 5 4 0 1
julia> hankelizer(elements, 2, 9)
2×9 Matrix{Int64}:
8 2 0 6 5 1 5 4 0
2 0 6 5 1 5 4 0 1
주어진 행렬 gauss(M)
을 작성하라.
행렬
두 직사각행렬
가 성립하고, 이를 축소 특이값 분해reduced singular value decomposition이라 한다. mySVD(A)
를 작성하라.
LinearAlgebra.jl
라이브러리의 rank
, eigen
, diagm
, svd
와 같은 함수를 사용해도 좋다.julia> A = [1 2 3
4 5 6
7 8 7
4 2 1];
julia> myU, myΣ, myVt = mySVD(A);
julia> myU*myΣ*myVt'
4×3 Matrix{Float64}:
1.0 2.0 3.0
4.0 5.0 6.0
7.0 8.0 7.0
4.0 2.0 1.0
julia> B = [1 2 3 4 5
2 4 6 8 10
7 8 7 6 5]
3×5 Matrix{Int64}:
1 2 3 4 5
2 4 6 8 10
7 8 7 6 5
julia> myU, myΣ, myVt = mySVD(B);
julia> myU*myΣ*myVt'
3×5 Matrix{Float64}:
1.0 2.0 3.0 4.0 5.0
2.0 4.0 6.0 8.0 10.0
7.0 8.0 7.0 6.0 5.0
SVD가 원래의 폼으로 되돌아 오면 분해 자체는 성공한 것이다. 표준 라이브러리인 LinearAlgebra.jl
과 비교하면 다음과 같다. 차원에는 차이가 있으나 근본적인 수치들, 특히 고유값의 경우 정확히 같음을 확인하라.
julia> myU
3×2 Matrix{Float64}:
0.295963 -0.33527
0.591925 -0.670541
-0.749687 -0.661792
julia> U
3×3 Matrix{Float64}:
-0.33527 -0.295963 -0.894427
-0.670541 -0.591925 0.447214
-0.661792 0.749687 1.66533e-16
julia> myΣ
2×2 Matrix{Float64}:
6.27906 0.0
0.0 21.4143
julia> Σ
3-element Vector{Float64}:
21.414326423487807
6.2790623367117195
0.0
julia> myVt
5×2 Matrix{Float64}:
-0.600089 -0.294611
-0.48381 -0.403797
-0.128741 -0.451175
0.226328 -0.498552
0.581397 -0.54593
julia> Vt
5×3 adjoint(::Matrix{Float64}) with eltype Float64:
-0.294611 0.600089 -0.594015
-0.403797 0.48381 0.769135
-0.451175 0.128741 -0.213693
-0.498552 -0.226328 -0.0979743
-0.54593 -0.581397 0.0177441
using LinearAlgebra
function mySVD(A::AbstractMatrix)
r = rank(A)
λ, V = eigen(A'A) # we can assume eigenpairs are given
λ = λ[ (end-r+1):end]
V = V[:,(end-r+1):end]
Σ = diagm(sqrt.(λ))
U = (A * V) / Σ
return U, Σ, V
end
A = [1 2 3
4 5 6
7 8 7
4 2 1];
myU, myΣ, myVt = mySVD(A);
myU*myΣ*myVt'
B = [1 2 3 4 5
2 4 6 8 10
7 8 7 6 5]
myU, myΣ, myVt = mySVD(B);
myU*myΣ*myVt'
U, Σ, Vt = svd(B);
U*diagm(Σ)*Vt'
myU
U
myΣ
Σ
myVt
Vt
주어진 시퀀스 arr
argext(arr)
를 작성하라.
주어진 함수 bisect(f,a,b;atol=eps())
를 작성하라. atol
은 절대허용오차(absolute tolerance)를 의미한다.
julia> bisect(x -> x^3 + 8, -7, 7)
-1.9999999850988388
julia> bisect(x -> sin(x), 3, 4)
3.141592025756836
위와 같이 로지스틱 패밀리logistic family를 통해 정의된 다이내믹 시스템이 주어져 있다고 하자.
logistic(r, x)
을 작성하라.iter(f, p, x0, n)
을 작성하라.julia> logistic(4, 0.5)
1.0
julia> traj = iter(logistic, 3, 0.5, 100);
julia> using Plots
julia> timeevolution = plot(traj, color = :black, legend = :none)