1 | :- multifile generate/2. | |
2 | :- multifile shrink/3. | |
3 | ||
4 | :- use_module(library(random),[random/3,random_member/2]). | |
5 | ||
6 | generate(prob_ast_int_expr,Value) :- | |
7 | generate(prob_ast_int_expr([]),Value). | |
8 | ||
9 | % Options: | |
10 | % not-well-defined | |
11 | % id to enable random generation of identifier | |
12 | % all options of any type are accepted and will be applied when valid | |
13 | ||
14 | % Expr :: integer | |
15 | generate(prob_ast_int_expr(Options),Value) :- | |
16 | % double the chance of generating recursive expression | |
17 | % (i.e. add,minus,multiplication,div,unary_minus) to increase depth, | |
18 | % because modulo and power_of also just generate ground integer nodes for well-definedness | |
19 | random_member(Expr,[add,minus,multiplication,div,unary_minus, | |
20 | modulo,power_of,max,min,max_int,min_int, | |
21 | add,minus,multiplication,div,unary_minus]) , | |
22 | generate(prob_ast_int_expr(Expr,Options),Value). | |
23 | ||
24 | generate(prob_ast_int_expr(card,Options),b(card(Set),integer,[])) :- | |
25 | random_member(Type,[integer([]),string([]),boolean([])]) , | |
26 | (member(id,Options) | |
27 | -> generate(id_or_ast(set(Type)),Set) | |
28 | ; generate(prob_ast_set(Type,Options),Set)). | |
29 | ||
30 | % also generate empty list for no well-definedness | |
31 | generate(prob_ast_int_expr(Expr,Options),b(NewPred,integer,[])) :- | |
32 | memberchk(not-well-defined,Options) , | |
33 | !, | |
34 | member(Expr,[max,min]) , | |
35 | random(0,9,R) , | |
36 | (R > 3 | |
37 | -> generate(prob_ast_set(integer([small]),[extension|Options]),Set) | |
38 | ; generate(prob_ast_set(empty([]),Options),Set)) , | |
39 | NewPred =.. [Expr,Set]. | |
40 | generate(prob_ast_int_expr(Expr,Options),b(NewPred,integer,[])) :- | |
41 | member(Expr,[max,min]) , | |
42 | generate(prob_ast_set(integer([small]),[extension|Options]),Set) , % no expression | |
43 | NewPred =.. [Expr,Set]. | |
44 | ||
45 | generate(prob_ast_int_expr(Expr,_),b(Expr,integer,[])) :- | |
46 | member(Expr,[max_int,min_int]). | |
47 | ||
48 | generate(prob_ast_int_expr(Expr,Options),b(NewPred,integer,[])) :- | |
49 | member(Expr,[add,minus,multiplication]) , | |
50 | Type = integer([small,random|Options]) , | |
51 | generate_aux(Options,Type,Type,A,B) , | |
52 | NewPred =.. [Expr,A,B]. | |
53 | ||
54 | generate(prob_ast_int_expr(Expr,Options),b(NewPred,integer,[])) :- | |
55 | memberchk(not-well-defined,Options) , | |
56 | !, | |
57 | memberchk(Expr,[modulo,power_of,div]) , | |
58 | % generate expressions (not well defined for zero, negative values or float) | |
59 | TypeA = integer([small,random,not-well-defined|Options]) , | |
60 | TypeB = integer([small,not-well-defined|Options]) , | |
61 | generate_aux(Options,TypeA,TypeB,A,B) , | |
62 | NewPred =.. [Expr,A,B]. | |
63 | % use really small numbers to receive well-definedness for | |
64 | % integer expressions in predicates | |
65 | generate(prob_ast_int_expr(power_of,Options),b(NewPred,integer,[])) :- | |
66 | Type = integer([between(0,7)|Options]) , | |
67 | % disabled generation of identifier | |
68 | /*(member(id,Options) -> | |
69 | generate(id_or_ast(Type),A) , | |
70 | generate(id_or_ast(Type),B) | |
71 | ;*/ gen_type(Type,ast,NType) , | |
72 | generate(NType,A) , | |
73 | generate(NType,B), | |
74 | NewPred =.. [power_of,A,B]. | |
75 | generate(prob_ast_int_expr(modulo,Options),b(NewPred,integer,[])) :- | |
76 | TypeA = integer([small,positive|Options]) , | |
77 | TypeB = integer([small,positive,nozero|Options]) , | |
78 | generate_aux(Options,TypeA,TypeB,A,B) , | |
79 | NewPred =.. [modulo,A,B]. | |
80 | generate(prob_ast_int_expr(div,Options),b(div(A,B),integer,[])) :- | |
81 | TypeA = integer([small,random|Options]) , | |
82 | TypeB = integer([small,positive,nozero|Options]) , | |
83 | generate_aux(Options,TypeA,TypeB,A,B). | |
84 | ||
85 | generate(prob_ast_int_expr(unary_minus,Options),b(unary_minus(Expr),integer,[])) :- | |
86 | Type = integer([small,random|Options]) , | |
87 | (member(id,Options) | |
88 | -> generate(id_or_ast(Type),Expr) | |
89 | ; gen_type(Type,ast,NType) , | |
90 | generate(NType,Expr)). | |
91 | ||
92 | generate(prob_ast_int_expr(size),b(size(Seq),integer,[])) :- | |
93 | generate(ground_type,Type) , | |
94 | generate(prob_ast_seq(Type),Seq). | |
95 | ||
96 | % generate two nodes for given types and options | |
97 | generate_aux(Options,TypeA,TypeB,NodeA,NodeB) :- | |
98 | member(id,Options) , ! , | |
99 | generate(id_or_ast(TypeA),NodeA) , | |
100 | generate(id_or_ast(TypeB),NodeB). | |
101 | generate_aux(_,TypeA,TypeB,NodeA,NodeB) :- | |
102 | gen_type(TypeA,ast,NTypeA) , generate(NTypeA,NodeA) , | |
103 | gen_type(TypeB,ast,NTypeB) , generate(NTypeB,NodeB). | |
104 | ||
105 | shrink(Type,Expression,Shrunken) :- | |
106 | Type =.. [prob_ast_int_expr|_] , | |
107 | minimize_int_expr(Expression,Shrunken). | |
108 | shrink(Type,Expression,Shrunken) :- | |
109 | Type =.. [prob_ast_int_expr|_] , | |
110 | get_inner_expr(Expression,Shrunken). |