%%% SICStus Prolog Code for Protein Folding Prediction %%% in CLP(FD) according to WFLP'02 paper. %%% Last Modifications: September, 10th, 2002 by Agostino Dovier %%% Partial solutions are printed during execution :-use_module(library(clpfd)). :-use_module(library(lists)). :-consult('data.pl'). %%% (MAIN) PREDICATE: fcc_pf %%% INPUT: ID, the code of the protein according to names in file data.pl %%% OUTPUT: the minimum Energy associated to the conformation %%% represented (and printed) by Tertiary_flat %%% EXAMPLE: fcc_pf('1ed0', Energy). %%% NOTE: "protein" is defined in data.pl fcc_pf( ID, Energy):- clean, %%% remove garbage if any protein(ID, Primary, Secondary), initial_time, constrain(Primary, Secondary, Indexes, Tertiary_flat, Energy,_), %%% Debugging command: writetime('Constraint time: '),nl,!, local_labeling(Primary, Secondary, Indexes, Tertiary_flat), writetime('Global time: '),nl,!, stampa(Primary,Tertiary_flat). %%% Formatted write of the result %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% CONSTRAINT DEFINITION PART %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% PREDICATE: constrain %%% INPUT: Primary, Secondary %%% Output: The lists Indexes, Tertiary, %%% the constrained value Energy, %%% the list Pot_list of contact contribution to energy, and %%% a series of constraints on the variables constrain(Primary, Secondary, Indexes, Tertiary_flat, Energy, ListaPot):- generate_tertiary(N, Primary, Tertiary, Tertiary_flat), domain_bounds(N, Tertiary), avoid_symmetries(N, Tertiary), avoid_self_loops(Tertiary), next_constraints(Tertiary), distance_constraints(Tertiary), generate_indexes(N, Indexes), secondary_info(Secondary, Indexes, Tertiary), indexes_to_coordinates(Indexes, Tertiary), energy_constraints(Primary, Tertiary, Energy, ListaPot). %%% PREDICATE: generate_tertiary %%% INPUT: N, a number greater than or equal to 0, %%% Primary, a list of aminoacids %%% OUTPUT: a list of N variables' triples to be used as %%% coordinates %%% and also its flat version, good for labeling generate_tertiary(N,[T|Aminoacids],[[X,Y,Z]|Rest],[X,Y,Z|Sest]):- aminoacid(T), generate_tertiary(M, Aminoacids, Rest,Sest), N is M + 1. generate_tertiary(0,[],[],[]). %%% PREDICATE: domain_bounds %%% INPUT: N, a number greater than or equal to 0, %%% Tertiary, the list of variables' triples %%% EFFECT: adding FD constraints to those variables %%% in order they keep value in 2*n fcc domain_bounds(_N, []). domain_bounds(N, [P1|Rest]) :- CUBESIZE is N * 2, domain(P1,0,CUBESIZE), sum(P1, #=, Sum), even(Sum), domain_bounds(N, Rest). %%% PREDICATE: domain_bounds %%% INPUT: N, a number greater than or equal to 0, %%% Tertiary, the list of variables' triples %%% EFFECT: adding FD constraints to those variables %%% in order to avoid trivial symmetries avoid_symmetries(0,[]). avoid_symmetries(1,_). avoid_symmetries(Length,[[Length,Length,Length],[M,M,Length]|_]):- even(Length), M #= Length+1. avoid_symmetries(Length,[[N,N,N],[M,M,N]|_]):- odd(Length), N #= Length + 1, M #= N+1. %%% PREDICATE: avoid_self_loops (aux.: positions_to_integers) %%% INPUT: Tertiary, the list of variables' triples %%% EFFECT: adding FD constraints to those variables %%% in order to avoid equal triples avoid_self_loops(Tertiary):- positions_to_integers(Tertiary, ListaInteri), all_different(ListaInteri). positions_to_integers([[X,Y,Z]|R],[I|S]):- I #= X*10000+Y*100+Z, %%% weigthed sum !!! positions_to_integers( R , S). positions_to_integers([],[]). %%% PREDICATE: next_constraints (aux.: next) %%% INPUT: Tertiary, the list of variables' triples %%% EFFECT: adding FD constraints to those variables %%% in order to set that the triples are consecutive next_constraints([]). next_constraints([_]). next_constraints([A,B|C]) :- next(A,B), next_constraints([B|C]). next([X_i,Y_i,Z_i],[X_si,Y_si,Z_si]):- DX in 0..1, DY in 0..1, DZ in 0..1, DX #= abs(X_i - X_si), DY #= abs(Y_i - Y_si), DZ #= abs(Z_i - Z_si), DX + DY + DZ #= 2. %%% PREDICATE: distance_constraints (aux.: distance, non_next) %%% INPUT: Tertiary, the list of variables' triples %%% EFFECT: adding FD constraints to those variables %%% in order to set that non consecutive triples %%% has lattice distance greater than 1. %%% NOTE: It introduces an explicit disjunction distance_constraints([_]). distance_constraints([P1,P2|R]):- distance(P1,R), distance_constraints([P2|R]). distance(_,[]). distance(P1,[P2|R]):- non_next(P1,P2), distance(P1,R). non_next([X_i,Y_i,Z_i],[X_j,Y_j,Z_j]):- %%% j > i + 1 !!! DX #= abs(X_i - X_j), DY #= abs(Y_i - Y_j), DZ #= abs(Z_i - Z_j), DX #> 1 #\/ DY #> 1 #\/ DZ #> 1 #\/ DX + DY + DZ #> 2. %%% PREDICATE: generate_indexes %%% INPUT: N, a number greater than or equal to 0, %%% OUTPUT: a list of N-2 variables as \theta-indexes generate_indexes(N, Indexes):- M is N-2, length(Indexes,M), domain(Indexes,1,6). %%% PREDICATE: secondary_info %%% INPUT: The list Secondary, %%% The list Indexes, %%% The list Tertiary %%% EFFECT: Adding constraints to the variables in Indexes and Tertiary %%% according to the information in Secondary %%% NOTE: helix(1,..) or strand(1,..) are not allowed!!! %%% We do not add +1 because in this way we leave free %%% the beginning and the ending of a chain/strand %%% Case 1: ssbond secondary_info([ssbond(A1,A2)|SecRest], Indexes, Tertiary):- !, nth(A1,Tertiary,PA1), nth(A2,Tertiary,PA2), ssbond(PA1,PA2), secondary_info(SecRest, Indexes, Tertiary). %%% Case 2: helix secondary_info([helix(Start,End)|SecRest], Indexes, Tertiary):- !, S is Start - 1, Helix_length #= End - Start, % We do not add + 1 sublist(S, Helix_length, Indexes, Subindexes), helix(Subindexes), secondary_info(SecRest,Indexes,Tertiary). %%% Case 3: strand secondary_info([strand(Start,End)|SecRest], Indexes, Tertiary):- !, S is Start - 1, Strand_length #= End - Start, % We do not add + 1 sublist(S, Strand_length, Indexes, Subindexes), strand(Subindexes), secondary_info(SecRest,Indexes, Tertiary). %%% Empty list secondary_info([], _, _). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% AUXILIARY PREDICATES FOR SECONDARY STRUCTURE CONSTRAINTS: %%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% PREDICATE: helix (aux. prefix, built-in) %%% INPUT: A sublist of Indexes, %%% EFFECT: Adding constraints to the variables involved in the sublist helix([1,3,4,6, X | Indexes]):- !, helix([ X | Indexes]). helix(Indexes):- prefix(Indexes, [1,3,4,6]). %%% PREDICATE: strand (aux. prefix, built-in) %%% INPUT: A sublist of Indexes, %%% EFFECT: Adding constraints to the variables involved in the sublist strand([2,3, X |Indexes]):- !, strand([X|Indexes]). strand(Indexes):- prefix(Indexes, [2,3]). %%% PREDICATE: ssbond %%% INPUT: Two triples of variables %%% EFFECT: Adding a "contact" constraint to the variables involved %%% in the sublist ssbond([X1,Y1,Z1],[X2,Y2,Z2]):- abs(X1-X2) + abs(Y1-Y2) + abs(Z1-Z2) #=< 6. %%% PREDICATE: indexes_to_coordinates %%% (aux. indexes_to_directions, directions_to_coordinates, %%% vector_sum) %%% INPUT: The list of Indexes %%% The list of variables's triples Tertiary %%% EFFECT: Relates the \theta-constraints on Indexes to the %%% coordinates variables in Tertiary indexes_to_coordinates(Indexes, Tertiary):- directions_to_coordinates([D0|Directions], Tertiary), indexes_to_directions(Indexes, [D0|Directions]). directions_to_coordinates([], [_] ). directions_to_coordinates([D1 | Directions],[X1,X2|Coordinate]):- vector_sum(D1, X1, X2), directions_to_coordinates(Directions,[X2|Coordinate]). indexes_to_directions([],[_]). indexes_to_directions([I1|Indexes],[D0,D1|Directions]):- new_direction(D0,I1,D1), indexes_to_directions(Indexes,[D1|Directions]). %%% PREDICATE: new_direction (aux. t1,t2,t3, vector_ops) %%% INPUT: An index,The list of Indexes %%% The list of variables's triples Tertiary %%% EFFECT: Moving the \theta-constraints on Indexes to the %%% coordinates variables in Tertiary new_direction(R12, I, [R23x,R23y,R23z]):- t1(R12, T1), t2(R12, T2), t3(R12, T3), vector_product(R12,T1,[R23_1x,R23_1y,R23_1z]), vector_sum(T1,T2,[R23_2x,R23_2y,R23_2z]), vector_sum(T1,T3,[R23_3x,R23_3y,R23_3z]), vector_minus(R12,MenoR12), vector_product(MenoR12,T1,[R23_4x,R23_4y,R23_4z]), vector_sum(T1,[R23_5x,R23_5y,R23_5z],T3), vector_sum(T1,[R23_6x,R23_6y,R23_6z],T2), I #= 1 #<=> (R23x #= R23_1x #/\ R23y #= R23_1y #/\ R23z #= R23_1z), I #= 2 #<=> (R23x #= R23_2x #/\ R23y #= R23_2y #/\ R23z #= R23_2z), I #= 3 #<=> (R23x #= R23_3x #/\ R23y #= R23_3y #/\ R23z #= R23_3z), I #= 4 #<=> (R23x #= R23_4x #/\ R23y #= R23_4y #/\ R23z #= R23_4z), I #= 5 #<=> (R23x #= R23_5x #/\ R23y #= R23_5y #/\ R23z #= R23_5z), I #= 6 #<=> (R23x #= R23_6x #/\ R23y #= R23_6y #/\ R23z #= R23_6z). %%% PREDICATE: energy_constraints %%% INPUT: The Primary list of aminoacids, %%% The Tertiary list of triples, %%% OUTPUT: Computes in Energy (as a constraint!) %%% the value of energy associated to a spatial %%% conformation and the list of potentials energy_constraints(Primary, Tertiary, Energy, Potential_list):- potential_list(Primary, Tertiary, Potential_list), sum(Potential_list,#=,Energy). %%% PREDICATE: potential_list (aux. list_pot_amino, table) %%% INPUT: The Primary list of aminoacids, %%% The Tertiary list of triples, %%% OUTPUT: The list Potential_list of variables associated to each possible %%% potential (due to a contact) to be computed in Energy (as a constraint!) %%% the value of energy associated to a spatial %%% conformation potential_list([_],[_],[]). potential_list([Ami1,Ami2|ListaAmin],[Pos1,Pos2|ListaPos],Pot_list_output):- list_pot_amino(Ami1,Pos1,ListaAmin,ListaPos,L), potential_list([Ami2|ListaAmin], [Pos2|ListaPos], ListaPot), append(L,ListaPot,Pot_list_output). list_pot_amino(_Amino,_Posizione,[],[],[]). list_pot_amino(Amino,[X1,Y1,Z1],[Amino2|ListaAmin],[[X2,Y2,Z2]|ListaPos],[C|L]):- table(Amino, Amino2, Pot), C in {0,Pot}, DX #= abs(X1 - X2), DY #= abs(Y1 - Y2), DZ #= abs(Z1 - Z2), 2 #= DX + DY + DZ #<=> C #= Pot, %%% CONTACT CONTRIBUTION list_pot_amino(Amino,[X1,Y1,Z1],ListaAmin,ListaPos,L). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% END OF CONSTRAINT DEFINITION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% LABELING PHASE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% PREDICATE: local_labeling %%% INPUT: The list Primary of aminoacids, The list of Secondary %%% structure Information, The list of Indexes, %%% The flat list Tertiary_flat of coordinates %%% OUTPUT: The ground values for Tertiary variables! %%% NOTE: If Indexes are all known, perform an immediate standard labeling. %%% Otherwise, look at Indexes, which is a sequence of alternations: %%% [(V1),G1,V2,G2,...] of variables and ground values. %%% Find the "best" sublist [G1,V2,G2] (or [V1,G1], or [Gn,Vn]) %%% The best is that having |G1|+|V2|+|G2| - 2 * |V2| bigger %%% (i.e. less variables than constant part). %%% Perform the labeling on that sublist!!!! local_labeling(_Primary, _Secondary, Indexes, Tertiary_flat ):- ground( Indexes ), ! , labeling([], Tertiary_flat). %%% Base case: Built-in labeling local_labeling(Primary, Secondary, Indexes, Tertiary_flat ):- choose_subindexes(Indexes, S, L), %%% Debugging: write('local labeling: starting point and substring length:'), write(S), write(' , '), write(L),nl, %%% L_prim is L + 2, local_ssbond(Secondary, S, L, Sec), sublist(S,L,Indexes,SubIndexes), sublist(S,L_prim,Primary,SubPri), constrain(SubPri, Sec, SubIndexes, _SubTertiary, Energy, ListaPot), choose_labeling( SubIndexes, Energy, ListaPot), local_labeling(Primary, Secondary, Indexes, Tertiary_flat ). %%% PREDICATE: choose_subindexes (aux. admissible_sub, best_sub) %%% INPUT: The list of Indexes, %%% OUTPUT: Two indexes Start and Length (starting point and %%% length of the sum of variables and non variables (2 alternations) %%% at the beginning choose_subindexes(Indexes, Start, Length):- admissible_sub(Indexes, 1, ListaPoss), best_sub(ListaPoss, Start, Length ). %%% PREDICATE: choose_labeling %%% INPUT: The Sublist of the Indexes and the Energy, %%% OUTPUT: The List of partial potentials, and the associated Energy %%% NOTE: If the number of vars is little, use built-in labeling. %%% Otherwise, use labeling_new (with Heuristics). choose_labeling( SubIndexes, Energy,_):- %%% (1): built-in numero_var(SubIndexes, Nvars), length(SubIndexes, Sublength), %%% Test: (values can be changed) Nvars < 6, Sublength < 20,!, labeling([ff,minimize(Energy)], SubIndexes) %%% Debugging ,writetime('### built-in labeling time and value: '), write(Energy),nl. choose_labeling( SubIndexes, Energy, ListaPot):- %%% (2): ad hoc (with heuristics) assert( best_solution(100000) ), length(SubIndexes,To_do), minimum_domain(ff, Min,SubIndexes, OtherVars), %% ff or leftmost minimize(( labeling_new(To_do, 0, 1, [Min|OtherVars],Energy, ListaPot) %%% Debugging ,writetime('### ad-hoc labeling time and value: '), write(Energy),nl ), Energy ), retract(best_solution(_)). %%% PREDICATE: labeling_new %%% INPUT: In the call to minimum_domain %%% "ff" first-fail, "leftmost" leftmost strategy %%% To be better explained %%% A first-fail or leftmost, self-programmed strategy: %%% (5 is the number of variables to be instantiated before %%% the next heuristic control) labeling_new( To_do, Done, MOD, [ A | R], Energy, ListaPot) :- Done < To_do, ground(A), Now_Done is Done + 1, labeling_new(To_do, Now_Done, MOD, R, Energy, ListaPot). labeling_new( To_do, Done, MOD, [ A | R], Energy, ListaPot) :- Done < To_do, MOD < 5, var(A), Now_Done is Done + 1, MOD1 is MOD + 1, minimum_domain(ff, Min, [ A | R], OtherVars), %% ff or leftmost indomain(Min), labeling_new(To_do, Now_Done, MOD1, OtherVars, Energy, ListaPot). labeling_new( To_do, Done, 5, [ A | R], Energy, ListaPot) :- Done < To_do, var(A), best_solution(Val), Now_Done is Done + 1, %%% Xi = 0.3 S1 is integer( 0.3 * Val * (Now_Done /To_do) ), %%% Eta = 1.1 S2 is integer( 1.1 * Val * (Now_Done /To_do) ), minimum_domain(ff, Min, [ A | R], OtherVars), %% ff or leftmost indomain(Min), %%% STRONG heuristic for pruning the search tree %%% To be used with Xi <= 0.3: sumgrounds( ListaPot, Valint ), Valint #< S1, %%% Additional "constraint-based" Heuristics. Less effective! %%% To be used with Eta <= 1.2: Energy #< S2, labeling_new(To_do, Now_Done, 1, OtherVars, Energy, ListaPot). labeling_new( Done, Done, _, [] , Energy,_) :- best_solution( Val ), ( Energy < Val, !, retract( best_solution(Val)), assert( best_solution(Energy)); true). %%%% PREDICATE: minimum_domain(Options,A, VarList, OrderedList). %%%% (aux. all_domain_size,remove_key; built.in: keysort,fd_size) %%%%%INPUT: The list VarList of finite domain variables %%%%%OUTPUT: One of the variable (A) with smaller domain, and %%%%% the list of the other variables, ordered %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% minimum_domain(ff,A,VarList,SortedVarList) :- all_domain_size(VarList,DomainSizeList), keysort(DomainSizeList,DomainSizeListSorted), remove_key([A|SortedVarList],DomainSizeListSorted). minimum_domain(leftmost,A,[A|R], R). %%% Note: keysort sorts lists of pairs Key-Value all_domain_size([],[]). all_domain_size([A|R],[SizeDomA-A|S]) :- fd_size(A,SizeDomA), all_domain_size(R,S). remove_key([],[]). remove_key([A|R],[_-A|S]) :- remove_key(R,S). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% AUXILIARY PREDICATES FOR THE LABELING PHASE %%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% PREDICATE: local_ssbond %%% INPUT: The list of Secondary Structure, The starting point Sn, the length Ln %%% OUTPUT: A new list of SSBONDS, parametric w.r.t. the sublist involved %%% NOTE: Currently, it works only if the ssbonds are put first in data.pl!!! local_ssbond([ssbond(A,B)|Rest], Sn, Ln, [ssbond(C,D)|Sec]):- %%% assumed that A < B A >= Sn, B =< Sn + Ln + 1, !, C is A - Sn + 1, D is B - Sn + 1, local_ssbond(Rest, Sn, Ln, Sec). local_ssbond([ssbond(_,_) | Rest], Sn, Ln, Sec):- !, local_ssbond(Rest, Sn, Ln, Sec). local_ssbond(_, _, _, []). %%% PREDICATE: admissible_sub %%% INPUT: The list of Indexes, a number i %%% OUTPUT: A list of triples: [Starting index, %%% #vars in the sublist + #non vars in the sublist, %%% #vars in the sublist ] %%% Note: very compact code to avoid multiple calls of %%% auxiliary procedure %%% Nuova quintupla: con una struttura [c,X,d,y,e] fornisco le %%% cinque lunghezze. admissible_sub(Indexes, 1, [[1, [0,Nvars,L2,0,0], Length, Nvars]|ListaPoss]):- vars(Indexes, Nvars, R1 ), Nvars > 0, !, (%%Case 1: [ Vars ] R1 = [], !, ListaPoss = [], Length = Nvars, L2 = 0; %%Case 2: [ Vars, Grounds | ...] grounds(R1, L2, _), Length is L2 + Nvars, NextStart is Nvars + 1, admissible_sub(R1, NextStart, ListaPoss)). admissible_sub(Indexes, Start, [[Start,[L1,Nvars1,L2,Nvars2,L3],Length, Nvars]| ListaPoss]):- grounds(Indexes, L1, R1), vars(R1,Nvars1,R2), Nvars1 > 0, !, grounds(R2,L2,R3), vars(R3,Nvars2,R4), grounds(R4,L3,R5), (%%% Case 4: [ Grounds , Vars ] R2 = [], !, ListaPoss = [], Nvars = Nvars1, Length is Nvars + L1; %%% Case 5: [ Ground , Vars , Ground] R3 = [], !, ListaPoss = [], Nvars = Nvars1, Length is Nvars1 + L1 + L2; %%% Case6: [ Grounds , Vars , Grounds , Vars ] R4 = [], !, ListaPoss = [], Nvars is Nvars1 + Nvars2, Length is L1 + Nvars1 + L2 + Nvars2; %%% Case7: [ Grounds , Vars , Ground , Vars , Ground ] R5 = [], !, ListaPoss = [], Length is L1 + Nvars1 + L2 + Nvars2 + L3, Nvars is Nvars1 + Nvars2; %%%% Case8: [ Grounds , Vars , Ground , Vars , Ground | ...] Length is L1 + Nvars1 + L2 + Nvars2 + L3, Nvars is Nvars1 + Nvars2, NewStart is Start + L1 + Nvars1, admissible_sub(R3,NewStart,ListaPoss)). %%% Case 3: Indexes = [ Ground ] admissible_sub(_, _, []). %%%%%%%%%%% NOTE:further cases can be analyzed to optimize!!!! %%% PREDICATE: best_sub/3 (aux. best_subaux/3) %%% INPUT: A list of triples: [Starting index, L , Nvar ] %%% identifying sublists [G1,V1,G2,V2,G3] where %%% L = |G1|+|V1|+|G2|+ |V2| + |G3|, Nvar = |V1| + |V2|. %%% generated by admissible_sub %%% OUTPUT: The best tuple (the last value is changed, %%% for optimization) %%% NOTE: We maximize L - 2 * Nvar %%% We use best_sub/3 for optimizing %%% If more than 10 variables are in the selected sublist, %%% we cut it, using possible_cut best_sub(List, Start, Length ) :- best_subaux(List, [_,_,_,-1000],Tuple), possible_cut(Tuple, Start, Length). best_subaux([ [Start,Q,L,Nvar] | R], [_,_,_,Pbest],Triple) :- P1 is L - 2*Nvar, P1 > Pbest,!, best_subaux( R , [Start, Q, L, P1] ,Triple). best_subaux([ [_,_,_,_] | R],[StartBest, Qbest,Lbest,NvarBest],Triple) :- best_subaux( R , [StartBest, Qbest,Lbest,NvarBest] ,Triple). best_subaux([] , BestTriple,BestTriple). possible_cut([Start,[_C1,V1,_C2,V2,_C3],L,_], Start, L) :- V1 + V2 #=< 10, !. possible_cut([Start,[C1,V1,C2,_V2,_C3],_,_], Start, L) :- V1 #=< 10,!, L is C1 + V1 + C2, write('### weak sublist cut'),nl. possible_cut([Start,[C1,_V1,_C2,_V2,_C3],_,_], Start, L) :- L is C1 + 10, write('### hard sublist cut'),nl. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% AUXILIARY (TECHNICAL AND EASY) PREDICATES %%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% numero_var(t) returns the number of non ground %%% elements of the list t numero_var([C|X],N):- ground(C), numero_var(X,N). numero_var([X|Y],N):- var(X), numero_var(Y,M), N is M + 1. numero_var([],0). %%% vars([A,B,C,a,b], X , Y ) %%% returns X = 3 (number of vars at the beginning) and %%% Y = [a,b] (the list bust the first initial vars) vars([],0,[]). vars([X|Y], 0, [X|Y]):- ground(X). vars([X|Y], L, R):- var(X), vars(Y, M, R), L is M+1. %%% grounds([a,b,c,A,B,C], X , Y ) %%% returns X = 3 (number of non vars at the beginning) and %%% Y = [A,B,C] (the list bust the first initial non vars) grounds([],0,[]). grounds([X|Y], 0, [X|Y]):- var(X). grounds([X|Y], L, R):- ground(X), grounds(Y, M, R), L is M+1. %%% sumgrounds([2,X,3,C,5,1],C ) %%% returns C = 11 (the sum of the non ground values) sumgrounds( [ A | R ] , C ) :- var(A), !, sumgrounds( R , C ). sumgrounds( [ A | R ] , C ) :- sumgrounds( R , C1 ), C is A + C1. sumgrounds( [], 0). %%% sublist(2,3,[a,b,c,d,e,f],X) %%% returns X = [b,c,d] (the list of 3 elements starting from 2) sublist(_Inizio, 0,[],[]). sublist(1, N, List, Sublist):- length( Sublist, N), prefix( Sublist, List). sublist(Inizio, N, [_Testa|Coda], Sublist):- Inizio > 1, NuovoInizio is Inizio-1, sublist( NuovoInizio, N, Coda, Sublist). %%% even/odd predicate: even(X):- 0 #= X mod 2. odd(X):- 1 #= X mod 2. %%% VECTORS (3D) operations: t1([R12x,R12y,R12z], [Tx, Ty, Tz]):- Tx #= R12y * R12z, Ty #= 0 - R12x * R12z, Tz #= R12x * R12y. t2([R12x,R12y,R12z], [Tx, Ty, Tz]):- Y #= abs(R12y),Z #= abs(R12z),X #= abs(R12x), Tx #= R12x * Y, Ty #= R12y * Z, Tz #= R12z * X. t3([R12x,R12y,R12z], [Tx, Ty, Tz]):- Y #= abs(R12y),Z #= abs(R12z),X #= abs(R12x), Tx #= R12x * Z, Ty #= R12y * X, Tz #= R12z * Y. vector_sum([A,B,C],[D,E,F],[G,H,I]):- G #= A + D, H #= B + E, I #= C + F. vector_product([Ax,Ay,Az],[Bx,By,Bz],[Cx,Cy,Cz]):- Cx #= Ay*Bz - Az*By, Cy #= Az*Bx - Ax*Bz, Cz #= Ax*By - Ay*Bx. vector_minus([X,Y,Z],[X1,Y1,Z1]):- X1 #= 0 - X, Y1 #= 0 - Y, Z1 #= 0 - Z. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% The list of the 20 aminoacids %%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% aminoacid(a). aminoacid(c). aminoacid(d). aminoacid(e). aminoacid(f). aminoacid(g). aminoacid(h). aminoacid(i). aminoacid(k). aminoacid(l). aminoacid(m). aminoacid(n). aminoacid(p). aminoacid(q). aminoacid(r). aminoacid(s). aminoacid(t). aminoacid(v). aminoacid(w). aminoacid(y). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% ENERGY MATRIX %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% c table(c,c,-3477). table(c,m,-2240). table(c,f,-2424). table(c, i, -2410). table(c, l, -2343). table(c, v, -2258). table(c, w, -2080). table(c, y, -1892). table(c, a, -1700). table(c, g, -1101). table(c, t, -1243). table(c, s, -1306). table(c, n, -788). table(c, q, -835). table(c, d, -616). table(c, e, -179). table(c, h, -1499). table(c, r, -771). table(c, k, -112). table(c, p, -1196). %% m table(m, m, -1901). table(m, f, -2304). table(m, i, -2286). table(m, l, -2208). table(m, v, -2079). table(m, w, -2090). table(m, y, -1834). table(m, a, -1517). table(m, g, -897). table(m, t, -999). table(m, s, -893). table(m, n, -658). table(m, q, -720). table(m, d, -409). table(m, e, -209). table(m, h, -1252). table(m, r, -611). table(m, k, -146). table(m, p, -788). %% f table(f, f, -2467). table(f, i, -2530). table(f, l, -2491). table(f, v, -2391). table(f, w, -2286). table(f, y, -1963). table(f, a, -1750). table(f, g, -1034). table(f, t, -1237). table(f, s, -1178). table(f, n, -790). table(f, q, -807). table(f, d, -482). table(f, e, -419). table(f, h, -1330 ). table(f, r, -805). table(f, k, -270). table(f, p, -1076). %% i table(i, i, -2691). table(i, l, -2647). table(i, v, -2568). table(i, w, -2303). table(i, y, -1998). table(i, a, -1872). table(i, g, -885). table(i, t, -1360). table(i, s, -1037). table(i, n, -669). table(i, q, -778). table(i, d, -402). table(i, e, -439). table(i, h, -1234). table(i, r, -854). table(i, k, -253). table(i, p, -991). %% l table(l, l, -2501). table(l, v, -2447). table(l, w, -2222). table(l, y, -1919). table(l, a, -1728). table(l, g, -767). table(l, t, -1202). table(l, s, -959). table(l, n, -524). table(l, q, -729). table(l, d, -291). table(l, e, -366). table(l, h, -1176). table(l, r, -758). table(l, k, -222). table(l, p, -771). %% v table(v, v, -2385). table(v, w, -2097). table(v, y, -1790). table(v, a, -1731). table(v, g, -756). table(v, t, -1240). table(v, s, -933). table(v, n, -673). table(v, q, -642). table(v, d, -298). table(v, e, -335). table(v, h, -1118). table(v, r, -664). table(v, k, -200). table(v, p, -886). %% w table(w, w, -1867). table(w, y, -1834). table(w, a, -1565). table(w, g, -1142). table(w, t, -1077). table(w, s, -1145). table(w, n, -884). table(w, q, -997). table(w, d, -613). table(w, e, -624). table(w, h, -1383). table(w, r, -912). table(w, k, -391). table(w, p, -1278). %% y table(y, y, -1335). table(y, a, -1318). table(y, g, -818). table(y, t, -892). table(y, s, -859). table(y, n, -670). table(y, q, -687). table(y, d, -631). table(y, e, -453). table(y, h, -1222). table(y, r, -745). table(y, k, -349). table(y, p, -1067). %% a table(a, a, -1119). table(a, g, -290). table(a, t, -717). table(a, s, -607). table(a, n, -371). table(a, q, -323). table(a, d, -235). table(a, e, -039). table(a, h, -646). table(a, r, -327). table(a, k, 196). table(a, p, -374). %% g table(g, g, 219). table(g, t, -311). table(g, s, -261). table(g, n, -230). table(g, q, 033). table(g, d, -097). table(g, e, 443). table(g, h, -325). table(g, r, -050). table(g, k, 589). table(g, p, -042). %% t table(t, t, -617). table(t, s, -548). table(t, n, -463). table(t, q, -342). table(t, d, -382). table(t, e, -192). table(t, h, -720). table(t, r, -247). table(t, k, 155). table(t, p, -222). %% s table(s, s, -519). table(s, n, -423). table(s, q, -260). table(s, d, -521). table(s, e, -161). table(s, h, -639). table(s, r, -264). table(s, k, 223). table(s, p, -199). %% n table(n, n, -367). table(n, q, -253). table(n, d, -344). table(n, e, 160). table(n, h, -455). table(n, r, -114). table(n, k, 271). table(n, p, -018). %% q table(q, q, 054). table(q, d, 022). table(q, e, 179). table(q, h, -290). table(q, r, -042). table(q, k, 334). table(q, p, -035). %% d table(d, d, 179). table(d, e, 634). table(d, h, -664). table(d, r, -584). table(d, k, -176). table(d, p, 189). %% e table(e, e, 933). table(e, h, -324). table(e, r, -374). table(e, k, -057). table(e, p, 257). %% h table(h, h, -1078). table(h, r, -307). table(h, k, 388). table(h, p, -346). %% r table(r, r, 200). table(r, k, 815). table(r, p, -023). %% k table(k, k, 1339). table(k, p, 661). %% p table(p, p, 129). %%% SYMMETRIC VALUES: table(P1,P2,C):- table(P2,P1,C),!. %%%%%% Print predicate stampa( Primary, Tertiary ) :- stampa( 1 , Primary, Tertiary ). stampa( I , [Amino|R], [X,Y,Z|N]) :- write(I), write('\t'), write(Amino), write('\t'), write(X), write('\t'), write(Y), write('\t'), write(Z), write('\t'), nl, I1 is I + 1, stampa( I1, R, N). stampa(_ , [], []). %%%%%%%%% Timing Predicates: initial_time :- statistics(runtime,[T|_]), assert(start(T)). writetime(Avviso) :- start(InitialTime), statistics(runtime,[CurrentTime|_]), Delta is CurrentTime - InitialTime, write(Avviso), stampa_bene(Delta), write('\t'). stampa_bene( K ) :- K < 60000,!, S is integer(K/1000), M is K mod 1000, write(S), write(','), write(M), write('s'). stampa_bene( K ) :- K < 3600000,!, M is integer(K / 60000), S is K mod 60000, write(M), write('min.'), stampa_bene(S). stampa_bene( K ) :- H is integer(K / 3600000), M is K mod 3600000, write(H), write('hours.'), stampa_bene(M). %%%%%%%% %%% For removing asserted facts, %%% remained in memory due to execution abort clean :- retract(start(_)), clean. clean :- retract(best_solution(_)), clean. clean. %%% Execute: :-clean.