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