1 :- multifile generate/2.
2
3 % shrinking of all mutations defined in mutation.pl
4
5 :- use_module(library(lists),[is_list/1,maplist/2]).
6 :- use_module(library(random),[random_permutation/2,random_member/2,random/3]).
7 :- use_module(library(clpfd)).
8
9 % ProB ast integer expressions
10 generate(mutation(Expression:prob_ast_int_expr),NewExpression) :-
11 \+is_list(Expression) ,
12 random_int_expr_mutation(Expression,NewExpression).
13 % mutation of a list of integer expressions
14 generate(mutation(Expressions:prob_ast_int_expr),NewExpression) :-
15 % well-definedness problem with concatenation using div and modulo, division by zero
16 % power_of also deprecated because of integer overflow
17 concatenate_ast(Expressions,[add,minus,multiplication],Expression) ,
18 random_int_expr_mutation(Expression,NewExpression).
19
20 % randomly replaces ground integer ast nodes with a matching
21 % integer expression
22
23 % leaves
24 random_int_expr_mutation(Node,Mutation) :-
25 prob_is_ground(Node,Res) , Res = true ,
26 replace_ground_with_expr(Node,Mutation).
27
28 % two argument expressions
29 random_int_expr_mutation(b(Expression,integer,Info),b(NewExpression,integer,Info)) :-
30 Expression =.. [Type,Expr1,Expr2] ,
31 member(Type,[add,minus,multiplication,div,modulo,power_of]) ,
32 % random choice heuristic for argument
33 random(0,3,R) ,
34 % if expression is ground replace its value by an arithmetic expression
35 random_int_expr_mutation_aux(R,Expr1,Expr2,NewExpr1,NewExpr2) ,
36 NewExpression =.. [Type,NewExpr1,NewExpr2].
37 random_int_expr_mutation(b(Expression,integer,Info),b(NewExpression,integer,Info)) :-
38 Expression =.. [Type,Expr1,Expr2] ,
39 random_int_expr_mutation(Expr1,NewExpr1) ,
40 random_int_expr_mutation(Expr2,NewExpr2) ,
41 NewExpression =.. [Type,NewExpr1,NewExpr2].
42
43 % one argument expressions
44 random_int_expr_mutation(b(Expression,integer,Info),b(NewExpression,integer,Info)) :-
45 Expression =.. [Type,_] ,
46 \+member(Type,[max,min]) ,
47 (prob_is_ground(b(Expression,integer,Info),true)
48 -> replace_ground_with_expr(b(Expression,integer,Info),NewExpr)
49 ; random_int_expr_mutation(b(Expression,integer,Info),NewExpr)) ,
50 NewExpression =.. [Type,NewExpr].
51 % no mutation for max_int, min_int, max, min or identifier
52 random_int_expr_mutation(Expression,Expression).
53
54 % either mutate only one argument or both
55 random_int_expr_mutation_aux(0,Expr1,Expr2,NewExpr1,Expr2) :-
56 random_int_expr_mutation_aux2(Expr1,NewExpr1).
57 random_int_expr_mutation_aux(1,Expr1,Expr2,Expr1,NewExpr2) :-
58 random_int_expr_mutation_aux2(Expr2,NewExpr2).
59 random_int_expr_mutation_aux(2,Expr1,Expr2,NewExpr1,NewExpr2) :-
60 random_int_expr_mutation_aux2(Expr1,NewExpr1) ,
61 random_int_expr_mutation_aux2(Expr2,NewExpr2).
62 random_int_expr_mutation_aux2(Expr,NewExpr) :-
63 prob_is_ground(Expr,Res) , Res = true , ! ,
64 replace_ground_with_expr(Expr,NewExpr).
65 random_int_expr_mutation_aux2(Expr,NewExpr) :-
66 random_int_expr_mutation(Expr,NewExpr).
67
68 % replace ground value with an integer expression
69 replace_ground_with_expr(b(unary_minus(Integer),integer,[]),NewExpr) :-
70 replace_ground_with_expr(Integer,TempNewExpr) ,
71 NewExpr = b(multiplication(b(unary_minus(b(integer(1),integer,[])),integer,[]),TempNewExpr),integer,[]).
72 replace_ground_with_expr(b(integer(Value),integer,Info),NewExpr) :-
73 find_expr_clpfd(Value,Expr) , ! ,
74 % random choice of further mutation
75 random(0,10,R) ,
76 (R < 3
77 -> NewExpr = b(Expr,integer,Info)
78 ; random_int_expr_mutation(b(Expr,integer,Info),NewExpr)).
79
80 % evaluate an expression using clpfd labeling to mutate a specific value
81 find_expr_clpfd(Value,Expr) :-
82 Val1 in -100000..100000 ,
83 Val2 in -100000..100000 ,
84 random_member(Operator,[add,minus,multiplication]) , % power_of, modulo, div
85 find_expr_aux_operator(Operator,Val1,Val2,Value) ,
86 labeling([],[Val1,Val2]) ,
87 Expr =.. [Operator,b(integer(Val1),integer,[]),b(integer(Val2),integer,[])].
88 % if labeling failed try another expression
89 find_expr_clpfd(Value,Expr) :-
90 find_expr_clpfd(Value,Expr).
91
92 find_expr_aux_operator(add,Val1,Val2,Value) :-
93 Val1 + Val2 #= Value.
94 find_expr_aux_operator(minus,Val1,Val2,Value) :-
95 Val1 - Val2 #= Value.
96 find_expr_aux_operator(div,Val1,Val2,Value) :-
97 Val2 #\= 0 ,
98 Val1 div Val2 #= Value.
99 find_expr_aux_operator(modulo,Val1,Val2,Value) :-
100 Val1 in 1..100000 ,
101 Val2 in 1..100000 , % no negative numbers
102 Val1 mod Val2 #= Value.
103 find_expr_aux_operator(_,Val1,Val2,Value) :-
104 Val1 * Val2 #= Value.