如何在Prolog中动态断言新数据

时间:2016-11-27 04:06:10

标签: prolog

我之前已动态定义了一些事实,如下所示。

% declare dynamic facts
:- dynamic title/2.
:- dynamic author/2.
:- dynamic publisher/2.
:- dynamic price/2.
:- dynamic call_number/2.
:- dynamic edition/2.
:- dynamic data_disk/2.
每次程序运行时

并断言这些事实

:- assert(title(book1, 'Elementary Statistics')).
:- assert(title(book2, 'Statistics for Engineers')).
:- assert(title(book3, 'Statistics for Engineers and Scientists')).
:- assert(title(book4, 'IT in Language Learning')).

:- assert(author(book1, 'Patricia Wilson')).
:- assert(author(book2, 'James Mori')).
:- assert(author(book3, 'James Mori')).
:- assert(author(book4, 'O Ivan')).

:- assert(publisher(book1, 'Addison Wesley')).
:- assert(publisher(book2, 'World Scientific')).
:- assert(publisher(book3, 'World Scientific')).
:- assert(publisher(book4, 'Universal Press')).

:- assert(price(book1, 75)).
:- assert(price(book2, 125)).
:- assert(price(book3, 125)).
:- assert(price(book4, 5)).

:- assert(call_number(book1, 'QA373')).
:- assert(call_number(book2, 'QA673')).
:- assert(call_number(book3, 'QA674')).
:- assert(call_number(book4, 'QA007')).

:- assert(edition(book1, 1)).
:- assert(edition(book2, 3)).
:- assert(edition(book3, 2)).
:- assert(edition(book4, 1)).

:- assert(data_disk(book1, 'No')).
:- assert(data_disk(book2, 'Yes')).
:- assert(data_disk(book3, 'Yes')).
:- assert(data_disk(book4, 'No')).

正如您所看到的那样,事实是按照一定的顺序

book1
book2
book3
book4

如何获得最后的X,其中X是bookX,并且增加1,以便插入的新书总是(X + 1)?

2 个答案:

答案 0 :(得分:1)

您找到了一个解决方案(即计算现有事实,并添加1),这有效但有一个主要缺点:它使添加单个新事实的运行时间与已经断言的事实数量成比例即可。这意味着声明一系列N个事实需要的时间与N 2 成正比。

理想情况下,我们希望断言单个事实在?(1)中,并且断言 N 事实因此在?( N )。

实现这一目标的一种方法是重新考虑您对书籍的初始陈述。

例如,假设您像这样展示您的书籍(为简洁起见省略了一些数据):

book([title('Elementary Statistics'),
      author('Patricia Wilson'),
      price(75)]).
book([title('Statistics for Engineers'),
      author('James Mori'),
      publisher('World Scientific')]).

请注意,此表示允许我们省略仅存在于某些书籍中的字段。其他陈述也是有道理的。

我们可以使用findall/3轻松获取所有这些事实:

?- findall(Book, book(Book), Books).

这些事实的数量是线性

此外,让我们按如下方式定义assert_book_/3

assert_book_(Book, N0, N) :-
        memberchk(title(Title), Book),
        memberchk(author(Author), Book),
        assertz(title(N0,Title)),
        assertz(author(N0,Author)),
        N #= N0 + 1.

为了举例,我专注于标题作者。我将此作为练习留下来。

这个谓词的参数是:

  • 要声明的图书,表示为属性列表
  • 当前索引 N0
  • 下一个索引 N1,它只是一个而不是N0

现在要点:这些参数使用 {{1}以适当的顺序弃用谓词书籍 }:

?- findall(Book, book(Book), Books),
   foldl(assert_book_, Books, 1, _).

运行此查询后,我们有:

?- title(N, T).
N = 1,
T = 'Elementary Statistics' ;
N = 2,
T = 'Statistics for Engineers'.

数据库中foldl/4的类似事实:

?- author(N, T).
N = 1,
T = 'Patricia Wilson' ;
N = 2,
T = 'James Mori'.

因此,我们使用author/2隐式跟踪我们需要的运行索引,并实现了具有所需运行时间的解决方案。

请注意,您的任务还有一个明智的解决方案:

assert_title(Book, Title) :-
        atom_concat(book, N0, Book),
        atom_number(N0, N),
        assertz(title(N, Title)).

这显然不是你想要的,但如果你使用的话,它会适用于你展示的例子:

:- assert_title(book1, 'Elementary Statistics').
:- assert_title(book2, 'Statistics for Engineers').

现在我们又来了:

?- title(N, Title).
N = 1,
Title = 'Elementary Statistics' ;
N = 2,
Title = 'Statistics for Engineers'.

这里的笑话是你已经实际输入了运行索引,我们可以使用foldl/4来获取它:

?- atom_concat(book, N0, book1),
   atom_number(N0, N).
N0 = '1',
N = 1.

- )

答案 1 :(得分:0)

我在最近的星巴克清醒过来,想出了最简单的答案。

@Autowired
    @Qualifier("datasource")
    private DataSource dataSource;

    @Bean
    public TokenStore tokenStore() {
        return new JdbcTokenStore(dataSource);
    }


    @Bean
    protected AuthorizationCodeServices authorizationCodeServices() {
        return new JdbcAuthorizationCodeServices(dataSource);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer)
            throws Exception {
        oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints)
            throws Exception {
        endpoints.authorizationCodeServices(authorizationCodeServices())
                .authenticationManager(authenticationManager).tokenStore(tokenStore())
                .approvalStoreDisabled();
    }

aggregate_all函数将计算我的知识库中可用的标题谓词数,并将执行一些计算。

我愿意接受更好的建议,如果你有更好的方法,请回复。