首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使TuProlog识别无效事实?

如何使TuProlog识别无效事实?
EN

Stack Overflow用户
提问于 2016-02-04 06:37:42
回答 2查看 138关注 0票数 0

我有以下两个Prolog文件:

ontology.pl:

代码语言:javascript
复制
isSite(Url) :- string(Url).
guestPostPublished(GuestPostId, Date, Site, Url) :-
 string(GuestPostId),
 date(Date),
 isSite(Site),
 string(Url),
 \+(guestPostPublished(GuestPostId, _, _, _)).

invalidFile.pl:

代码语言:javascript
复制
isSite('somesite.com').
guestPostPublished(
    'gp1',
    date(2016,2,2),
    'somesite.com',
    'someUrl').

guestPostPublished(
    'gp1',
    date(2016,2,2),
    'somesite.com',
    'anotherUrl').

invalidFile.pl无效,因为它违反了ontology.pl中指定的规则,即所有GuestPostId必须是唯一的。

当我将数据加载到我的引擎中时,我只会抛出一些显示数据无效的异常。但事实并非如此。

我做错了什么?如何确保向TuProlog引擎提供无效数据时,会收到某种类型的通知(例如,异常或标志)?

下面是我的代码的相关片段(您可以找到整个代码这里):

代码语言:javascript
复制
@Test
public void test2() throws InvalidObjectIdException, IOException,
        MalformedGoalException, InvalidTheoryException, UnknownVarException, NoSolutionException,
        NoMoreSolutionException, InvalidLibraryException {
    final Prolog engine = createEngine();

    try
    {
        loadPrologFiles(engine, new String[]{
                "src/main/resources/ontology.pl",
                "src/main/resources/invalidFile.pl"
        });
        Assert.fail("Engine swallows invalid Prolog file.");
    }
    catch (final Exception exception) {
        // TODO: Check that the right exception is thrown
    }
    final List<String> result = getResults(engine, "guestPostPublished(_,X,_,_).", "X");
    System.out.println("result: " + result);
}

private Prolog createEngine() throws InvalidObjectIdException {
    final Prolog engine = new Prolog();
    engine.addOutputListener(new OutputListener() {
        public void onOutput(OutputEvent outputEvent) {
            System.out.println(String.format("PROLOG: %s", outputEvent.getMsg()));
        }
    });
    Library lib = engine.getLibrary("alice.tuprolog.lib.OOLibrary");
    ((OOLibrary)lib).register(new Struct("stdout"), System.out);
    return engine;
}

private void loadPrologFiles(final Prolog engine, final String[] files) throws IOException, InvalidTheoryException {
    final List<String> paths = Arrays.asList(files);
    final StringBuilder theoryBuilder = new StringBuilder();

    for (final String path : paths) {
        theoryBuilder.append(System.lineSeparator());
        theoryBuilder.append("% ");
        theoryBuilder.append(path);
        theoryBuilder.append(" (START)");
        theoryBuilder.append(System.lineSeparator());
        theoryBuilder.append(FileUtils.readFileToString(new File(path)));
        theoryBuilder.append(System.lineSeparator());
        theoryBuilder.append("% ");
        theoryBuilder.append(path);
        theoryBuilder.append(" (END)");
        theoryBuilder.append(System.lineSeparator());
    }

    final Theory test1 = new Theory(theoryBuilder.toString());
    engine.setTheory(test1);
}

private List<String> getResults(final Prolog engine, final String query, final String varName) throws
        MalformedGoalException, NoSolutionException, UnknownVarException, NoMoreSolutionException {
    SolveInfo res2 = engine.solve(query);

    final List<String> result = new LinkedList<String>();
    if (res2.isSuccess()) {
        result.add(res2.getTerm(varName).toString());
        while (engine.hasOpenAlternatives()) {
            res2 = engine.solveNext();
            final Term x2 = res2.getTerm("X");
            result.add(x2.toString());
        }
    }
    return result;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-02-04 08:23:44

若要在Prolog事实表上设置数据完整性约束,您需要采取不同的方法。我建议您首先尝试使用纯Prolog,而不使用Java位,只是为了了解正在发生的事情。

如果数据库是静态的,并且不会更改,那么很容易:只需加载它,然后对它运行查询,对其执行数据完整性检查。例如,您有一个具有单个列的表site/1,并且希望确保所有值都是字符串:

没有site(S),所以S不是字符串。

代码语言:javascript
复制
\+ ( site(S), \+ string(S) )

如果要将其包装到谓词中,则必须用与表不同的名称命名谓词!

代码语言:javascript
复制
site_must_be_string :-
    \+ ( site(S), \+ string(S) ).

或者,对于另一个列,一个唯一的列(主键):

guest_post_published/4的第一个参数中没有重复项

代码语言:javascript
复制
findall(ID, guest_post_published(ID, _, _, _), IDs),
length(IDs, Len),
sort(IDs, Sorted),   % sort/2 removes duplicates!
length(Sorted, Len). % length does not change after sorting

您可能也需要将其封装在自己的谓词中。

票数 1
EN

Stack Overflow用户

发布于 2016-02-04 14:28:19

如果要在断言“指称”事实之前检查“指称”事实的有效性,则需要阅读(而不是查阅)该文件,并尝试调用每个指称的事实以查看其是否成功。

作为一个非常简单的例子,您可以执行以下操作:

代码语言:javascript
复制
open('invalidFile.pl', read, S),
read(S, TestFact),
call(TestFact).

考虑到您现有的事实和规则,如果从call(TestFact)中读取的术语成功,那么invalidFile.pl就会成功,否则它将失败。您可以使用此序列并阅读所有指称的事实并对它们进行测试:

代码语言:javascript
复制
validate_file(File) :-
    open(File, read, S),
    read_terms(S, Terms),
    maplist(call, Terms),   % This will fail if *any* term fails
    close(S).

read_terms(Stream, []):- 
    at_end_of_stream(Stream). 

read_terms(Stream, [Term|Terms]):- 
    \+  at_end_of_stream(Stream), 
    read(Stream, Term), 
    read_terms(Stream, Terms).

在这种情况下,如果文件中的任何术语为false,则validate_file将失败。作为练习,您可以通过跟踪“术语计数”或类似于read_terms中的内容来使其更智能,并编写一个谓词,检查一个术语并在其失败时反馈该术语号,这样您就可以看到哪一个(几个)失败了。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35194122

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档