Prolog中术语频率的计算

Prolog中术语频率的计算,prolog,Prolog,我搜索了谷歌,但没有结果。这里有谁能告诉我如何在Prolog中编码术语频率?“逻辑”越多越好。 给定一个文本文件,忽略非字母数字字符,检测单词,删除停止词(可能在外部文件中给出),计算文件中每个单词的出现次数,并按频率递减顺序输出类似“word:freq”的内容 谢谢 (顺便说一句,这不是家庭作业,这是我正在做的项目)这里有一些东西可以让你开始: 它假定每个单词都位于输入文件的单独一行上 不处理“停止词” 不实现排序 要过滤停止词,一个好方法是通过assert: read_sw(Path) :-

我搜索了谷歌,但没有结果。这里有谁能告诉我如何在Prolog中编码术语频率?“逻辑”越多越好。 给定一个文本文件,忽略非字母数字字符,检测单词,删除停止词(可能在外部文件中给出),计算文件中每个单词的出现次数,并按频率递减顺序输出类似“word:freq”的内容

谢谢


(顺便说一句,这不是家庭作业,这是我正在做的项目)

这里有一些东西可以让你开始:

它假定每个单词都位于输入文件的单独一行上

不处理“停止词”

不实现排序


要过滤停止词,一个好方法是通过
assert

read_sw(Path) :-
    open( Path, read, Stream ),
    read_words_file( Stream, Words ),
    add_sw(Words).

add_sw([]).
add_sw([Word|Rest]) :-
    assertz(stop_word(Word)),
    add_sw(Rest).
完成此操作后,您可以使用
stop_word/1
检查某个单词是否为stop word并忽略它。例如,如果您正在实现Scott Hunter的答案,您可以在
calc_freq/2
中添加一个附加子句来过滤掉这些单词:

calc_freq( [], [] ).
calc_freq( [Word|Words], Freq ) :-
    stop_word(Word), !,
    calc_freq( Words, Freq ).
calc_freq( [Word|Words], Freq ) :-
    calc_freq( Words, FreqRest ),
    add_word( Word, FreqRest, Freq ).

我在这个答案中使用了SWI Prolog广泛的库支持,因此可能不适合您的情况

当然,解决任何编程任务的方式都会受到所选语言的可用性和使用能力的强烈影响

在这里,我使用,如果您的系统错过了它,那么您可以使用一个列表或使用assert/retract进行模拟

这个片段只是展示了一种(惯用的)计算单词的方法,计算频率可以通过库(聚合)或一点算术轻松完成,也许你想试着自己写下来练习语言

/*  File:    frequency_of_words.pl
    Author:  Carlo,,,
    Created: May 23 2012
    Purpose: http://stackoverflow.com/questions/10711483/calculating-term-frequency-in-prolog
*/

:- module(frequency_of_words, [count_words/2, count_words/1]).
:- [library(assoc)].

count_words(File, Assoc) :-
    empty_assoc(Empty),
    open(File, read, Stream),
    frequency_of_words(Stream, Empty, Assoc, ""),
    close(Stream).
count_words(File) :-
    count_words(File, Assoc),
    assoc_to_list(Assoc, List),
    maplist(writeln, List).

frequency_of_words(Stream, SoFar, Words, CurrWord) :-
    get_code(Stream, Code),
    (   Code == -1
    ->  update_dictionary(SoFar, Words, CurrWord)
    ;   use_character(Code, SoFar, Updated, CurrWord, NextWord),
        frequency_of_words(Stream, Updated, Words, NextWord)
    ).

update_dictionary(SoFar, SoFar, Word) :-
    skip_word(Word).
update_dictionary(SoFar, Updated, Codes) :-
    atom_codes(Word, Codes),
    ( get_assoc(Word, SoFar, CountSoFar) ; CountSoFar = 0 ),
    WordCount is CountSoFar + 1,
    put_assoc(Word, SoFar, WordCount, Updated).

use_character(Code, SoFar, Updated, CurrWord, NextWord) :-
    (   word_character(Code)
    ->  Updated = SoFar,
        NextWord = [Code|CurrWord]
    ;   reverse(CurrWord, Forward),
        update_dictionary(SoFar, Updated, Forward),
        NextWord = ""
    ).

word_character(Code) :-
    [Code] @>= "A", [Code] @=< "Z" ;
    [Code] @>= "a", [Code] @=< "z" ;
    [Code] @>= "0", [Code] @=< "9" ;
    [Code] == "_".

skip_word(""). % a trick on EOF or consecutive blanks: not really a skipword
skip_word("is").

