% FILE: crypto.pro of crypto_hps % TYPE: Prolog source % LINE: The heuristic crypto problem solver % DATE: Fall 2019 % ----------------------------------------------------------------------------------------------- % LOAD FILES :- consult('../combinatorial_sets/combinatorial_sets.pro'). :- consult('../crypto_problems.pro'). :- consult('../lp.pro'). % ----------------------------------------------------------------------------------------------- % SOME SIMPLE "LOWER LEVEL" RECOGNITION UTILITIES same(A,A). not_same(A,B) :- A \= B. adjacent(A,B) :- A is B+1. adjacent(A,B) :- A is B-1. adjacent_two(A,B) :- A is B+2. adjacent_two(A,B) :- A is B-2. subtr(A,B,A1) :- A1 is A-B. div(A,B,A1) :- A1 is A/B. % ----------------------------------------------------------------------------------------------- % SOME SIMPLE "LOWER LEVEL" ACTION UTILITIES multiply([A,B],ex(A,*,B)). multiply([H|T],ex(H,*,R)) :- multiply(T,R). subtract([A,B],ex(A,-,B)). subtract([H|T],ex(H,-,R)) :- subtract(T,R). % ----------------------------------------------------------------------------------------------- % SOME SIMPLE "HIGHER LEVEL" CRYPTO PROBLEM SOLVING PREDICATES goal_is_zero :- value_of(crypto_problem,problem(_,goal(0))). goal_is_one :- value_of(crypto_problem,problem(_,goal(1))). goal_is_two :- value_of(crypto_problem,problem(_,goal(2))). goal_is_three :- value_of(crypto_problem,problem(_,goal(3))). goal_is_four :- value_of(crypto_problem,problem(_,goal(4))). goal_is_nonzero :- value_of(crypto_problem,problem(_,goal(G))), G \= 0. zero_in_numbers :- value_of(crypto_problem,problem(numbers(N1,N2,N3,N4,N5),_)), contains([N1,N2,N3,N4,N5],0). goal_in_numbers :- value_of(crypto_problem,problem(numbers(N1,N2,N3,N4,N5),goal(G))), contains([N1,N2,N3,N4,N5],G). pair_in_numbers :- value_of(crypto_problem,problem(numbers(N1,N2,N3,N4,N5),_)), comb(set(N1,N2,N3,N4,N5),comb(A,B),_), same(A,B). pair_in_numbers(value(V),rest(C,D,E)) :- value_of(crypto_problem,problem(numbers(N1,N2,N3,N4,N5),_)), comb(set(N1,N2,N3,N4,N5),comb(A,B),extras(C,D,E)), same(A,B), V = A. no_pair_in_numbers :- value_of(crypto_problem,problem(numbers(N1,N2,N3,N4,N5),_)), comb(set(N1,N2,N3,N4,N5),comb(A,B),_), not_same(A,B). no_pair_in_numbers(value(V,V1),rest(C,D,E)) :- value_of(crypto_problem,problem(numbers(N1,N2,N3,N4,N5),_)), comb(set(N1,N2,N3,N4,N5),comb(A,B),extras(C,D,E)), not_same(A,B), V = A, V1 = B. adj_pair_in_numbers :- value_of(crypto_problem,problem(numbers(N1,N2,N3,N4,N5),_)), comb(set(N1,N2,N3,N4,N5),comb(A,B),_), adjacent(A,B). adj_pair_in_numbers(value(V,V1),rest(C,D,E)) :- value_of(crypto_problem,problem(numbers(N1,N2,N3,N4,N5),_)), comb(set(N1,N2,N3,N4,N5),comb(A,B),extras(C,D,E)), adjacent(A,B), V = A, V1 = B. adj_two_pair_in_numbers :- value_of(crypto_problem,problem(numbers(N1,N2,N3,N4,N5),_)), comb(set(N1,N2,N3,N4,N5),comb(A,B),_), adjacent(A,B). adj_two_pair_in_numbers(value(V,V1),rest(C,D,E)) :- value_of(crypto_problem,problem(numbers(N1,N2,N3,N4,N5),_)), comb(set(N1,N2,N3,N4,N5),comb(A,B),extras(C,D,E)), adjacent_two(A,B), V = A, V1 = B. two_in_numbers :- value_of(crypto_problem,problem(numbers(N1,N2,N3,N4,N5),_)), contains([N1,N2,N3,N4,N5],2). goal_div_two_in_numbers :- value_of(crypto_problem,problem(numbers(N1,N2,N3,N4,N5),goal(G))), div(G,2,G1), contains([N1,N2,N3,N4,N5],G1). one_in_numbers :- value_of(crypto_problem,problem(numbers(N1,N2,N3,N4,N5),_)), contains([N1,N2,N3,N4,N5],1). goal_min_one_in_numbers :- value_of(crypto_problem,problem(numbers(N1,N2,N3,N4,N5),goal(G))), subtr(G,1,G1), contains([N1,N2,N3,N4,N5],G1). goal_min_two_in_numbers :- value_of(crypto_problem,problem(numbers(N1,N2,N3,N4,N5),goal(G))), subtr(G,2,G1), contains([N1,N2,N3,N4,N5],G1). numbers(N1,N2,N3,N4,N5) :- value_of(crypto_problem,problem(numbers(N1,N2,N3,N4,N5),_)). goal(G) :- value_of(crypto_problem,problem(_,goal(G))). numbers_other_than(these(A1,A2),those(B1,B2,B3)) :- numbers(N1,N2,N3,N4,N5), remove_elements([A1,A2],[N1,N2,N3,N4,N5],[B1,B2,B3]). sm_numbers_other_than(these(A1),those(B1,B2)) :- numbers(N1,N2,N3,_,_), remove_elements([A1],[N1,N2,N3],[B1,B2]). % ----------------------------------------------------------------------------------------------- % MORE LIST PROCESSORS remove_elements([],List,List). remove_elements([H|T],List,Reduced_List) :- member(H,List), remove(H,List,Partial_List), remove_elements(T,Partial_List,Reduced_List). remove_elements([_|T],List,Reduced_List) :- remove_elements(T,List,Reduced_List). % ----------------------------------------------------------------------------------------------- % CRYPTO HEURISTIC 1 situation1 :- goal_is_zero, zero_in_numbers. action1 :- numbers(N1,N2,N3,N4,N5), multiply([N1,N2,N3,N4,N5],Expression), add_solution_to_KB(Expression). % ----------------------------------------------------------------------------------------------- % CRYPTO HEURISTIC 2 situation2 :- goal_is_zero, pair_in_numbers. action2 :- pair_in_numbers(value(V),rest(C,D,E)), subtract([V,V],X1), multiply([0,C,D,E],X2), substitute(X1, 0, X2, Expression), add_solution_to_KB(Expression). % ----------------------------------------------------------------------------------------------- % CRYPTO HEURISTIC 3 situation3 :- goal_is_nonzero, goal_in_numbers, zero_in_numbers. action3 :- goal(G), numbers_other_than(these(0,G),those(A,B,C)), multiply([0,A,B,C],Zero_valued_expression), Expression = ex(G,+,Zero_valued_expression), add_solution_to_KB(Expression). % ----------------------------------------------------------------------------------------------- % CRYPTO HEURISTIC 3 situation4 :- goal_is_two, adj_two_pair_in_numbers, zero_in_numbers. action4 :- adj_two_pair_in_numbers(value(W,W1),rest(F,G,H)), max_pair(W,W1,Max), min_pair(W,W1,Min), subtract([Max,Min], Diff), multiply([F,G,H],Prod), Expression = ex(Diff,+,Prod), add_solution_to_KB(Expression). % ----------------------------------------------------------------------------------------------- % CRYPTO HEURISTIC 5 situation5 :- goal_is_one, pair_in_numbers, adj_pair_in_numbers. action5 :- pair_in_numbers(value(W),rest(F,G,H)), subtract([W,W],X2), max_pair(G,H,Max), min_pair(G,H,Min), subtract([Max,Min],Diff), multiply([F,X2],Prod), Expression = ex(Diff,+,Prod), add_solution_to_KB(Expression). % ----------------------------------------------------------------------------------------------- % CRYPTO HEURISTIC 6 situation6 :- adj_pair_in_numbers, no_pair_in_numbers, goal_is_two, adj_two_pair_in_numbers, one_in_numbers. action6 :- adj_pair_in_numbers(value(W,W1),rest(F,G,H)), max_pair(W,W1,Max), min_pair(W,W1,Min), subtract([Max,Min],X2), multiply([F,X2], X4), max_pair(G,H,Max1), min_pair(G,H,Min1), subtract([Max1,Min1],X5), Expression = ex(X5,*,X4), add_solution_to_KB(Expression). % ----------------------------------------------------------------------------------------------- % CRYPTO HEURISTIC 7 situation7 :- goal_is_three, adj_two_pair_in_numbers, one_in_numbers, zero_in_numbers. action7 :- adj_two_pair_in_numbers(value(W,W1),rest(F,G,H)), max_pair(W,W1,Max), min_pair(W,W1,Min), subtract([Max,Min],Diff), multiply([G,H],Prod), subtract([F,Prod],Diff1), Expression = ex(Diff,+,Diff1), add_solution_to_KB(Expression). % ----------------------------------------------------------------------------------------------- % CRYPTO HEURISTIC 8 situation8 :- goal_is_four, adj_two_pair_in_numbers, two_in_numbers, zero_in_numbers. action8 :- adj_two_pair_in_numbers(value(W,W1),rest(F,G,H)), max_pair(W,W1,Max), min_pair(W,W1,Min), subtract([Max,Min],Diff), multiply([G,H],Prod), subtract([F,Prod],Diff1), Expression = ex(Diff,+,Diff1), add_solution_to_KB(Expression). % ----------------------------------------------------------------------------------------------- % THE RULE BASE rule(1,situation1,action1). rule(2,situation2,action2). rule(3,situation3,action3). rule(4,situation4,action4). rule(5,situation5,action5). rule(6,situation6,action6). rule(7,situation7,action7). rule(8,situation8,action8). % ----------------------------------------------------------------------------------------------- % SOLVE AN INTERNALIZED PROBLEM (IT MAY HAVE BEEN RANDOMLY GENERATED OR SPECIFICALLY ESTABLISHED) % HEURISTICALLY, PLACING ITS SOLUTION IN THE KB. solve_problem_heuristically :- rule(Number,Situation,Action), write('considering rule '),write(Number),write(' ...'),nl, Situation, write('application of rule '),write(Number), Action. solve_problem_heuristically :- add_solution_to_KB(none). add_solution_to_KB(Expression) :- undeclare(solution), declare(solution,solution(Expression)). add_solution_to_KB(Expression) :- declare(solution,solution(Expression)). % ----------------------------------------------------------------------------------------------- % DISPLAY THE SOLUTION -- ASSUMING THAT THE PROBLEM HAS BEEN SOLVED display_solution :- value_of(solution,solution(none)), write('No SOLUTION found with this rule base.'),nl. display_solution :- value_of(solution,solution(Expression)), write(' produces solution: '),display_result(Expression),nl. display_solution. display_result(ex(A,O,B)) :- number(A), number(B), write('( '), write(A), write(' '), write(O), write(' '), write(B),write(' )'). display_result(ex(A,O,B)) :- number(A), B=ex(A1,O1,B1), write('( '),write(A),write(' '),write(O),write(' '), display_result(ex(A1,O1,B1)),write(' )'). display_result(ex(A,O,B)) :- number(B), A=ex(A1,O1,B1), write('( '),display_result(ex(A1,O1,B1)),write(' '),write(O),write(' '), write(B),write(' )'). display_result(ex(A,O,B)) :- A=ex(A1,O1,B1), B=ex(A2,O2,B2), write('( '),display_result(ex(A1,O1,B1)),write(' '),write(O),write(' '), display_result(ex(A2,O2,B2)),write(' )'). % ----------------------------------------------------------------------------------------------- % SUBSTITUTION CODE substitute(New,Old,ex(Old,O,Z),ex(New,O,Z)). substitute(New,Old,ex(X,O,Old),ex(X,O,New)). substitute(New,Old,ex(X,O,Z),ex(Y,O,Z)) :- substitute(New,Old,X,Y). substitute(New,Old,ex(X,O,Z),ex(X,O,Y)) :- substitute(New,Old,Z,Y). % ------------------------------------------------------------------- % CRYPTO PROBLEM SOLVER -- SOLVE A RANDOM PROBLEM solve_one :- generate_random_crypto_problem, display_problem, solve_problem_heuristically, display_solution. % ------------------------------------------------------------------- % CRYPTO PROBLEM SOLVER -- SOLVE A SPECIFIC PROBLEM solve(problem(numbers(N1,N2,N3,N4,N5),goal(G))) :- add_crypto_problem_to_KB(N1,N2,N3,N4,N5,G), % from crypto_problems display_problem, solve_problem_heuristically, display_solution. % ------------------------------------------------------------------- % RANDOM CRYPTO PROBLEM SOLVING demo(1) :- solve_one. demo(N) :- demo(1), M is N-1, demo(M).