Skip to content

Commit

Permalink
Merge pull request #45 from bab2min/documentation
Browse files Browse the repository at this point in the history
update documentation
  • Loading branch information
bab2min authored Sep 10, 2021
2 parents de7201c + e5a06e5 commit ebd7ba8
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 29 deletions.
4 changes: 2 additions & 2 deletions docs/Doxyfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Doxyfile 1.8.13
# Doxyfile 1.9.2

# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
Expand Down Expand Up @@ -162,7 +162,7 @@ FULL_PATH_NAMES = YES
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.

STRIP_FROM_PATH =
STRIP_FROM_PATH = ../

# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
Expand Down
97 changes: 90 additions & 7 deletions include/kiwi/Form.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
/**
* @file Form.h
* @author bab2min ([email protected])
* @brief 형태 및 형태소에 관한 정보를 담는 구조체들이 선언된 헤더
* @version 0.10.0
* @date 2021-09-10
*
*
*/

#pragma once

#include <kiwi/Types.h>
Expand All @@ -7,15 +17,54 @@ namespace kiwi
{
struct Morpheme;

/**
* @brief 형태소에 관한 모든 정보를 담는 구조체의 템플릿
*
* @note `baked = false`는 변경가능한 상태로 인덱스와 관련된 값이나 std::vector 등의 길이를 변경할 수 있음.
* 이 상태는 `kiwi::MorphemeRaw`라는 타입의 부모클래스로 쓰이며, `kiwi::KiwiBuilder`에서 사용한다.
* `baked = true`는 변경 불가능한 상태로 인덱스는 모두 포인터로, std::vector는 FixedVector로 변경되어 수정이 불가능한 대신
* 각 값에 효율적으로 빠르게 접근 가능하다. 이 상태는 `kiwi::Morpheme`이라는 타입의 부모클래스로 쓰이며,
* `kiwi::Kiwi` 내 실제 형태소 분석 단계에 쓰인다.
* @tparam baked
*/
template<bool baked>
struct MorphemeT
{
typename std::conditional<baked, const KString*, uint32_t>::type kform = 0;
POSTag tag = POSTag::unknown;
CondVowel vowel = CondVowel::none;
CondPolarity polar = CondPolarity::none;
typename std::conditional<baked, const KString*, uint32_t>::type kform = 0; /**< 형태에 대한 포인터 */
POSTag tag = POSTag::unknown; /**< 품사 태그 */
CondVowel vowel = CondVowel::none; /**< 선행형태소의 자/모음 조건 */
CondPolarity polar = CondPolarity::none; /**< 선행형태소의 모음조화 조건 */

/**
* @brief 형태소가 두 부분으로 분할된 경우 결합 번호를 표기하기 위해 사용된다.
*
* @note `덥/VA`, `춥/VA` 등의 형태소는 `어/EC`와 만나면 `더워`, `추워`와 같이 형태가 변화한다.
* 이 경우를 각각 처리하기 보다는 `더/V + ㅂ/V`, `추/V + ㅂ/V`과 같이 분해하면
* `ㅂ/V` + `어/EC`가 `워`로 변한다는 규칙만으로 처리가 가능해진다. (이 규칙은 `chunks`를 이용해 형태소 정보에 담길 수 있음)
* 그러나 모든 ㅂ으로 끝나는 형태소가 위와 같은 규칙에 결합되면 안된다.
* 예를 들어 `굽/VA`의 경우 `어/EC`와 만나도 `굽어`라고 형태가 유지되기 때문.
* 따라서 `ㅂ/V`이 결합할 수 있는 조건을 명시해서 이 조건과 맞는 경우에만 `더/V + ㅂ/V` -> `덥/VA`과 같이 복원해야 한다.
* `combineSocket`이 0이면 이런 결합 조건이 없는 일반 형태소임을 뜻하며, 0이 아닌 경우 결합 조건을 가지고 분해된 형태소임을 뜻한다.
* `더/V`와 `워/UNK`(`ㅂ/V + 어/EC`)는 예를 들어 3과 같이 동일한 combineSocket을 할당해 둘이 서로 결합이 가능한 형태소임을 식별한다.
*/
uint8_t combineSocket = 0;

/**
* @brief 여러 형태소가 결합되어 형태가 변경된 경우에 원 형태소 목록을 표기하기 위해 사용된다.
*
* @note `되/VV + 어/EC`의 결합은 `돼`라는 형태로 축약될 수 있다.
* 분석과정에서 `돼`를 만난 경우 역으로 `되/VV + 어/EC`로 분석할 수 있도록 `돼/UNK`를 더미 형태소로 등록하고
* chunks에는 `되/VV`와 `어/EC`에 대한 포인터를 넣어둔다.
*/
typename std::conditional<baked, FixedVector<const Morpheme*>, std::vector<uint32_t>>::type chunks;

/**
* @brief 분할된 형태소의 원형 형태소를 가리키는 오프셋
*
* @note `덥/VA`이 `더/V` + `ㅂ/V`으로 분할된 경우 `더/V`는 `덥/VA`에 대한 오프셋을 combined에 저장해둔다.
* `kiwi::Morpheme::getCombined()`를 통해 원형 형태소의 포인터를 구할 수 있음
* @sa combineSocket
*/
int32_t combined = 0;
float userScore = 0;

Expand All @@ -39,21 +88,39 @@ namespace kiwi
void serializerWrite(std::ostream& ostr) const;
};

/**
* @brief 최적화된 형태소 정보를 담는 구조체. 값을 변경하면 안된다.
*
*/
struct Morpheme : public MorphemeT<true>
{
using MorphemeT<true>::MorphemeT;

/** 형태소의 형태를 반환한다. */
const KString& getForm() const { return *kform; }

/** 분할된 형태소의 경우 원형 형태소를 반환한다. 그 외에는 자기 자신을 반환한다. */
const Morpheme* getCombined() const { return this + combined; }
};

/**
* @brief 형태에 관한 모든 정보를 담는 구조체의 템플릿
*
* @note `baked = false`는 변경가능한 상태로 인덱스와 관련된 값이나 std::vector 등의 길이를 변경할 수 있음.
* 이 상태는 `kiwi::FormRaw`라는 타입의 부모클래스로 쓰이며, `kiwi::KiwiBuilder`에서 사용한다.
* `baked = true`는 변경 불가능한 상태로 인덱스는 모두 포인터로, std::vector는 FixedVector로 변경되어 수정이 불가능한 대신
* 각 값에 효율적으로 빠르게 접근 가능하다. 이 상태는 `kiwi::Form`이라는 타입의 부모클래스로 쓰이며,
* `kiwi::Kiwi` 내 실제 형태소 분석 단계에 쓰인다.
* @tparam baked
*/
template<bool baked>
struct FormT
{
KString form;
CondVowel vowel = CondVowel::none;
CondPolarity polar = CondPolarity::none;
KString form; /**< 형태 */
CondVowel vowel = CondVowel::none; /**< 선행형태소의 자/모음 조건 */
CondPolarity polar = CondPolarity::none; /**< 선행형태소의 모음조화 조건 */
typename std::conditional<baked, FixedVector<const Morpheme*>, Vector<uint32_t>>::type candidate;
/**< 이 형태에 해당하는 형태소들의 목록 */

FormT(const kchar_t* _form = nullptr)
{
Expand Down Expand Up @@ -91,6 +158,22 @@ namespace kiwi
using FormT<true>::FormT;
};

/**
* @brief 변경가능한 형태 정보를 bake하여 최적화한다.
*
* @param o 변경 가능한 형태 정보
* @param morphBase 형태소 배열의 시작 위치
* @return 최적화된 형태 정보
*/
Form bake(const FormRaw& o, const Morpheme* morphBase);

/**
* @brief 변경 가능한 형태소 정보를 bake하여 최적화한다.
*
* @param o 변경 가능한 형태소 정보
* @param morphBase 형태소 배열의 시작 위치
* @param formBase 형태 배열의 시작 위치
* @return 최적화된 형태소 정보
*/
Morpheme bake(const MorphemeRaw& o, const Morpheme* morphBase, const Form* formBase);
}
82 changes: 62 additions & 20 deletions include/kiwi/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* @version 0.10.0
* @date 2021-08-31
*
* @copyright Copyright (c) 2021
*
*/

Expand Down Expand Up @@ -86,21 +85,48 @@ namespace kiwi
using KcVector = Vector<kchar_t>;
using KcScores = Vector<std::pair<KcVector, float>>;
#else
/**
* @brief std::vector의 내부용 타입. mimalloc 옵션에 따라 mi_stl_allocator로부터 메모리를 할당받는다.
*
* @note Vector는 std::vector와 동일한 역할을 수행하지만,
* mimalloc 사용시 Vector가 좀 더 빠른 속도로 메모리를 할당 받을 수 있음.
* Vector와 std::vector는 섞어 쓸 수 없다.
* Kiwi 내부에서만 사용할 것이라면 Vector를, 외부로 반환해야할 값이라면 std::vector를 사용할 것.
*/
template<typename _Ty>
using Vector = std::vector<_Ty>;

/**
* @brief std::unordered_map의 내부용 타입. mimalloc 옵션에 따라 mi_stl_allocator로부터 메모리를 할당받는다.
*
* @note UnorderMap은 std::unordered_map과 동일한 역할을 수행하지만,
* mimalloc 사용시 UnorderMap이 좀 더 빠른 속도로 메모리를 할당 받을 수 있음.
* @sa Vector
*/
template<typename _K, typename _V>
using UnorderedMap = std::unordered_map<_K, _V>;

/**
* @brief std::u16string의 내부용 타입. mimalloc 옵션에 따라 mi_stl_allocator로부터 메모리를 할당받는다.
*
* @note KString은 std::u16string과 동일한 역할을 수행하지만,
* mimalloc 사용시 KString이 좀 더 빠른 속도로 메모리를 할당 받을 수 있음.
* @sa Vector
*/
using KString = std::basic_string<kchar_t>;
using KStringStream = std::basic_stringstream<kchar_t>;
using KcVector = Vector<kchar_t>;
using KcScores = Vector<std::pair<KcVector, float>>;
#endif

/**
* @brief 형태소 품사 태그와 관련된 열거형
*
* @note 나머지 품사 태그에 대한 정보는 README.md 를 참조할 것.
*/
enum class POSTag : uint8_t
{
unknown,
unknown, /**< 미설정 */
nng, nnp, nnb,
vv, va,
mag,
Expand All @@ -115,29 +141,37 @@ namespace kiwi
w_url, w_email, w_mention, w_hashtag,
jks, jkc, jkg, jko, jkb, jkv, jkq, jx, jc,
ep, ef, ec, etn, etm,
v,
max,
v, /**< 분할된 동사/형용사를 나타내는데 사용됨 */
max, /**< POSTag의 총 개수를 나타내는 용도 */
};

constexpr size_t defaultTagSize = (size_t)POSTag::jks;

/**
* @brief 선행 형태소의 종성 여부 조건과 관련된 열거형
*
*/
enum class CondVowel : uint8_t
{
none,
any,
vowel,
vocalic,
vocalic_h,
non_vowel,
non_vocalic,
non_vocalic_h,
none, /**< 조건이 설정되지 않음 */
any, /**< 자음, 모음 여부와 상관 없이 등장 가능 */
vowel, /**< 선행 형태소가 받침이 없는 경우만 등장 가능*/
vocalic, /**< 선행 형태소가 받침이 없거나 ㄹ받침인 경우만 등장 가능*/
vocalic_h, /**< 선행 형태소가 받침이 없거나 ㄹ, ㅎ 받침인 경우만 등장 가능 */
non_vowel, /**< `vowel`의 부정 */
non_vocalic, /**< `vocalic`의 부정 */
non_vocalic_h, /**< `vocalic_h`의 부정 */
};

/**
* @brief 선행 형태소의 양/음성 조건(모음 조화)과 관련된 열거형
*
*/
enum class CondPolarity : char
{
none,
positive,
negative
none, /**< 조건이 설정되지 않음 */
positive, /**< 선행 형태소가 양성(ㅏ,ㅑ,ㅗ)인 경우만 등장 가능 */
negative, /**< 선행 형태소가 음성(그 외)인 경우만 등장 가능 */
};

/**
Expand All @@ -156,13 +190,17 @@ namespace kiwi

struct Morpheme;

/**
* @brief 분석 완료된 각 형태소들의 정보를 담는 구조체
*
*/
struct TokenInfo
{
std::u16string str;
uint32_t position = 0;
uint16_t length = 0;
POSTag tag = POSTag::unknown;
const Morpheme* morph = nullptr;
std::u16string str; /**< 형태 */
uint32_t position = 0; /**< 시작 위치(UTF16 문자 기준) */
uint16_t length = 0; /**< 길이(UTF16 문자 기준) */
POSTag tag = POSTag::unknown; /**< 품사 태그 */
const Morpheme* morph = nullptr; /**< 기타 형태소 정보에 대한 포인터 (OOV인 경우 nullptr) */

TokenInfo() = default;

Expand Down Expand Up @@ -209,6 +247,10 @@ namespace kiwi
}
};

/**
* @brief 분석 완료된 형태소의 목록(`std::vector<TokenInfo>`)과 점수(`float`)의 pair 타입
*
*/
using TokenResult = std::pair<std::vector<TokenInfo>, float>;

using U16Reader = std::function<std::u16string()>;
Expand Down

0 comments on commit ebd7ba8

Please sign in to comment.