2016-11-27 7 views
0

私は以前、以下のようにいくつかのファクトを動的に定義しています。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. 

、あなたは事実が特定の順序私は、最後のXを取得できますか

book1 
book2 
book3 
book4 

である見ることができるようにプログラムが

:- 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')). 

を実行するたびにこれらの事実を主張XはbookXであり、挿入する新しい本が常に(X + 1)になるように1ずつインクリメントされますか?

答えて

0

私は一番近いスターバックスで私の心を払い、最も簡単な答えを思いついた。

add_book :- 
    aggregate_all(count, title(_,_), Count), 
    NewCount is Count + 1, 
    atom_concat('book', NewCount, NewBook). 

aggregate_all機能は、私の知識ベースで利用可能だし、いくつかの計算が行われることになるタイトル述語の数をカウントします。

私はより良い提案にはオープンしていますが、より良いアプローチがあれば回答してください。

1

既存のファクトを数え、  1を追加しました。これは機能しますが、1つの大きな欠点があります.1つの新しいファクトを追加する実行時間が、すでにアサートされたファクトの数に比例します。。これは一連のNの事実をアサートすることは、  Nに比例する時間がかかることを意味します。

理想的には、我々は一つの事実を主張することは  풪である状況(1)を持っていると思います、とN  事実を主張することは  풪(N)にあるように。

これを達成する方法の1つは、 本の最初の表現を再考することです。例えば

、あなたは この(一部のデータは、簡潔にするため省略)のようなあなたの本を提示しているとします。この表現は 本の一部にのみ存在するフィールドを省略するために私達にできること

 
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より大きくなります。

主なポイント:このクエリを実行した後

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

:これらの引数は   foldl/4を使用して、  冊のリストに対する述語に適切な順序であります我々は:

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

と同様のfデータベース内author/2のための行為:

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

したがって、我々は我々 必要ランニングインデックスのfoldl/4暗黙的にキープトラックを使用し、 時間を実行している希望しているソリューションを達成しました。あなたのタスクのための賢明なクラッキングソリューションもあることを


注:

 
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'. 
ここ

ジョークは、あなたが実際には、すでに実行中のインデックスが入力されていることであり、我々はそれを得るためにatom_concat/3を使用することができます。

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

;-)

関連する問題