这对于一个所谓的问题来说太宽泛了。到目前为止你试过什么?你面临什么问题?Prolog不是我选择的语言风格。我正在寻找一位“专家开场白”,告诉我如何用逻辑编程的方式思考这个问题。这个问题不适合逻辑编程IMHO。即使在Prolog中实现,它的结构也非常类似于命令式程序。我建议尝试以最好的方式实现它,然后提交给同行评审,这样人们就可以提出更多的“逻辑”方法来改进它。谢谢你的意见mgibsonbr。问题不是“这对逻辑编程来说是一个好问题吗?”而是“你如何在prolog中做到这一点?”问题不仅仅是让它工作——这不是家庭作业,我明天也不必发布代码。这是关于如何用逻辑来表达它。有Prolog经验的人可以比我做得更好。希望一些prolog专家会读到这篇文章。不过,这个问题还是有点太宽泛了。我为停止词问题提供了答案,对于文本的解析(即识别自由文本中的词),我作为建议离开,希望它能有所帮助!谢谢我假设read_文件与read相同,是吗?在任何情况下,这个问题的一个部分,我想看到的是将一行拆分为单词的逻辑;以及表示非字母过滤的逻辑;以及过滤停止词的逻辑。我希望其中的很多都能用基本事实来表达,例如stop_单词(the)。你会这样做吗?谢谢!这涵盖了我一直在寻找的很多东西。看了很久。。。此解决方案使用内联处理方法,即在读取文件时一次读取一个字符。prolog专家就是这样自然而然地处理这个问题的吗?(另一种选择是管道和过滤器,您首先读取整个文件,然后从整个数据中过滤出非字母,并生成另一段数据,然后检测单词并传递它们,等等。这会使规则的逻辑在prolog中更简单还是更复杂?)我认为这样代码会更复杂,需要更多的步骤。如果您读取了整个文件,那么就可以使用DCG,但是这里没有任何好处。我使用的技术类似于(非常)简单的扫描仪。
/*  File:    frequency_of_words.pl
    Author:  Carlo,,,
    Created: May 23 2012
    Purpose: http://stackoverflow.com/questions/10711483/calculating-term-frequency-in-prolog
*/

:- module(frequency_of_words, [count_words/2, count_words/1]).
:- [library(assoc)].

count_words(File, Assoc) :-
    empty_assoc(Empty),
    open(File, read, Stream),
    frequency_of_words(Stream, Empty, Assoc, ""),
    close(Stream).
count_words(File) :-
    count_words(File, Assoc),
    assoc_to_list(Assoc, List),
    maplist(writeln, List).

frequency_of_words(Stream, SoFar, Words, CurrWord) :-
    get_code(Stream, Code),
    (   Code == -1
    ->  update_dictionary(SoFar, Words, CurrWord)
    ;   use_character(Code, SoFar, Updated, CurrWord, NextWord),
        frequency_of_words(Stream, Updated, Words, NextWord)
    ).

update_dictionary(SoFar, SoFar, Word) :-
    skip_word(Word).
update_dictionary(SoFar, Updated, Codes) :-
    atom_codes(Word, Codes),
    ( get_assoc(Word, SoFar, CountSoFar) ; CountSoFar = 0 ),
    WordCount is CountSoFar + 1,
    put_assoc(Word, SoFar, WordCount, Updated).

use_character(Code, SoFar, Updated, CurrWord, NextWord) :-
    (   word_character(Code)
    ->  Updated = SoFar,
        NextWord = [Code|CurrWord]
    ;   reverse(CurrWord, Forward),
        update_dictionary(SoFar, Updated, Forward),
        NextWord = ""
    ).

word_character(Code) :-
    [Code] @>= "A", [Code] @=< "Z" ;
    [Code] @>= "a", [Code] @=< "z" ;
    [Code] @>= "0", [Code] @=< "9" ;
    [Code] == "_".

skip_word(""). % a trick on EOF or consecutive blanks: not really a skipword
skip_word("is").
?- count_words('frequency_of_words.pl').
0-2
1-3
2012-1
23-1
9-1
A-1
Author-1
Carlo-1
Code-14
Codes-2
CountSoFar-3
Created-1
CurrWord-6
EOF-1
Empty-2
File-3
Forward-2
Full-2
List-2
May-1
NextWord-5
Purpose-1
SoFar-11
StackOverflow-1
Stream-6
Updated-7
Word-5
WordCount-2
Words-3
Z-1
_-1
a-3
answer-1
assoc-1
assoc_to_list-1
atom_codes-1
blanks-1
close-1
consecutive-1
count_words-2
empty_assoc-1
frequency_of_words-5
get_assoc-1
get_code-1
library-1
maplist-1
module-1
not-1
on-1
open-1
or-1
pl-1
put_assoc-1
read-1
really-1
reverse-1
skip_word-3
skipword-1
trick-1
update_dictionary-4
use_character-2
word_character-2
writeln-1
z-1