Compare commits

..
6 Commits
4 changed files with 236 additions and 185 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 538 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 570 KiB

+81 -73
View File
@@ -27,7 +27,8 @@
#table_of_contents() #table_of_contents()
#domain_frame( #domain_frame(
bg_img_path: "assets/research/bg.png", bg_img_path: "assets/research/bg.jpg",
cover_color: rgb("0F0F0F").transparentize(40%),
font_color: color.oklch(95%, 0.01, 250deg), font_color: color.oklch(95%, 0.01, 250deg),
chrome_color: color.oklch(80%, 0.01, 250deg), chrome_color: color.oklch(80%, 0.01, 250deg),
title: [본질을 향한 여정], title: [본질을 향한 여정],
@@ -54,15 +55,7 @@
#activity_cover( #activity_cover(
name: [Dijkstra Runtime Analysis], name: [Dijkstra Runtime Analysis],
hook: [ hook: [Big-O가 버린 세부 실행비용을 다시 세우고, 실행해야만 있던 감소 횟수를 그래프 특성만으로 구해, 이진 Dijkstra의 런타임 변동 96.9%를 실행 전에 설명한 모델.],
`Big-O` 시간 복잡도의 한계를 넘어, \
알고리즘의 세부 작업 실행 횟수와 단위 실행 시간을 고려한 \
가장 정확한 `Dijkstra` 알고리즘 런타임 예측 모델
],
)[]
#activity_intro(
title: "Big-O가 답하지 못하는 것",
)[ )[
네비게이션, 자율주행, 우주항공 많은 현대 기술들에게 최적 경로를 탐색하는 것은 중요한 일이며, 네비게이션, 자율주행, 우주항공 많은 현대 기술들에게 최적 경로를 탐색하는 것은 중요한 일이며,
Dijkstra 알고리즘은 최적 경로를 도출하는 가장 효율적인 알고리즘이다. \ Dijkstra 알고리즘은 최적 경로를 도출하는 가장 효율적인 알고리즘이다. \
@@ -73,11 +66,26 @@
IB 소논문 활동에서 시작해 계속 발전시켜 현재는 외부 학술지에도 기제된 연구로, 목표는 그래프의 노드 수, 간선 수, 가중치의 분산, 기기 성능만으로 이집 힙이 적용된 Dijkstra의 실행시간을 예측하는 것이다. IB 소논문 활동에서 시작해 계속 발전시켜 현재는 외부 학술지에도 기제된 연구로, 목표는 그래프의 노드 수, 간선 수, 가중치의 분산, 기기 성능만으로 이집 힙이 적용된 Dijkstra의 실행시간을 예측하는 것이다.
] ]
// #activity_intro(
// title: "Big-O가 답하지 못하는 것",
// )[
// 네비게이션, 자율주행, 우주항공 등 많은 현대 기술들에게 최적 경로를 탐색하는 것은 중요한 일이며,
// Dijkstra 알고리즘은 최적 경로를 도출하는 가장 효율적인 알고리즘이다. \
// 그러나 자율주행과 같이 실시간성과 속도가 중요한 문제가 많아지자, 휴리스틱 기반의 A\* 알고리즘들이 적용되었다. 이들은 속도는 빠르지만, 항상 최적해를 보장하지는 않한다는 트레이드오프가 존재한다. \
// 상황에 따라 적절한 알고리즘을 선택하면 될 듯 하지만, Big-O 시간복잡도는 노드·간선 수 등 입력 크기에 따른 점근적 증가율만 나타낼 뿐, 상수항이나 그래프의 특성, 기기 성능 같은 요인은 반영하지 않기 때문에 Dijkstra의 실제 실행시간이 충분한지 알기 어렵다. \
// 그래서 *"이 트레이드오프를 감이 아닌 숫자로 계산해서 상황에 따른 정확한 알고리즘을 선택할 수는 없을까?"*라는 질문에서 출발하여 입력 그래프와 기기 성능만으로 Dijkstra의 실제 실행시간을 예측하는 모델을 연구했다.
// IB 소논문 활동에서 시작해 계속 발전시켜 현재는 외부 학술지에도 기제된 연구로, 목표는 그래프의 노드 수, 간선 수, 가중치의 분산, 기기 성능만으로 이집 힙이 적용된 Dijkstra의 실행시간을 예측하는 것이다.
// ]
#activity_table()
#let RS = math.italic("RS") #let RS = math.italic("RS")
#let RSR = math.italic("RSR") #let RSR = math.italic("RSR")
#activity_process( #activity_process(
title: "통제된 환경", title: [*통제된 환경*],
hook: [통제된 환경에서 벗어나다.],
)[ )[
#problem()[ #problem()[
실행 시간 측정의 신뢰도와 타당도를 높이기 위해서는 일정한 환경을 유지하는 것이 중요하다. 실행 시간 측정의 신뢰도와 타당도를 높이기 위해서는 일정한 환경을 유지하는 것이 중요하다.
@@ -219,7 +227,7 @@
그래프의 특성만으로 Dijkstra 실행 없이 $RS$ 예측하는 방법을 찾는다. 그래프의 특성만으로 Dijkstra 실행 없이 $RS$ 예측하는 방법을 찾는다.
] ]
#stack( #steps(
( (
[$bold(RS)$ 재정의], [$bold(RS)$ 재정의],
[ [
@@ -444,80 +452,80 @@
] ]
] ]
#activity_result(title: "예측할 수 있게 된 것")[ // #activity_result(title: "예측할 수 있게 된 것")[
#block_equation( // #block_equation(
title: [키 감소 횟수], // title: [키 감소 횟수],
description: [$V$ : 노드 수, $E$ : 간선 수, $sigma$ : 가중치 표준편차], // description: [$V$ : 노드 수, $E$ : 간선 수, $sigma$ : 가중치 표준편차],
)[ // )[
$ // $
RSR(macron(k), sigma) & = macron(k)^0.0612 (0.928 log sigma - 0.711), quad // RSR(macron(k), sigma) & = macron(k)^0.0612 (0.928 log sigma - 0.711), quad
macron(k)(V, E) & = E \/ V \ // macron(k)(V, E) & = E \/ V \
RS(V, E, sigma) & = E dot RSR(macron(k)(V, E), sigma) // RS(V, E, sigma) & = E dot RSR(macron(k)(V, E), sigma)
$ // $
] // ]
실행해야만 알 수 있던 $RS$를 세 변수만으로 계산할 수 있게 되었다. // 실행해야만 알 수 있던 $RS$를 세 변수만으로 계산할 수 있게 되었다.
#block_equation( // #block_equation(
title: [단위 실행시간], // title: [단위 실행시간],
description: [단위 : 초], // description: [단위 : 초],
)[ // )[
$ // $
"UC"_1 & = 2.15 times 10^(-7) \ // "UC"_1 & = 2.15 times 10^(-7) \
k_3(V) & = 1.59 times 10^(-7) e^(-5.67 times 10^(-5) V) + 4.37 times 10^(-8) \ // k_3(V) & = 1.59 times 10^(-7) e^(-5.67 times 10^(-5) V) + 4.37 times 10^(-8) \
"UC"_2(V) & = 1.06 times 10^(-6) log_2 V - 1.09 times 10^(-5) // "UC"_2(V) & = 1.06 times 10^(-6) log_2 V - 1.09 times 10^(-5)
$ // $
] // ]
세 값은 모두 $V$의 함수이거나 상수가 되어 식에 남아 있던 미지수가 전부 사라진다. // 세 값은 모두 $V$의 함수이거나 상수가 되어 식에 남아 있던 미지수가 전부 사라진다.
#block_equation( // #block_equation(
title: [최종 모델], // title: [최종 모델],
description: [입력 : $V$, $E$, $sigma$], // description: [입력 : $V$, $E$, $sigma$],
)[ // )[
$ // $
"Runtime"(V, E, sigma) = V dot "UC"_1 + E dot k_3(V) + RS(V, E, sigma) dot "UC"_2(V) // "Runtime"(V, E, sigma) = V dot "UC"_1 + E dot k_3(V) + RS(V, E, sigma) dot "UC"_2(V)
$ // $
] // ]
최종 식의 세 변수 모두 실행 전에 그래프에서 직접 추출할 수 있는 값이기에, \ // 최종 식의 세 변수 모두 실행 전에 그래프에서 직접 추출할 수 있는 값이기에, \
*Dijkstra를 번도 실행하지 않고 실행시간을 예측할 있다.* // *Dijkstra를 한 번도 실행하지 않고 실행시간을 예측할 수 있다.*
] // ]
#activity_result(title: "남은 오차")[ // #activity_result(title: "남은 오차")[
#figure( // #figure(
image("assets/research/dijkstra/comparison_plot.png"), // image("assets/research/dijkstra/comparison_plot.png"),
caption: [실제 경로 데이터에 대한 실행시간 예측과 $RS$ 예측], // caption: [실제 경로 데이터에 대한 실행시간 예측과 $RS$ 예측],
) // )
#figure( // #figure(
image("assets/research/dijkstra/predicted_vs_real.png", width: 60%), // image("assets/research/dijkstra/predicted_vs_real.png", width: 60%),
caption: [생성 그래프에 대한 예측값과 실측값], // caption: [생성 그래프에 대한 예측값과 실측값],
) // )
내삽에 대해 실행 시간 예측에 대해서 $96.9%$를 설명에 성공했다. \ // 내삽에 대해 실행 시간 예측에 대해서 $96.9%$를 설명에 성공했다. \
게다가 실제 경로 데이터(외삽)에서도 $RS$예측에 대해 일관된 정확도를 보였다. \ // 게다가 실제 경로 데이터(외삽)에서도 $RS$예측에 대해 일관된 정확도를 보였다. \
그러나 실전 상황에서 그래프가 커질수록 실행시간 예측은 과대평가하는 경항이 보였다.\ // 그러나 실전 상황에서 그래프가 커질수록 실행시간 예측은 과대평가하는 경항이 보였다.\
이 결과들에서 내 연구의 의의와 한계가 뚜렷하게 드러난다. \ // 이 결과들에서 내 연구의 의의와 한계가 뚜렷하게 드러난다. \
$RS$는 그래프의 구조만으로 결정되므로, 그래프의 근본적인 특성까지 쪼개었더니 정확하게 설명이 가능해졌으나, 실행시간은 파이썬 아래의 캐싱이나 하드웨어적 특성까지 쪼개지 못해 예측과 실측값 차이가 벌어졌다. // $RS$는 그래프의 구조만으로 결정되므로, 그래프의 근본적인 특성까지 쪼개었더니 정확하게 설명이 가능해졌으나, 실행시간은 파이썬 아래의 캐싱이나 하드웨어적 특성까지 쪼개지 못해 예측과 실측값 차이가 벌어졌다.
#table( // #table(
columns: (auto, 1fr), // columns: (auto, 1fr),
table.header([*문제 상황*], [*극복 방법*]), // table.header([*문제 상황*], [*극복 방법*]),
[학습 데이터의 부재], [분포를 분석해 864,000개를 직접 생성], // [학습 데이터의 부재], [분포를 분석해 864,000개를 직접 생성],
[실행해야 있는 ], [$E times RSR$ 쪼개 미지수를 하나로 축소], // [실행해야 알 수 있는 값], [$E times RSR$로 쪼개 미지수를 하나로 축소],
[다중공선성], [$V$ 개별 회귀 기여도 기준으로 정밀도 배분], // [다중공선성], [$V$별 개별 회귀 후 기여도 기준으로 정밀도 배분],
) // )
모든 문제 상황에서는 직면한 문제를 작은 단위들로 쪼개고, 작은 문제들의 해결책들을 종합하여 전체 문제를 해결해나갔다. // 모든 문제 상황에서는 직면한 큰 문제를 작은 단위들로 쪼개고, 작은 문제들의 해결책들을 종합하여 전체 문제를 해결해나갔다.
실행시간 측정을 위한 통제된 환경은 직접 구축한 홈서버의 가상화 환경(PVE)를 통해 구현했다. // 실행시간 측정을 위한 통제된 환경은 직접 구축한 홈서버의 가상화 환경(PVE)를 통해 구현했다.
이제 남은 오차는 파이썬이라는 언어 아래의 저차원에 위치해 있다. \ // 이제 남은 오차는 파이썬이라는 언어 아래의 저차원에 위치해 있다. \
카이스트에서 언어와 하드웨어 수준의 저차원 요소를 배워 모델의 정확도를 끌어올리고, 완성한 모델을 실제 임베디드 시스템에서 알고리즘 선택의 지표로 적용하려 한다. // 카이스트에서 언어와 하드웨어 수준의 저차원 요소를 배워 이 모델의 정확도를 끌어올리고, 완성한 모델을 실제 임베디드 시스템에서 알고리즘 선택의 지표로 적용하려 한다.
#context ref_evidence() // #context ref_evidence()
] // ]
#add_evidence( #add_evidence(
activity_ref: ref(label("Dijkstra Runtime Analysis")), activity_ref: ref(label("Dijkstra Runtime Analysis")),
+138 -95
View File
@@ -250,7 +250,7 @@
) )
] ]
#let stack(..layers) = context { #let steps(..layers) = context {
let cp = color-palette.get() let cp = color-palette.get()
let radius = 12pt let radius = 12pt
let gutter = 12pt let gutter = 12pt
@@ -316,7 +316,7 @@
} }
} }
#let ref_evidence() = { #let ref_evidence(kinds: none) = {
let ca = cur_activity() let ca = cur_activity()
set ref( set ref(
@@ -326,7 +326,10 @@
align(bottom)[ align(bottom)[
#hl[] #hl[]
*활동 증빙 자료:* *활동 증빙 자료:*
#underline[#ref(label("Evidence) " + ca.name))] #underline[#ref(label("evidence) " + ca.name))]
#if kinds != none {
text(fill: color-ink-helper)[(#kinds)]
}
] ]
} }
@@ -364,7 +367,7 @@
)[ )[
#context { #context {
let m = meta.get() let m = meta.get()
link((page: 1, x: 0pt, y: 0pt))[#m.cur_domain. #m.domain_name] link((page: 2, x: 0pt, y: 0pt))[#m.cur_domain. #m.domain_name]
h(1fr) h(1fr)
if show_activity { if show_activity {
let ca = cur_activity() let ca = cur_activity()
@@ -441,32 +444,73 @@
] ]
} }
// Table of contents templage function // Table of contents template function
#let table_of_contents() = page( #let table_of_contents() = context {
footer: footer_template(), let cp = color-palette.get()
)[
#context {
let m = meta.get() let m = meta.get()
heading(level: 1, outlined: false, numbering: none)[#m.cur_domain. #m.domain_name]
page(
footer: footer_template(),
)[
#show outline.entry.where(level: 1): it => link(it.element.location())[
#block(above: 25pt)[
#grid(
columns: (1fr, auto),
align: horizon,
text(font: font-subhead, size: 15pt, weight: 700)[
#it.indented(it.prefix(), heading_text(it.body()))
],
text(size: 10pt, fill: color-ink-helper)[
#it.page()
],
)
#let desc = it.element.supplement
#if desc != [domain] and desc != [evidence] {
text(fill: color-ink-helper, size: 10pt)[
#it.element.supplement
]
} }
#outline(title: none, depth: 2) #v(10pt)
]
#line(length: 100%, stroke: (paint: cp.accent-faint, thickness: 0.5pt))
]
]
#heading(level: 1, outlined: false, numbering: none)[#m.cur_domain. #m.domain_name]
#label("table_of_contents")
#outline(title: none, depth: 1)
]
}
// Domain frame template function // Domain frame template function
#let domain_frame(title: "", bg_img_path: none, font_color: color-ink, chrome_color: color-ink-helper, content) = page( #let domain_frame(
background: place( title: "",
center + horizon, bg_img_path: none,
if bg_img_path != none { cover_color: white.transparentize(50%),
image(bg_img_path, width: 100.5%, height: 100.5%, fit: "cover") font_color: color-ink,
}, chrome_color: color-ink-helper,
content,
) = page(
background: if bg_img_path != none {
stack(
image(bg_img_path, width: 100.5%, height: 100.5%, fit: "cover"),
move(
dy: -50%,
rect(width: 100.5%, height: 100.5%, fill: cover_color),
), ),
)
} else { none },
header: header_template(font_color: chrome_color), header: header_template(font_color: chrome_color),
footer: footer_template(font_color: chrome_color), footer: footer_template(font_color: chrome_color),
)[ )[
#set text(fill: font_color) #set text(fill: font_color)
#show strong: set text(fill: font_color)
#heading(level: 1)[ #heading(level: 1, supplement: [domain])[
#title #title
] ]
@@ -474,11 +518,16 @@
] ]
// Activity cover template function // Activity cover template function
#let activity_cover(name: "", hook: "", content) = page( #let activity_cover(name: "", hook: "", content) = context {
let cp = color-palette.get()
page(
header: header_template(), header: header_template(),
footer: footer_template(), footer: footer_template(),
)[ fill: cp.cover-surface,
#heading(level: 1)[ )[
#show heading.where(level: 1): set block(above: 0em, below: 25pt)
#heading(level: 1, supplement: hook)[
#name #name
] ]
#label(heading_text(name)) #label(heading_text(name))
@@ -487,45 +536,80 @@
#hook #hook
] ]
#content #v(25pt)
]
// Activity intro template function #content
#let activity_intro(title: "", content) = page( ]
}
#let activity_table() = context {
let cp = color-palette.get()
let ca = cur_activity()
let level1s = query(heading.where(level: 1, outlined: true))
let n = counter(heading).get().at(0)
let sel = heading.where(level: 2, outlined: true).after(ca.location)
if n < level1s.len() {
sel = sel.before(level1s.at(n).location(), inclusive: false)
}
page(
header: header_template(show_activity: true), header: header_template(show_activity: true),
footer: footer_template(), footer: footer_template(),
)[ )[
#kicker("프로젝트 소개") #show outline: it => [
#line(length: 100%, stroke: (paint: cp.accent-faint, thickness: 0.5pt))
#heading(level: 2)[ #it
#title
] ]
#content #show outline.entry.where(level: 2): it => link(it.element.location())[
] #set par(
spacing: 1em,
)
#block(above: 15pt)[
#grid(
columns: (1fr, auto),
align: horizon,
text(size: 12pt, weight: 700)[
#it.body()
],
text(size: 8pt, fill: color-ink-helper)[
#it.page()
],
)
#let desc = it.element.supplement
#par(
spacing: 0pt,
leading: 0.8em,
)[
#text(fill: color-ink-helper, size: 10pt)[
#it.element.supplement
]
]
#line(length: 100%, stroke: (paint: cp.accent-faint, thickness: 0.5pt))
]
]
#heading(level: 2, outlined: false)[
시행착오 목차
]
#outline(title: none, target: sel)
]
}
// Activity process // Activity process
#let activity_process(title: "", content) = page( #let activity_process(title: "", hook: [], content) = page(
header: header_template(show_activity: true), header: header_template(show_activity: true),
footer: footer_template(), footer: footer_template(),
)[ )[
#kicker("시행착오") #kicker("시행착오")
#heading(level: 2)[ #heading(level: 2, supplement: hook)[
#title
]
#content
]
// Activity result
#let activity_result(title: "", content) = page(
header: header_template(show_activity: true),
footer: footer_template(),
)[
#kicker("결과")
#heading(level: 2)[
#title #title
] ]
@@ -540,9 +624,12 @@
header: header_template(), header: header_template(),
footer: footer_template(), footer: footer_template(),
)[ )[
#set heading(numbering: (..nums) => { #set heading(
numbering: (..nums) => {
numbering("A", nums.at(1)) numbering("A", nums.at(1))
}) },
supplement: [evidence],
)
#show heading.where(level: 2): it => { #show heading.where(level: 2): it => {
let num = counter(heading).display( let num = counter(heading).display(
(..nums) => numbering("A", nums.at(1)), (..nums) => numbering("A", nums.at(1)),
@@ -565,7 +652,7 @@
#let cnt = ed.len() #let cnt = ed.len()
#for (name, data) in ed [ #for (name, data) in ed [
#heading(level: 2, supplement: "evidence")[#name] #heading(level: 2, supplement: "evidence")[#name]
#label("Evidence) " + name) #label("evidence) " + name)
#table( #table(
columns: (10em, 1fr), columns: (10em, 1fr),
@@ -708,50 +795,6 @@
fill: color-ink, fill: color-ink,
) )
// outline config
set outline(
indent: 2em,
)
show outline: set par(leading: 1em)
show outline.entry: it => link(
it.element.location(),
)[
#grid(
columns: (1fr, auto),
it.indented(it.prefix(), heading_text(it.body())), it.page(),
)
]
show outline.entry.where(level: 1): it => {
set text(
font: font-subhead,
size: 15pt,
weight: 700,
)
block(above: 50pt)[
#it
#line(length: 100%, stroke: (paint: color-ink-secondary, thickness: 1pt))
]
}
show outline.entry.where(level: 2): it => {
set text(
font: font-body,
size: 12pt,
weight: 400,
fill: color-ink-secondary,
)
if it.element.supplement.text != "evidence" {
block(above: 20pt)[
#it
]
}
}
// render content // render content
doc doc
} }