OSDN Git Service

単語抽出の向上
[chnosproject/CHNOSProject.git] / CHNOSProject / AI003 / AI003 / main.c
1 //\r
2 //  main.c\r
3 //  AI003\r
4 //\r
5 //  Created by 西田 耀 on 13/01/28.\r
6 //  Copyright (c) 2013年 Hikaru Nishida. All rights reserved.\r
7 //\r
8 \r
9 //\r
10 //Include headers\r
11 //\r
12 \r
13 #include <stdio.h>\r
14 #include "core.h"\r
15 \r
16 //\r
17 //Define static values\r
18 //\r
19 \r
20 AI_WorkingSet WorkingSet;\r
21 \r
22 int main(int argc, const char * argv[])\r
23 {\r
24     //エントリポイント\r
25     int i, i_max;\r
26     CHNLIB_String *input, *temp;\r
27     CHNLIB_UIPArray *separated, *sorted;\r
28     int passthink;\r
29     FILE *readfp;\r
30     \r
31     CHNLIB_Environment_SetCurrentWorkingDirectory(argv[0]);\r
32     \r
33     CHNLIB_Debug("Hello, World.", CHNLIB_DEBUG_ARGUMENTS);\r
34     \r
35     AI_System_InitializeSystemWorkingSet();\r
36     \r
37     AI_System_LoadMemory(AI_CONFIG_FILE_NAME);\r
38     \r
39     readfp = NULL;\r
40 \r
41     for(;;){\r
42         passthink = False;\r
43         if(readfp == NULL){\r
44             input = CHNLIB_ReadLine(stdin);\r
45         } else{\r
46             input = CHNLIB_ReadLine(readfp);\r
47             if(input == NULL){\r
48                 readfp = NULL;\r
49             } else{\r
50                 puts(CHNLIB_String_GetReferencePointerOfCString(input));\r
51             }\r
52         }\r
53 \r
54         if(CHNLIB_String_CompareStringWithCString(input, "::")){\r
55             //システムコマンド解釈\r
56             passthink = True;\r
57             separated = CHNLIB_UIPArray_Initialize();\r
58             CHNLIB_UIPArray_GetSeparatedStringByUIPArray(&separated, WorkingSet.SystemWordList0, input);\r
59             \r
60             temp = CHNLIB_UIPArray_GetPointerByIndex(separated, 2);\r
61             if(temp != NULL){\r
62                 if(CHNLIB_String_CompareStringWithCString(temp, "info")){\r
63                     printf("AI internal information:\n");\r
64                 } else if(CHNLIB_String_CompareStringWithCString(temp, "exit")){\r
65                     break;\r
66                 } else if(CHNLIB_String_CompareStringWithCString(temp, "wordlist")){\r
67                     sorted = CHNLIB_UIPArray_SortInDescendingOrderByData32(WorkingSet.RootWordList);\r
68                     i_max = CHNLIB_UIPArray_GetNumberOfDatas(sorted);\r
69                     for(i = 0; i < i_max; i++){\r
70                         printf("word%3d:%3d:%s\n", i, CHNLIB_UIPArray_GetData32ByIndex(sorted, i), CHNLIB_String_GetReferencePointerOfCString(CHNLIB_UIPArray_GetPointerByIndex(sorted, i)));\r
71                     }\r
72                     CHNLIB_UIPArray_FreeOnlyArray(&sorted);\r
73                 } else if(CHNLIB_String_CompareStringWithCString(temp, "readfile")){\r
74                     //::readfile:filename\r
75                     readfp = fopen(CHNLIB_String_GetReferencePointerOfCString(CHNLIB_UIPArray_GetPointerByIndex(separated, 4)), "rb");\r
76                     if(readfp == NULL){\r
77                         puts("File open error.");\r
78                     }\r
79                 } else{\r
80                     passthink = False;\r
81                 }\r
82             }\r
83             \r
84             //WorkingSet.SystemWordList0を使っているので、解放しないように注意\r
85             CHNLIB_UIPArray_FreeSelectedAll(&separated);\r
86         }\r
87         \r
88         if(!passthink){\r
89             //AIへの入力\r
90             //::readfile:AITestData_ja.txt\r
91             AI_Think_LearnWordFromInputString(input);\r
92             \r
93             CHNLIB_UIPArray_AppendLast(&WorkingSet.InputHistory, CHNLIB_UIPArray_GetNumberOfDatas(WorkingSet.InputHistory), input);\r
94         }\r
95     }\r
96     \r
97     return 0;\r
98 }\r
99 \r
100 void AI_Think_LearnWordFromInputString(CHNLIB_String *input)\r
101 {\r
102     //入力文字列から単語を抽出して記憶する。\r
103     CHNLIB_UIPArray *candidateWordList;\r
104     int i, i_max;\r
105     int tagIndex, maxExistingWordIndex;\r
106     \r
107     candidateWordList = CHNLIB_UIPArray_Initialize();\r
108     candidateWordList = AI_Think_SlideLookUpWordByHistory(input);\r
109     i_max = CHNLIB_UIPArray_GetNumberOfDatas(candidateWordList);\r
110     maxExistingWordIndex = CHNLIB_UIPArray_GetNumberOfDatas(WorkingSet.RootWordList) - 1;\r
111     \r
112     printf("Index(Decimal),CountOfContain(Decimal), String\n");\r
113     for(i = 0; i < i_max; i++){\r
114         printf("%d,%d,%s\n", i, CHNLIB_UIPArray_GetData32ByIndex(candidateWordList, i), CHNLIB_String_GetReferencePointerOfCString(CHNLIB_UIPArray_GetPointerByIndex(candidateWordList, i)));\r
115         \r
116         //単語リストに登録。\r
117         tagIndex = AI_Memory_AddRootWordData(CHNLIB_UIPArray_GetPointerByIndex(candidateWordList, i));\r
118         \r
119         CHNLIB_UIPArray_SetData32ByIndex(WorkingSet.RootWordList, tagIndex, CHNLIB_UIPArray_GetData32ByIndex(WorkingSet.RootWordList, tagIndex) + CHNLIB_UIPArray_GetData32ByIndex(candidateWordList, i));\r
120         \r
121         if(tagIndex <= maxExistingWordIndex){\r
122             //既存のタグなので、解放されるようにdata32をFalseにしておく。\r
123             CHNLIB_UIPArray_SetData32ByIndex(candidateWordList, i, False);\r
124         }\r
125         //新規追加されたタグについては0以上の値つまりTrueが設定されているはずなので、解放されない。\r
126     }\r
127     //data32 == Falseのタグ、つまり既存のタグと同じだったもののみ解放する。\r
128     CHNLIB_UIPArray_FreeSelectedAll(&candidateWordList);\r
129 \r
130     return;\r
131 }\r
132 \r
133 CHNLIB_UIPArray *AI_Think_SlideLookUpWordByHistory(CHNLIB_String *input)\r
134 {\r
135     //[UTF-8]\r
136     //入力文字列と履歴文字列を照らし合わせ、単語の候補を抜き出す。\r
137     //候補単語は、新たに確保されたUIPArrayに格納され、そのArrayへのポインタを返す。\r
138     //data32=入力文字列中に含まれる候補単語の数。\r
139     //pointer=候補単語を示すCHNLIB_String.\r
140     CHNLIB_UIPArray *candidatewordlist;\r
141     int i, i_max;\r
142     int j, j_max;\r
143     int k, k_max;\r
144     const char *cstr_input, *cstrp_input;\r
145     const char *cstr_history, *cstrp_history;\r
146     int candidatelength, templength;\r
147     int cstrp_input_length;\r
148     \r
149     candidatewordlist = CHNLIB_UIPArray_Initialize();\r
150     i_max = CHNLIB_UIPArray_GetNumberOfDatas(WorkingSet.InputHistory);\r
151     \r
152     cstr_input = CHNLIB_String_GetReferencePointerOfCString(input);\r
153     k_max = CHNLIB_UTF8_GetStringLengthByCharacter(cstr_input);\r
154     cstrp_input = cstr_input;\r
155     \r
156     for(k = 0; k < k_max; k++){\r
157         //input character loop\r
158         candidatelength = 0;\r
159         cstrp_input_length = CHNLIB_UTF8_GetStringLengthByCharacter(cstrp_input);\r
160         for(i = 0; i < i_max; i++){\r
161             //history entry loop\r
162             cstr_history = CHNLIB_String_GetReferencePointerOfCString(CHNLIB_UIPArray_GetPointerByIndex(WorkingSet.InputHistory, i));\r
163             j_max = CHNLIB_UTF8_GetStringLengthByCharacter(cstr_history);\r
164             cstrp_history = cstr_history;\r
165             \r
166             for(j = 0; j < j_max; j++){\r
167                 //history character loop\r
168                 templength = CHNLIB_UTF8_CompareString_LeftHand(cstrp_history, cstrp_input);\r
169                 if(templength > candidatelength && templength != cstrp_input_length){\r
170                     //前方一致の長さが、これまで見つかった単語よりも長く、かつ入力文字列の検索部分の全長ではない場合、\r
171                     //単語の候補とする。\r
172                     candidatelength = templength;\r
173                 }\r
174                 CHNLIB_UTF8_GetNextUnicodeOfCharacter(cstrp_history, &cstrp_history);\r
175             }\r
176         }\r
177         if(candidatelength > 0){\r
178             CHNLIB_UIPArray_AppendLast_ProtectFromDuplication(&candidatewordlist, 0, CHNLIB_String_ExtractByLength(input, CHNLIB_UTF8_GetByteSizeFromLengthByCharacter(cstr_input, 0, k - 1), CHNLIB_UTF8_GetByteSizeFromLengthByCharacter(cstrp_input, 0, candidatelength - 1)), &AI_Memory_AddRootWordData_IsDuplicated);\r
179         }\r
180         CHNLIB_UTF8_GetNextUnicodeOfCharacter(cstrp_input, &cstrp_input);\r
181     }\r
182     \r
183     //各候補単語が履歴文字列にいくつ含まれているかをdata32に保存する。\r
184     k_max = CHNLIB_UIPArray_GetNumberOfDatas(candidatewordlist);\r
185     for(k = 0; k < k_max; k++){\r
186         j = 0;\r
187         cstr_input = CHNLIB_String_GetReferencePointerOfCString(CHNLIB_UIPArray_GetPointerByIndex(candidatewordlist, k));\r
188         for(i = 0; i < i_max; i++){\r
189             cstr_history = CHNLIB_String_GetReferencePointerOfCString(CHNLIB_UIPArray_GetPointerByIndex(WorkingSet.InputHistory, i));\r
190             j += CHNLIB_UTF8_GetCountOfContain(cstr_history, cstr_input);\r
191             \r
192         }\r
193         CHNLIB_UIPArray_SetData32ByIndex(candidatewordlist, k, j);\r
194     }\r
195     \r
196     //重複抽出フィルタリング\r
197     AI_Think_CandidateWordList_Filter01(&candidatewordlist, 1);\r
198     AI_Think_CandidateWordList_Filter00(&candidatewordlist);\r
199     \r
200     return candidatewordlist;\r
201 }\r
202 \r
203 int AI_Think_CandidateWordList_Filter00(CHNLIB_UIPArray **candidatewordlist)\r
204 {\r
205     //[Not implemented]\r
206     //[UTF-8]\r
207     //AI_Think_SlideLookUpWordByHistoryで返されたArray内の候補単語に対して、フィルターをかける。\r
208     //00:長い単語に含まれており、かつ出現頻度が長い単語と等しい単語を削除\r
209     int i, i_max;\r
210     CHNLIB_String *nowstr, *basestr;\r
211     int basestrCoC;     //CountOfContainInHistoryStrings\r
212     \r
213     i_max = CHNLIB_UIPArray_GetNumberOfDatas(*candidatewordlist);\r
214     basestr = CHNLIB_UIPArray_GetPointerByIndex(*candidatewordlist, 0);\r
215     basestrCoC = CHNLIB_UIPArray_GetData32ByIndex(*candidatewordlist, 0);\r
216     for(i = 1; i < i_max; i++){\r
217         nowstr = CHNLIB_UIPArray_GetPointerByIndex(*candidatewordlist, i);\r
218         if(CHNLIB_UTF8_GetCountOfContain(CHNLIB_String_GetReferencePointerOfCString(basestr), CHNLIB_String_GetReferencePointerOfCString(nowstr)) > 0){\r
219             //nowstrはbasestrに含まれている\r
220             if(basestrCoC == CHNLIB_UIPArray_GetData32ByIndex(*candidatewordlist, i)){\r
221                 //かつ出現頻度が等しいので不要な単語\r
222                 //出現頻度を0にして、後で削除する。\r
223                 CHNLIB_UIPArray_SetData32ByIndex(*candidatewordlist, i, 0);\r
224             }\r
225         }\r
226         \r
227         if(CHNLIB_UIPArray_GetData32ByIndex(*candidatewordlist, i) != 0){\r
228             //単語は削除されなかった、つまり異なる単語なので、basestrを更新\r
229             basestr = nowstr;\r
230             basestrCoC = CHNLIB_UIPArray_GetData32ByIndex(*candidatewordlist, i);\r
231         }\r
232     }\r
233     \r
234     for(i = 1; i < i_max; i++){\r
235         if(CHNLIB_UIPArray_GetData32ByIndex(*candidatewordlist, i) == 0){\r
236             //削除対象\r
237             CHNLIB_UIPArray_RemoveByIndex(candidatewordlist, i);\r
238             i--;\r
239             i_max--;\r
240         }\r
241     }\r
242     \r
243     return 0;\r
244 }\r
245 \r
246 int AI_Think_CandidateWordList_Filter01(CHNLIB_UIPArray **candidatewordlist, int length)\r
247 {\r
248     //[Not implemented]\r
249     //[UTF-8]\r
250     //AI_Think_SlideLookUpWordByHistoryで返されたArray内の候補単語に対して、フィルターをかける。\r
251     //01:length以下の文字数の単語を削除\r
252     \r
253     int i, i_max;\r
254     \r
255     i_max = CHNLIB_UIPArray_GetNumberOfDatas(*candidatewordlist);\r
256     for(i = 0; i < i_max; i++){\r
257         if(CHNLIB_UTF8_GetStringLengthByCharacter(CHNLIB_String_GetReferencePointerOfCString(CHNLIB_UIPArray_GetPointerByIndex(*candidatewordlist, i))) <= length){\r
258             CHNLIB_UIPArray_RemoveByIndex(candidatewordlist, i);\r
259             i--;\r
260             i_max--;\r
261         }\r
262     }\r
263     \r
264     return 0;\r
265 }\r
266 \r
267 int AI_Memory_AddRootWordData(CHNLIB_String *tag)\r
268 {\r
269     //WorkingSet.RootWordListに文字列を追加する。\r
270     //重複がある場合は警告を出し、追加しない。\r
271     //戻り値は追加されたまたは重複したタグのIndex.\r
272     \r
273     return CHNLIB_UIPArray_AppendLast_ProtectFromDuplication(&WorkingSet.RootWordList, 0, tag, &AI_Memory_AddRootWordData_IsDuplicated);\r
274 }\r
275 \r
276 int AI_Memory_AddRootWordData_IsDuplicated(const void *listtag, const void *newtag)\r
277 {\r
278     //CHNLIB_UIPArray_AppendLast_ProtectFromDuplicationに渡す関数ポインタ。\r
279     if(CHNLIB_StructureHeader_GetTypeID(listtag) != CHNLIB_STRUCT_ID_String){\r
280         return False;\r
281     }\r
282     if(CHNLIB_String_CompareString_Strict(listtag, newtag)){\r
283         CHNLIB_ReportError("Word[%s] has already existed.", CHNLIB_DEBUG_ARGUMENTS, CHNLIB_String_GetReferencePointerOfCString(newtag));\r
284         return True;\r
285     }\r
286     return False;\r
287 }\r
288 \r
289 void AI_System_InitializeSystemWorkingSet(void)\r
290 {\r
291     //WorkingSetを初期化する。\r
292     WorkingSet.SystemWordList0 = CHNLIB_UIPArray_Initialize();\r
293     CHNLIB_UIPArray_AppendLast(&WorkingSet.SystemWordList0, True, CHNLIB_String_Initialize(":"));\r
294     CHNLIB_UIPArray_AppendLast(&WorkingSet.SystemWordList0, True, CHNLIB_String_Initialize(","));\r
295     \r
296     WorkingSet.InputHistory = CHNLIB_UIPArray_Initialize();\r
297     \r
298     return;\r
299 }\r
300 \r
301 void AI_System_LoadMemory(const char configfilename[])\r
302 {\r
303     //指定されたファイル名のテキストファイルから設定を読み出す。\r
304     FILE *fp;\r
305     CHNLIB_String *line, *currentfilename;\r
306     int i;\r
307     \r
308     fp = fopen(configfilename, "rb");\r
309     currentfilename = CHNLIB_ReadLine(fp);\r
310     fclose(fp);\r
311     \r
312     fp = fopen(CHNLIB_String_GetReferencePointerOfCString(currentfilename), "rb");\r
313     \r
314     WorkingSet.RootWordList = CHNLIB_UIPArray_Initialize();\r
315     for(i = 1; ;i++){\r
316         line = CHNLIB_ReadLine(fp);\r
317         if(line == NULL){\r
318             break;\r
319         }\r
320         CHNLIB_UIPArray_AppendLast(&WorkingSet.RootWordList, i, line);\r
321         //CHNLIB_String_Free(line);リストに登録している実体なので解放の必要なし!\r
322     }\r
323     fclose(fp);\r
324     CHNLIB_String_Free(currentfilename);\r
325     \r
326     //CHNLIB_Debug_PrintStructureData(WorkingSet.RootWordList, 0);\r
327     \r
328     return;\r
329 }\r