289 lines
6.2 KiB
Perl
289 lines
6.2 KiB
Perl
|
/* $Id$
|
||
|
|
||
|
Part of SWI-Prolog
|
||
|
|
||
|
Author: Jan Wielemaker
|
||
|
E-mail: wielemak@science.uva.nl
|
||
|
WWW: http://www.swi-prolog.org
|
||
|
Copyright (C): 1985-2006, University of Amsterdam
|
||
|
|
||
|
This program is free software; you can redistribute it and/or
|
||
|
modify it under the terms of the GNU General Public License
|
||
|
as published by the Free Software Foundation; either version 2
|
||
|
of the License, or (at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public
|
||
|
License along with this library; if not, write to the Free Software
|
||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
|
||
|
As a special exception, if you link this library with other files,
|
||
|
compiled with a Free Software compiler, to produce an executable, this
|
||
|
library does not by itself cause the resulting executable to be covered
|
||
|
by the GNU General Public License. This exception does not however
|
||
|
invalidate any other reasons why the executable file might be covered by
|
||
|
the GNU General Public License.
|
||
|
*/
|
||
|
|
||
|
:- module(rdf_random_test,
|
||
|
[ concur/2, % +Threads, +Actions
|
||
|
go/0,
|
||
|
go/1, % +Actions
|
||
|
record/1, % +Actions
|
||
|
replay/1 % +Actions
|
||
|
]).
|
||
|
:- asserta(user:file_search_path(foreign, '.')).
|
||
|
:- use_module(rdf_db).
|
||
|
:- use_module(library(thread)).
|
||
|
:- use_module(library(debug)).
|
||
|
|
||
|
replay_file('rnd.reply').
|
||
|
|
||
|
%% concur(+Threads:int, +Actions:int) is det.
|
||
|
%
|
||
|
% Create _N_ Threads, each performing Actions using go/1.
|
||
|
|
||
|
concur(1, Actions) :- !,
|
||
|
go(Actions).
|
||
|
concur(Threads, Actions) :-
|
||
|
create_threads(Threads, go(Actions), Ids),
|
||
|
wait(Ids).
|
||
|
|
||
|
create_threads(0, _, []) :- !.
|
||
|
create_threads(N, G, [Id|T]) :-
|
||
|
thread_create(G, Id, []),
|
||
|
N2 is N - 1,
|
||
|
create_threads(N2, G, T).
|
||
|
|
||
|
wait([]).
|
||
|
wait([H|T]) :-
|
||
|
thread_join(H, Result),
|
||
|
( Result == true
|
||
|
-> true
|
||
|
; format('ERROR from ~w: ~w~n', [H, Result])
|
||
|
),
|
||
|
wait(T).
|
||
|
|
||
|
%% go is det.
|
||
|
%% go(+N) is det.
|
||
|
%
|
||
|
% Perform N random operations on the database.
|
||
|
|
||
|
go :-
|
||
|
go(20000).
|
||
|
go(N) :-
|
||
|
nb_setval(rnd_file, none),
|
||
|
do_random(N),
|
||
|
rdf_statistics(triples(T)),
|
||
|
rdf_predicate_property(rdfs:subPropertyOf, triples(SP)),
|
||
|
format('~D triples; property hierarchy complexity: ~D~n', [T, SP]).
|
||
|
|
||
|
%% record(+N)
|
||
|
%
|
||
|
% As go/1, but record generated random numbers in the file
|
||
|
% specified with replay_file/1.
|
||
|
|
||
|
record(N) :-
|
||
|
replay_file(File),
|
||
|
open(File, write, Out),
|
||
|
nb_setval(rnd_file, out(Out)),
|
||
|
do_random(N).
|
||
|
|
||
|
%% replay(+N)
|
||
|
%
|
||
|
% Replay first N actions recorded using record/1. N is normally
|
||
|
% the same as used for record/1.
|
||
|
|
||
|
replay(N) :-
|
||
|
replay_file(File),
|
||
|
open(File, read, In),
|
||
|
nb_setval(rnd_file, in(In)),
|
||
|
do_random(N).
|
||
|
|
||
|
%% next(-N, +Max)
|
||
|
%
|
||
|
% Produce a random number 1 =< N <= Max. During record/1, write
|
||
|
% to file. Using replay/1, read from file.
|
||
|
|
||
|
next(N, Max) :-
|
||
|
nb_getval(rnd_file, X),
|
||
|
( X == none
|
||
|
-> N is random(Max)+1
|
||
|
; X = in(Fd)
|
||
|
-> read(Fd, N)
|
||
|
; X = out(Fd),
|
||
|
N is random(Max)+1,
|
||
|
format(Fd, '~q.~n', [N]),
|
||
|
flush_output(Fd)
|
||
|
).
|
||
|
|
||
|
|
||
|
%% do_random(N) is det.
|
||
|
%
|
||
|
% Take a random action on the database.
|
||
|
|
||
|
do_random(N) :-
|
||
|
nb_setval(line, 1),
|
||
|
random_actions(N).
|
||
|
|
||
|
random_actions(N) :-
|
||
|
MM is N mod 100,
|
||
|
( MM = 0
|
||
|
-> rdf_statistics(triples(Triples)),
|
||
|
debug(count, 'Count ~w, Triples ~w', [N, Triples])
|
||
|
; true
|
||
|
),
|
||
|
next(Op, 10),
|
||
|
rans(Subject),
|
||
|
ranp(Predicate),
|
||
|
rano(Object),
|
||
|
rang(Graph),
|
||
|
do(Op, Subject, Predicate, Object, Graph),
|
||
|
N1 is N - 1,
|
||
|
( N > 1
|
||
|
-> random_actions(N1)
|
||
|
; true
|
||
|
).
|
||
|
|
||
|
%% do(+Operation, +Subject, +Predicate, +Object, +Graph) is det.
|
||
|
%
|
||
|
% Execute an operation on Graph.
|
||
|
%
|
||
|
% @tbd Test update
|
||
|
|
||
|
do(1, S, P, O, G) :-
|
||
|
debug(bug(S,P,O), 'ASSERT(~q,~q,~q,~q)', [S,P,O,G]),
|
||
|
rdf_assert(S,P,O,G).
|
||
|
do(2, S, P, O, G) :-
|
||
|
debug(bug(S,P,O), 'RETRACTALL(~q,~q,~q,~q)', [S,P,O,G]),
|
||
|
rdf_retractall(S,P,O,G).
|
||
|
do(3, S, _P, _O, _G) :- rdf_s(S). % allow profiling
|
||
|
do(4, S, P, _O, _G) :- rdf_sp(S, P).
|
||
|
do(5, S, _P, _O, _G) :- has_s(S).
|
||
|
do(6, S, P, _O, _G) :- has_sp(S, P).
|
||
|
do(7, S, P, _O, _G) :- reach_sp(S, P).
|
||
|
do(8, _S, P, O, _G) :- reach_po(P, O).
|
||
|
do(9, _, P, _, G) :- % add a random subproperty below me
|
||
|
repeat,
|
||
|
ranp(P2),
|
||
|
P2 \== P, !,
|
||
|
rdf_assert(P2, rdfs:subPropertyOf, P, G),
|
||
|
debug(subPropertyOf, 'Added ~p rdfs:subPropertyOf ~p~n', [P2, P]).
|
||
|
do(10, _, P, _, G) :- % randomly delete a subproperty
|
||
|
( rdf(_, rdfs:subPropertyOf, P)
|
||
|
-> repeat,
|
||
|
ranp(P2),
|
||
|
P2 \== P,
|
||
|
rdf(P2, rdfs:subPropertyOf, P), !,
|
||
|
debug(subPropertyOf, 'Delete ~p rdfs:subPropertyOf ~p~n', [P2, P]),
|
||
|
rdf_retractall(P2, rdfs:subPropertyOf, P, G)
|
||
|
; true
|
||
|
).
|
||
|
|
||
|
rdf_s(S) :-
|
||
|
forall(rdf(S, _, _), true).
|
||
|
rdf_sp(S, P) :-
|
||
|
forall(rdf(S, P, _), true).
|
||
|
has_s(S) :-
|
||
|
forall(rdf_has(S, _, _), true).
|
||
|
has_sp(S, P) :-
|
||
|
forall(rdf_has(S, P, _), true).
|
||
|
reach_sp(S, P) :-
|
||
|
forall(rdf_reachable(S, P, _), true).
|
||
|
reach_po(P, O) :-
|
||
|
( atom(O)
|
||
|
-> forall(rdf_reachable(_, P, O), true)
|
||
|
; true
|
||
|
).
|
||
|
|
||
|
|
||
|
%% rans(-Subject) is det.
|
||
|
%
|
||
|
% Generate a random subject.
|
||
|
|
||
|
rans(X) :-
|
||
|
next(I, 4),
|
||
|
rs(I, X).
|
||
|
|
||
|
rs(1, a).
|
||
|
rs(2, b).
|
||
|
rs(3, c).
|
||
|
rs(4, d).
|
||
|
|
||
|
%% ranp(-Predicate) is det.
|
||
|
%
|
||
|
% Generate a random predicate.
|
||
|
|
||
|
ranp(X) :-
|
||
|
next(I, 4),
|
||
|
rp(I, X).
|
||
|
rp(1, a).
|
||
|
rp(2, p1).
|
||
|
rp(3, p2).
|
||
|
rp(4, p3).
|
||
|
|
||
|
%% rano(-Object) is det.
|
||
|
%
|
||
|
% Generate a random object.
|
||
|
|
||
|
rano(X) :-
|
||
|
next(I, 13),
|
||
|
ro(I, X).
|
||
|
ro(1, a).
|
||
|
ro(2, b).
|
||
|
ro(3, c).
|
||
|
ro(4, p1).
|
||
|
ro(5, literal(1)).
|
||
|
ro(6, literal(hello_world)).
|
||
|
ro(7, literal(bye)).
|
||
|
ro(8, literal(lang(en, bye))).
|
||
|
ro(9, literal(lang(nl, bye))).
|
||
|
ro(10, d).
|
||
|
ro(11, R) :-
|
||
|
next(I, 1000),
|
||
|
atom_concat(r, I, R).
|
||
|
ro(12, literal(L)) :-
|
||
|
next(I, 1000),
|
||
|
atom_concat(l, I, L).
|
||
|
ro(13, literal(lang(Lang, L))) :-
|
||
|
next(I, 1000),
|
||
|
atom_concat(l, I, L),
|
||
|
ranl(Lang).
|
||
|
|
||
|
ranl(Lang) :-
|
||
|
next(I, 2),
|
||
|
rl(I, Lang).
|
||
|
|
||
|
rl(1, en).
|
||
|
rl(2, nl).
|
||
|
|
||
|
|
||
|
%% rang(-Graph) is det.
|
||
|
%
|
||
|
% Generate a random graph.
|
||
|
|
||
|
graph_count(200).
|
||
|
|
||
|
rang(X:Line) :-
|
||
|
graph_count(Count),
|
||
|
next(I, Count),
|
||
|
rg(I, X),
|
||
|
Line = 1.
|
||
|
% line(Line).
|
||
|
|
||
|
term_expansion(rg(x,x), Clauses) :-
|
||
|
graph_count(Count),
|
||
|
findall(rg(I,N), (between(1, Count, I), atom_concat(g,I,N)), Clauses).
|
||
|
|
||
|
rg(x,x).
|
||
|
|
||
|
line(Line) :-
|
||
|
nb_getval(line, Line),
|
||
|
NL is Line+1,
|
||
|
nb_setval(line, NL).
|
||
|
|