This chapter contains the {\small GENEX} database as well as the code
for the {\small GENEX} interpreter and the front end.  Clauses
encoding domain knowledge are expressed as arguments to a binary
function called \verb+genex_clause+ to facilitate the use of the
interpreter.  For example, if the original Prolog clause encoding a
piece of domain knowledge was 
\begin{center}
\verb+rule1(X,Y) :- a(X),b(Y).+,
\end{center}
it would be written as 
\begin{center}
\verb+genex_clause(rule1(X,Y),[a(X),b(Y)]).+ 
\end{center}
to run under the {\small GENEX} interpreter.

\begin{verbatim}
genex_clause(nt(t),[]).
genex_clause(nt(g),[]).
genex_clause(nt(c),[]).
genex_clause(nt(u),[]).

genex_clause(complement(a,t),[]).
genex_clause(complement(g,c),[]).
genex_clause(complement(t,a),[]).
genex_clause(complement(c,g),[]).

%facts about operons%
genex_clause(part_of(Operon, Promoter),
                             [operon(Operon), promoter(Promoter)]).
genex_clause(part_of(Operon, Operator),
                             [operon(Operon), operator(Operator)]).
genex_clause(assoc(Operon, Reg_gene),
                           [operon(Operon), reg_gene(Reg_gene)]).
genex_clause(part_of(Operon, Struc_genes),
                             [operon(Operon),
                             setof(X, structural_gene(Operon,X), 
                             Struc_genes)]).
genex_clause(part_of(Operon, T),
                             [operon(Operon), terminator(T)]).

genex_clause(ntseq([]),[]).
genex_clause(ntseq([X|Y]),[nt(X),ntseq(Y)]).

genex_clause(enzyme(rna-pol),[]).
genex_clause(enzyme(dna-pol),[]).
genex_clause(protein(X),[enzyme(X)]).
genex_clause(part_of(Enz,active_site1(Enz)),[enzyme(Enz)]).
genex_clause(part_of(Enz,active_site2(Enz)),[enzyme(Enz)]).
genex_clause(binding_site(Mol, active_site1(Enz)),
                               [substrate1(Enz,Mol)]).
genex_clause(binding_site(Mol, active_site2(Enz)),
                               [substrate2(Enz,Mol)]).
\end{verbatim}
\begin{verbatim}
genex_clause(promoter(P), 
        [sequence(P,Seq),\+ sequence(P,[]),
        length(Seq,N),
        approx(N,40),
        contains_subseq(P,[t,t,g,a,c,a]), 
        contains_subseq(P,[t,a,t,a,a,t,g])]). 


genex_clause(contains_subseq(X,[],0),[X=[]]).
genex_clause(contains_subseq(X,[],0),[X=[_|_]]).
genex_clause(contains_subseq([Head|P_tail],[Head|S_tail],1),
                                [S_tail=[]]).
genex_clause(contains_subseq([Head|P_tail],[Head|S_tail],1),
                                [prefix_of(P_tail,S_tail)]).

genex_clause(contains_subseq([_|P_tail],Subseq,Offset),
                             [contains_subseq(P_tail,Subseq,N),
                              Offset is N+1]).

genex_clause(header([X|Y],[X|Z]), [Y=[]]). 
genex_clause(header([X|Y],[X|Z]), [prefix(Z,Y)]). 
%the string X...Y appears at the head of string X...Y...Z %

genex_clause(prefix_of([X|Y],[X]),[]).
genex_clause(prefix_of([X|Y],[X|Z]),[prefix_of(Y,Z)]).

genex_clause(approx(N,M),[Tolerance is M/10,
               High is M+Tolerance,
               Low is M-Tolerance,
               N > Low,
               N < High]).

genex_clause(length([],0),[]).
genex_clause(length([H|T],N),[length(T,M),N is M+1]).

genex_clause(member(X,[X|_]),[]).
genex_clause(member(X,[_|List]),[member(X,List)]).

genex_clause(gene(X),[reg_gene(X)]).
genex_clause(gene(X),[structural_gene(X)]).

genex_clause(protein(X),[reg_protein(X)]).
genex_clause(reg_protein(X),[activator(Operon,X)]).
genex_clause(reg_protein(X),[repressor(Operon,X)]).
genex_clause(reg_protein(X),[product(Reg_gene,X),
                reg_gene(Reg_gene)]).
genex_clause(present(Reg_pro),[reg_protein(Reg_pro)]).
genex_clause(protein(X),[struct_protein(X)]).
genex_clause(part_of(R,smbs(R)),
                [reg_protein(R),
                 normal(R)]).
genex_clause(part_of(R, smbs(R)),
          [reg_protein(R),assuming(part_of(R,smbs(R)))]).
\end{verbatim}
\begin{verbatim}
genex_clause(amino_acid_seq([]),[]).
genex_clause(amino_acid_seq([Y|Z]),[protein(Y)]).
genex_clause(amino_acid_seq([Y|Z]),[amino_acid(Y), amino_acid_seq(Z)]).
genex_clause(amino_acid(gly),[]).
genex_clause(amino_acid(ala),[]).
genex_clause(amino_acid(val),[]).
genex_clause(amino_acid(ileu),[]).
genex_clause(amino_acid(leu),[]).
genex_clause(amino_acid(ser),[]).
genex_clause(amino_acid(thr),[]).
genex_clause(amino_acid(pro),[]).
genex_clause(amino_acid(asp),[]).
genex_clause(amino_acid(glu),[]).
genex_clause(amino_acid(lys),[]).
genex_clause(amino_acid(arg),[]).
genex_clause(amino_acid(asn),[]).
genex_clause(amino_acid(gln),[]).
genex_clause(amino_acid(cys),[]).
genex_clause(amino_acid(met),[]).
genex_clause(amino_acid(trp),[]).
genex_clause(amino_acid(phe),[]).
genex_clause(amino_acid(tyr),[]).
genex_clause(amino_acid(his),[]).

genex_clause(codon([u,u,u],phe),[]).
genex_clause(codon([u,u,c],phe),[]).
genex_clause(codon([u,u,a],leu),[]).
genex_clause(codon([u,u,g],leu),[]).
genex_clause(codon([u,c,u],ser),[]).
genex_clause(codon([u,c,c],ser),[]).
genex_clause(codon([u,c,a],ser),[]).
genex_clause(codon([u,c,g],ser),[]).
genex_clause(codon([u,a,u],tyr),[]).
genex_clause(codon([u,a,c],tyr),[]).
genex_clause(codon([u,a,a],term),[]).
genex_clause(codon([u,a,g],term),[]).
genex_clause(codon([u,g,u],cys),[]).
genex_clause(codon([u,g,c],cys),[]).
genex_clause(codon([u,g,a],term),[]).
genex_clause(codon([u,g,g],trp),[]).
genex_clause(codon([c,u,u],leu),[]).
genex_clause(codon([c,u,c],leu),[]).
genex_clause(codon([c,u,a],leu),[]).
genex_clause(codon([c,u,g],leu),[]).
genex_clause(codon([c,c,u],pro),[]).
genex_clause(codon([c,c,c],pro),[]).
genex_clause(codon([c,c,a],pro),[]).
genex_clause(codon([c,c,g],pro),[]).
genex_clause(codon([c,a,u],his),[]).
genex_clause(codon([c,a,c],his),[]).
genex_clause(codon([c,a,a],gln),[]).
genex_clause(codon([c,a,g],gln),[]).
genex_clause(codon([c,g,u],arg),[]).
genex_clause(codon([c,g,c],arg),[]).
genex_clause(codon([c,g,a],arg),[]).
genex_clause(codon([c,g,g],arg),[]).
genex_clause(codon([a,u,u],ileu),[]).
genex_clause(codon([a,u,c],ileu),[]).
genex_clause(codon([a,u,a],ileu),[]).
genex_clause(codon([a,u,g],met),[]).
genex_clause(codon([a,c,u],thr),[]).
genex_clause(codon([a,c,c],thr),[]).
genex_clause(codon([a,c,a],thr),[]).
genex_clause(codon([a,c,g],thr),[]).
genex_clause(codon([a,a,u],asn),[]).
genex_clause(codon([a,a,c],asn),[]).
genex_clause(codon([a,a,a],lys),[]).
genex_clause(codon([a,a,g],lys),[]).
genex_clause(codon([a,g,u],ser),[]).
genex_clause(codon([a,g,c],ser),[]).
genex_clause(codon([a,g,a],arg),[]).
genex_clause(codon([a,g,g],arg),[]).
genex_clause(codon([g,u,u],val),[]).
genex_clause(codon([g,u,c],val),[]).
genex_clause(codon([g,u,a],val),[]).
genex_clause(codon([g,u,g],val),[]).
genex_clause(codon([g,c,u],ala),[]).
genex_clause(codon([g,c,c],ala),[]).
genex_clause(codon([g,c,a],ala),[]).
genex_clause(codon([g,c,g],ala),[]).
genex_clause(codon([g,a,u],asp),[]).
genex_clause(codon([g,a,c],asp),[]).
genex_clause(codon([g,a,a],glu),[]).
genex_clause(codon([g,a,g],glu),[]).
genex_clause(codon([g,g,u],gly),[]).
genex_clause(codon([g,g,c],gly),[]).
genex_clause(codon([g,g,a],gly),[]).
genex_clause(codon([g,g,g],gly),[]).
\end{verbatim}
\begin{verbatim}
genex_clause(binding_site(X,overlap_region(P,O)),
                [reg_protein(X), operator(O),promoter(P)]).
genex_clause(binding_site(rna_pol,P),[promoter(P)]).
genex_clause(binding_site(I,smbs(R)),
                        [reg_protein(R),
                        part_of(R,smbs(R)),
                        assoc(O,RG),
                        reg_gene(RG),
                        product(RG,R),
                        inducible(O),
                        inducer(O,I)]).

genex_clause(binding_site(C,smbs(R)),
                        [reg_protein(R),
                        part_of(R,smbs(R)),
                        assoc(O,RG),
                        reg_gene(RG),
                        product(RG,R),
                        repressible(O),
                        corepressor(O,C)]).
\end{verbatim}
\begin{verbatim}
genex_clause(bind(Mol, Site),
                       [binding_site(Mol, Site), %preconditions%
                       complementary_conform(Mol,Site),
                       \+ bound(X,Site),
                     % free_to_bind(Mol), %
                       asserta(genex_clause(bound(Mol,Site)))]).
genex_clause(bind(Mol, Site),
                       [binding_site(Mol, Site), %preconditions%
                       assuming(complementary_conform(Mol,Site)),
                       \+ bound(X,Site),
                     % free_to_bind(Mol), %
                       asserta(genex_clause(bound(Mol,Site)))]).

genex_clause(part_of(P,overlap_region(P,O)),[promoter(P),operator(O)]).
genex_clause(part_of(P,promoter_specific(P)),[promoter(P)]).
genex_clause(part_of(O,overlap_region(P,O)),[operator(O),promoter(P)]).
genex_clause(part_of(O,operator_specific(O)),[operator(O)]).

genex_clause(same(X,X),[]).

genex_clause(bound(Mol, P),[promoter(P),
                            part_of(P, Promoter_part),
                            bound(Mol, Promoter_part)]).

genex_clause(bound(Mol, O),[operator(O),
                 part_of(O, Operator_part),
                 bound(Mol, Operator_part)]).


genex_clause(bindable(X,Y),[bound(X,Y)]).
genex_clause(bindable(X,Y),[bind(X,Y)]).

genex_clause(complementary_conform(Reg_pro,overlap_region(P,Oper)),
                        [operator(Oper),
                        promoter(P),
                        reg_protein(Reg_pro), 
                        normal(overlap_region(P,Oper)),
                        active(Reg_pro)]).
genex_clause(complementary_conform(Mol, Regpro),[operon(O),
                        assoc(O,RG),
                        product(RG,Regpro),
                        smmol(O,Mol),
                        present(Mol),
                        normal(Regpro)]).
genex_clause(smmol(O,Mol),[inducer(O,Mol)]).
genex_clause(smmol(O,Mol),[corepressor(O,Mol)]).
genex_clause(complementary_conform(rna_pol,P),[promoter(P),
                        \+ bad_rna_conform(P)]).

genex_clause(unbind(Mol,Site),[retract(bound(Mol,Site))]).
\end{verbatim}
\begin{verbatim}
%%% this clause states the requirements for an operon to be expressed %%%
genex_clause(expressed(Operon),[operon(Operon), 
                initiated(Operon),!,
                not_attenuated(Operon),!,
                xcribe(get_gene_seq(Operon),Xcripts),!,
                xlate(Xcripts,Protein)]).
%               processed(Protein).     %
% processed includes termination_ok (if not msg could be unstable) %

%%% if operon is not initiated, the above will fail, but we want it %%%
%%% to keep looking for other reasons, so run it from the next step %%%
%%% if we have gotten this far and no sequence is given, we cannot conclude %%%
%%% anything about transcription or translation, so just stop and fail.     %%%

genex_clause(expressed(Operon),[print('transcription cannot initiate'),nl,
                print('checking other explanations'),nl,!,
                operon(Operon), 
                not_attenuated(Operon),!, 
                get_gene_seq(Operon,[]),!,fail]).

%%% otherwise continue to see if you can find problems in transcription  %%%
%%% or translation.                                                      %%%
genex_clause(expressed(Operon),[print('transcription cannot initiate'),nl,
                print('checking other explanations'),nl,!,
                operon(Operon), 
                not_attenuated(Operon),!, 
                get_gene_seq(Operon,[Seq|Rest]),!,
                xcribe([Seq|Rest],Xcripts),!,
                xlate(Xcripts,Protein)]).
%               processed(Protein).     %

genex_clause(expressed(Operon),[operon(Operon),
                print('checking other explanations'),nl,
                get_gene_seq(Operon,[Seq|Rest]),!,
                xcribe([Seq|Rest],Xcripts),!,
                xlate(Xcripts,Protein)]).
%               processed(Protein).     %

%% if you get this far, you can't prove operon expressed, so fail.  %%
genex_clause(expressed(Operon),[operon(Operon),!,fail]).

% If there is no sequence given for the operon, it should be %
% entered as [] %

genex_clause(get_gene_seq(O,[]),[sequence(O,[])]).
%%% get_gene_seq gets structural gene sequence from operon sequence. %%%
%%% it is not implemented yet. %%%

genex_clause(xcribe([],[]),[print('no sequence given...'),nl]).
genex_clause(xcribe([Gene|Rest],[Msg|Xcripts]),
                       [sequence(Gene,Seq), 
                        transc(Seq,Msg),
                        xcribe(Rest,Xcripts)]).

genex_clause(transc([],[]),[print('no transcript created...'),nl]).
genex_clause(transc([First|Rest],[Mfirst|Mrest]),
                        [xc(First,Mfirst),transc(Rest,Mrest)]).
genex_clause(xc(a,u),[]).
genex_clause(xc(t,a),[]).
genex_clause(xc(g,c),[]).
genex_clause(xc(c,g),[]).

genex_clause(xlate([],[]),[print('no message to translate...'),nl]).
genex_clause(xlate([Msg|Rest],[Prot1|Proteins]),
                [transl(Msg,Prot1),xlate(Rest,Proteins)]).

% have to look for the ribosome binding site for each transcribed gene in msg %

genex_clause(transl(M,Protein),
            [contains_subseq(M,[a,g,g,a],N), % the rib. bind site %
             index(M,N,Substr), %ignore seq upstream of rib bind site%
             get_start_codon(Substr,0,XL),
             xl(XL,Protein)]).

genex_clause(get_start_codon(Msg,20,_),[fail]). 
% start codon is within 13 nt of bind site %

genex_clause(get_start_codon(Msg,Offset,XL),
                  [Start_point is Offset+10, 
                  length(Msg,L),
                  L > Start_point,
                  index(Msg,Start_point,Head),!,
                  prefix_of(Head,[a,u,g]), XL=Head]).

genex_clause(get_start_codon(Msg,Offset,XL),
                  [Start_point is Offset+10, 
                  length(Msg,L),
                  L > Start_point,
                  index(Msg,Start_point,Head),!,
                  New_offset is Offset+1,
                  get_start_codon(Msg,New_offset,XL)]).

genex_clause(index([],_,[]),[]).
genex_clause(index(String,1,String),[]).
genex_clause(index([_|Tail],I,Substr),
                 [J is I-1, index(Tail,J,Substr)]).

genex_clause(xl([],[]),[]).
genex_clause(xl([Nt1,Nt2,Nt3|Rest],[Amino1|Aminos]),
                 [codon([Nt1,Nt2,Nt3],Amino1),
                 Amino1=term,
                 Aminos=[]]).  % termination case %
genex_clause(xl([Nt1,Nt2,Nt3|Rest],[Amino1|Aminos]),
                 [codon([Nt1,Nt2,Nt3],Amino1),
                 xl(Rest,Aminos)]).

% have to take care of error cases %
genex_clause(proper_xcript(M),
                [\+ nonsense_mut(M),! ,\+ missense_mut(M), !]).

\end{verbatim}
\begin{verbatim}
genex_clause(anabolic_proc(digestion),[]).
genex_clause(catabolic_proc(synthesis),[]).

% how to tell if an operon is inducible %
% if the operon doesn't fit either of these rules, %
% then guess either or both %

genex_clause(inducible(O),[operon(O),
                structural_gene(O,Gene),
                product(Gene,Prod),
                purpose(Prod,Proc),
                catabolic_proc(Proc)]).
genex_clause(inducible(O),[operon(O),inducer(O,I)]).

genex_clause(repressible(O),[operon(O),
                structural_gene(O,Gene),
                product(Gene,Prod),
                purpose(Prod,Proc),
                anabolic_proc(Proc)]).
genex_clause(repressible(O),[operon(O),corepressor(O,C)]).

genex_clause(inducer(O,I),[operon(O),
                structural_gene(O,Gene),
                product(Gene,Prod),
                substrate(Prod,I),
                proportional_to(Prod,I),
                repressor(O,R),
                bindable(I,R)]).
genex_clause(inducer(O,I),
                [operon(O),
                structural_gene(O,Gene),
                product(Gene,P),
                dir_rel(I,P)]).
genex_clause(corepressor(O,C),[operon(O),
                structural_gene(O,Gene),
                product(Gene,Prod),
                end_product(Prod,C),
                inv_proportional_to(Prod,C),
                repressor(O,R),
                bindable(C,R)]).
genex_clause(corepressor(O,C),[operon(O),
                structural_gene(O,Gene),product(Gene,P),
                inv_rel(C,P)]).
\end{verbatim}
\begin{verbatim}
genex_clause(initiated(Op),[operon(Op),
                part_of(Op,P),
                promoter(P),  
                bindable(rna_pol,P)]).

genex_clause(bad_rna_conform(P),[promoter(P),
                normal(P),
                operon(Op),
                part_of(Op,P),
                neg_control(Op),
                repressor(Op,R),
                part_of(Op,O),
                operator(O),
                bindable(R,overlap_region(P,O))]).

genex_clause(bad_rna_conform(P),[promoter(P),
                normal(P),
                operon(Op),
                part_of(Op,P),
                possible_pos_control(Op),
                activator(Op,A),
                part_of(Op,O),
                operator(O),  
                inactive_activator(A,O,P)]).
genex_clause(inactive_activator(A,O,P),[\+ active(A)]).
genex_clause(inactive_activator(A,O,P), 
                 [\+ bindable(A,overlap_region(P,O))]).

genex_clause(neg_control(Op),[operon(Op)]). 
% most operons are under negative control %

genex_clause(possible_pos_control(Op),[glucose_sensitive(Op)]).
genex_clause(possible_pos_control(Op),[assuming(pos_control(Op))]).

genex_clause(glucose_sensitive(Op),[operon(Op), 
                        structural_gene(Op,X),
                        product(X,P),
                        purpose(P, catabolism(S)),
                        sugar(S)]).

genex_clause(sugar(lactose),[]).
genex_clause(sugar(galactose),[]).
genex_clause(sugar(arabinose),[]).
genex_clause(sugar(maltose),[]).

genex_clause(activator(Op,cap),[operon(Op),glucose_sensitive(Op)]).
genex_clause(inducible(cap),[]).
genex_clause(inducer(cap,cAMP),[]).
genex_clause(present(cAMP),[\+ present(glucose)]).
\end{verbatim}
\begin{verbatim}
genex_clause(active(Reg_protein),
               [reg_protein(Reg_protein),
                active_smmol_conform(Reg_protein)]).
genex_clause(active(Reg_protein),
               [reg_protein(Reg_protein),
                assuming(active_smmol_conform(Reg_protein))]).

genex_clause(active_smmol_conform(R),
               [repressor(Op,R),
                normal(R),
                inducible(Op),
                \+ inducer(Op,I)]).
genex_clause(active_smmol_conform(R),
               [repressor(Op,R),
                normal(R),
                inducible(Op),
                inducer(Op,I),
                \+ bindable(I,smbs(R))]).
genex_clause(active_smmol_conform(R),
               [repressor(Op,R),
                phenotype(Op,inducible),
                \+ inducer(Op,I)]).
genex_clause(active_smmol_conform(R),
               [repressor(Op,R),
                phenotype(Op,inducible),
                inducer(Op,I),
                \+ bindable(I,smbs(R))]).
genex_clause(active_smmol_conform(R),
               [repressor(Op,R),
                normal(R),
                repressible(Op),
                corepressor(Op,C),
                bindable(C,smbs(R))]).
genex_clause(active_smmol_conform(R),
               [repressor(Op,R),
                phenotype(Op,repressible),
                corepressor(Op,C),
                bindable(C,smbs(R))]).
genex_clause(active_smmol_conform(A),
               [activator(Op,A),
                normal(A),
                inducible(Op),
                inducer(Op,I),
                bindable(I,smbs(A))]).
genex_clause(active_smmol_conform(A),
               [activator(Op,A),
                phenotype(Op,inducible),
                inducer(Op,I),
                bindable(I,smbs(A))]).
genex_clause(active_smmol_conform(A),
               [activator(Op,A),
                normal(A),
                repressible(Op),
                \+ corepressor(Op,C)]).
genex_clause(active_smmol_conform(A),
               [activator(Op,A),
                normal(A),
                repressible(Op),
                corepressor(Op,C),
                \+ bindable(C,smbs(A))]).
genex_clause(active_smmol_conform(A),
               [activator(Op,A),
                phenotype(Op,repressible),
                \+ corepressor(Op,C)]).
genex_clause(active_smmol_conform(A),
               [activator(Op,A),
                phenotype(Op,repressible),
                corepressor(Op,C),
                \+ bindable(C,smbs(A))]).
\end{verbatim}
\begin{verbatim}
genex_clause(normal(X),[\+ mutated(X),\+ assuming(mutated(X))]).
genex_clause(normal(Y),[gene(X),product(Y,X),normal(X)]).
genex_clause(repressor(Op,R),
                   [operon(Op),
                   neg_control(Op),
                   assoc(Op,Reg_gene),
                   reg_gene(Reg_gene),
                   product(Reg_gene,R)]).

genex_clause(activator(Op,A),
                   [operon(Op),
                   possible_pos_control(Op),
                   assoc(Op,Reg_gene),
                   reg_gene(Reg_gene),
                   product(Reg_gene,A)]).

genex_clause(not_attenuated(Op),
                 [seq(Op,Seq),\+ Seq = [],
                  structural_gene(Op,X),
                  product(X,Prod),
                  purpose(Prod,synthesis),
                  product(Prod,Amino_acid),
                  amino_acid(Amino_acid),
                  present(Amino_acid),
                  codons(Amino_acid,Codons),
                  find_atten_reg(Seq,Codons),!,fail]).
genex_clause(not_attenuated(Op),
                 [seq(Op,[]),
                  structural_gene(Op,X),
                  product(X,Prod),
                  purpose(Prod,synthesis),
                  product(Prod,Amino_acid),
                  amino_acid(Amino_acid),
                  present(Amino_acid),
                  print(Op),print('  is possibly attenuated'),nl,!,fail]).
                  present(Amino_acid),
                  print(Op),print('  is possibly attenuated'),nl]).

genex_clause(find_atten(Seq,Codons),
                 [find_atten2(Seq,Codons,0,0,[])]).

genex_clause(find_atten2([],C,length,clength,atten_seq),[fail]).
\end{verbatim}
\begin{verbatim}

% the following four clauses determine the likely model of %
% the operon's behavior. %

create_model(O,Remove,Assumptions,Mode) :- genex_clause(operon(O),[]),
                            genex_clause(observed_expressed(O),[]),
                            no_influence(Smmol,O),
                            ((genex_clause(assoc(O,RG),[]),
                              genex_clause(reg_gene(RG),[]),
                              genex_clause(mutated(RG),[]));
                             (genex_clause(part_of(O,Op),[]),
                              genex_clause(operator(Op),[]),
                              genex_clause(mutated(Op),[]))),
                            precond(constitutive,O,Remove,Assumptions,Mode).

create_model(O,Remove,Assumptions,Mode) :- genex_clause(operon(O),[]),
                            genex_clause(observed_not_expressed(O),[]),
                            no_influence(Smmol,O),
                            ((genex_clause(assoc(O,RG),[]),
                              genex_clause(reg_gene(RG),[]),
                              genex_clause(mutated(RG),[]));
                             (genex_clause(part_of(O,Op),[]),
                              genex_clause(operator(Op),[]),
                              genex_clause(mutated(Op),[]))),
                           precond(uninducible,O,Remove,Assumptions,Mode).

create_model(O,Remove,Assumptions,Mode) :- genex_clause(operon(O),[]),
                        genex_clause(structural_gene(O,Gene),[]),
                        genex_clause(product(Gene,Prod),[]),
                        genex_clause(dir_rel(Smmol,Prod),[]),
                        precond(regulatable,O,Remove,Assumptions,Mode).

create_model(O,Remove,Assumptions,Mode) :- genex_clause(operon(O),[]),
                        genex_clause(structural_gene(O,Gene),[]),
                        genex_clause(product(Gene,Prod),[]),
                        genex_clause(inv_rel(Smmol,Prod),[]),
                        precond(regulatable,O,Remove,Assumptions,Mode).

no_influence(Smmol,O) :-
                genex_clause(operon(O),[]),
                genex_clause(structural_gene(O,Gene),[]),
                genex_clause(product(Gene,Prod),[]),
                 \+ genex_clause(dir_rel(Smmol,Prod),[]),
                 \+ genex_clause(inv_rel(Smmol,Prod),[]).

% the following three clauses return a list of sets of conditions %
% necessary for the model to be true. Each  set separately is    %
% sufficient. These are used in terse mode.  %

precond(regulatable,O,
        [[complementary_conform(X,smbs(RP)), % uncertain vars to remove %
          complementary_conform(RP,overlap_region(P,Op))]],
        [[smmol(X),reg_protein(RP),operator(Op), % make these %
         complementary_conform(X,smbs(RP)),      % assumptions %
         complementary_conform(RP,overlap_region(P,Op))]],terse)
        :-      name(O, Oname),
                append(Oname,"_promoter",Pname),
                name(P,Pname),
                append(Oname,"_operator",Opname),
                name(Op,Opname),
                append(Oname,"_reg_gene",Rname),
                name(R,Rname),
                append(Oname,"_reg_protein",RPname),    
                name(RP,RPname).

precond(constitutive,O,
        [[complementary_conform(RP,overlap_region(P,Op))],
         [complementary_conform(X,smbs(RP))]],
        [[not_complementary_conform(RP,overlap_region(P,Op))],
         [not_complementary_conform(X,smbs(RP))]],terse)
        :-      name(O, Oname),
                append(Oname,"_promoter",Pname),
                name(P,Pname),
                append(Oname,"_operator",Opname),
                name(Op,Opname),
                append(Oname,"_reg_gene",Rname),
                name(R,Rname),
                append(Oname,"_reg_protein",RPname),    
                name(RP,RPname).        

precond(uninducible,O,
        [[complementary_conform(rna_pol,P)],
         [complementary_conform(Smmol,smbs(RP))],
         [complementary_conform(RP,overlap_region(P,Op))]],
        [[not_complementary_conform(rna_pol,P)],
         [not_complementary_conform(Smmol,smbs(RP))],
         [reg_protein(RP),operator(Op),
          complementary_conform(RP,overlap_region(P,Op))],
         [not_complementary_conform(RP,overlap_region(P,Op))]],terse)
        :-      name(O, Oname),
                append(Oname,"_promoter",Pname),
                name(P,Pname),
                append(Oname,"_operator",Opname),
                name(Op,Opname),
                append(Oname,"_reg_gene",Rname),
                name(R,Rname),
                append(Oname,"_reg_protein",RPname),    
                name(RP,RPname).

% The following three clauses are used in verbose mode.  They do not %
% include the assumptions about conformation so that the program %
% will give a detailed description of the mechanism of the operon %
% using model-based reasoning. %

precond(regulatable,O,
        [],
        [[smmol(X),reg_protein(RP),operator(Op),
         complementary_conform(X,smbs(RP)),
         complementary_conform(RP,overlap_region(P,Op))]],verbose)
        :-      name(O, Oname),
                append(Oname,"_promoter",Pname),
                name(P,Pname),
                append(Oname,"_operator",Opname),
                name(Op,Opname),
                append(Oname,"_reg_gene",Rname),
                name(R,Rname),
                append(Oname,"_reg_protein",RPname),    
                name(RP,RPname).


precond(constitutive,O,
        [],
        [[not_complementary_conform(RP,overlap_region(P,Op))],
         [not_complementary_conform(X,smbs(RP))]],verbose)
        :-      name(O, Oname),
                append(Oname,"_promoter",Pname),
                name(P,Pname),
                append(Oname,"_operator",Opname),
                name(Op,Opname),
                append(Oname,"_reg_gene",Rname),
                name(R,Rname),
                append(Oname,"_reg_protein",RPname),    
                name(RP,RPname).        

precond(uninducible,O,
        [],
        [[not_complementary_conform(rna_pol,P)],
         [not_complementary_conform(Smmol,smbs(RP))],
         [reg_protein(RP),operator(Op),
          complementary_conform(RP,overlap_region(P,Op))],
         [not_complementary_conform(RP,overlap_region(P,Op))]],verbose)
        :-      name(O, Oname),
                append(Oname,"_promoter",Pname),
                name(P,Pname),
                append(Oname,"_operator",Opname),
                name(Op,Opname),
                append(Oname,"_reg_gene",Rname),
                name(R,Rname),
                append(Oname,"_reg_protein",RPname),    
                name(RP,RPname).


\end{verbatim}
\begin{verbatim}
%%% given the behavior, deduce a model of the behavior.  Use the %%%
%%% preconditions for the model to tell you what variables to  %%%
%%% assume %%%


genex_clause(phenotype(O,derepressed),
                           [operon(O),
                            assoc(O,RG),
                            reg_gene(RG),
                            mutated(RG),
                            observed_expressed(O),
                            no_influence(Smmol,O),
                            asserta
                              (genex_clause(phenotype(O,derepressed)))]).
genex_clause(phenotype(O,derepressed),
                           [operon(O),
                            part_of(O,Op),
                            operator(Op),
                            mutated(Op),
                            observed_expressed(O),
                            no_influence(Smmol,O),
                            asserta
                              (genex_clause(phenotype(O,derepressed)))]).

genex_clause(phenotype(O,superrepressed),
                           [operon(O),
                            assoc(O,RG),
                            reg_gene(RG),
                            mutated(RG),
                            observed_not_expressed(O),
                            no_influence(Smmol,O),
                            asserta
                              (genex_clause(phenotype(O,superrepressed)))]).
genex_clause(phenotype(O,superrepressed),
                           [operon(O),
                            part_of(O,Op),
                            operator(Op),
                            mutated(Op),
                            observed_not_expressed(O),
                            no_influence(Smmol,O),
                            asserta
                              (genex_clause(phenotype(O,superrepressed)))]).

genex_clause(phenotype(O,constitutive),
                           [operon(O),
                            assoc(O,RG),
                            reg_gene(RG),
                            mutated(RG),
                            observed_expressed(O),
                            no_influence(Smmol,O),
                            asserta
                              (genex_clause(phenotype(O,constitutive)))]).
genex_clause(phenotype(O,constitutive),
                           [operon(O),
                            part_of(O,Op),
                            operator(Op),
                            mutated(Op),
                            observed_expressed(O),
                            no_influence(Smmol,O),
                            asserta
                              (genex_clause(phenotype(O,constitutive)))]).

genex_clause(phenotype(O,uninducible),
                           [operon(O),
                            assoc(O,RG),
                            reg_gene(RG),
                            mutated(RG),
                            observed_not_expressed(O),
                            no_influence(Smmol,O),
                            asserta
                              (genex_clause(phenotype(O,uninducible)))]).
genex_clause(phenotype(O,uninducible),
                           [operon(O),
                            part_of(O,Op),
                            operator(Op),
                            mutated(Op),
                            observed_not_expressed(O),
                            no_influence(Smmol,O),
                            asserta
                              (genex_clause(phenotype(O,uninducible)))]).

genex_clause(phenotype(O,inducible),
                        [operon(O),
                        structural_gene(O,Gene),
                        product(Gene,Prod),
                        dir_rel(Smmol,Prod),
                        asserta(genex_clause(phenotype(O,inducible)))]).

genex_clause(phenotype(O,repressible),
                        [operon(O),
                        structural_gene(O,Gene),
                        product(Gene,Prod),
                        inv_rel(Smmol,Prod),
                        asserta(genex_clause(phenotype(O,repressible)))]).
\end{verbatim}
\begin{verbatim}
genex_clause(no_influence(Smmol,O),
                [operon(O),
                 structural_gene(O,Gene),
                 product(Gene,Prod),
                 \+ dir_rel(Smmol,Prod),
                 \+ inv_rel(Smmol,Prod)]).

genex_clause(inc_affinity(Reg_pro,Oper),
                       [operon(O),
                        part_of(O,Oper),
                        operator(Oper),
                        mutated(Oper),
                        assoc(O,RG),
                        reg_gene(RG),
                        product(RG,Reg_pro),
                        phenotype(O,uninducible)]).
genex_clause(inc_affinity(Reg_pro,Oper),
                       [operon(O),
                        part_of(O,Oper),
                        operator(Oper),
                        mutated(Oper),
                        assoc(O,RG),
                        reg_gene(RG),
                        product(RG,Reg_pro),
                        phenotype(O,superrepressed)]).
genex_clause(inc_affinity(Reg_pro,Oper),
                       [operon(O),
                        part_of(O,Oper),
                        operator(Oper),
                        assoc(O,RG),
                        reg_gene(RG),
                        mutated(RG),
                        product(RG,Reg_pro),
                        phenotype(O,uninducible)]).
genex_clause(inc_affinity(Reg_pro,Oper),
                       [operon(O),
                        part_of(O,Oper),
                        operator(Oper),
                        assoc(O,RG),
                        reg_gene(RG),
                        mutated(RG),
                        product(RG,Reg_pro),
                        phenotype(O,superrepressed)]).

genex_clause(dec_affinity(Reg_pro,Oper),
                       [operon(O),
                        part_of(O,Oper),
                        operator(Oper),
                        mutated(Oper),
                        assoc(O,RG),
                        reg_gene(RG),
                        product(RG,Reg_pro),
                        phenotype(O,derepressed)]).
genex_clause(dec_affinity(Reg_pro,Oper),
                       [operon(O),
                        part_of(O,Oper),
                        operator(Oper),
                        mutated(Oper),
                        assoc(O,RG),
                        reg_gene(RG),
                        product(RG,Reg_pro),
                        phenotype(O,constitutive)]).
genex_clause(dec_affinity(Reg_pro,Oper),
                       [operon(O),
                        part_of(O,Oper),
                        operator(Oper),
                        assoc(O,RG),
                        reg_gene(RG),
                        mutated(RG),
                        product(RG,Reg_pro),
                        phenotype(O,derepressed)]).
genex_clause(dec_affinity(Reg_pro,Oper),
                       [operon(O),
                        part_of(O,Oper),
                        operator(Oper),
                        assoc(O,RG),
                        reg_gene(RG),
                        mutated(RG),
                        product(RG,Reg_pro),
                        phenotype(O,constitutive)]).

genex_clause(norm_affinity(Reg_pro,Oper),
                       [operon(O),
                        part_of(O,Oper), operator(Oper),
                        assoc(O,RG), reg_gene(RG),
                        product(RG,Reg_pro),
                        \+ phenotype(O,derepressed),
                        \+ phenotype(O,superrepressed),
                        \+ phenotype(O,constitutive),
                        \+ phenotype(O,uninducible)]).
\end{verbatim}
\begin{verbatim}
genex_clause(complementary_conform(Reg_pro,overlap_region(P,Oper)),
                [reg_protein(Reg_pro),promoter(P),operator(Oper),
                inc_affinity(Reg_pro,Oper)]).
genex_clause(complementary_conform(Reg_pro,overlap_region(P,Oper)),
                [operon(O),assoc(O,Reg_gene),reg_gene(Reg_gene),
                product(Reg_gene,Reg_pro),
                reg_protein(Reg_pro),active(Reg_pro),
                part_of(O,P),promoter(P),
                part_of(O,Oper),operator(Oper),
                phenotype(O,repressible)]).
genex_clause(complementary_conform(Reg_pro,overlap_region(P,Oper)),
                [operon(O),assoc(O,Reg_gene),reg_gene(Reg_gene),
                product(Reg_gene,Reg_pro),
                reg_protein(Reg_pro),active(Reg_pro),
                part_of(O,P),promoter(P),
                part_of(O,Oper),operator(Oper),
                phenotype(O,inducible)]).
genex_clause(complementary_conform(X,smbs(RP)),
                [operon(O),assoc(O,RG),reg_gene(RG),product(RG,RP),
                reg_protein(RP),smmol(O,X),phenotype(O,repressible)]).
genex_clause(complementary_conform(X,smbs(RP)),
                [operon(O),assoc(O,RG),reg_gene(RG),product(RG,RP),
                reg_protein(RP),smmol(O,X),phenotype(O,inducible)]).

genex_clause(part_of(RP,smbs(RP)),
                [operon(O),assoc(O,RG),reg_gene(RG),product(RG,RP),
                reg_protein(RP),phenotype(O,repressible)]).
genex_clause(part_of(RP,smbs(RP)),
                [operon(O),assoc(O,RG),reg_gene(RG),product(RG,RP),
                reg_protein(RP),phenotype(O,inducible)]).
\end{verbatim}

The following code comprises the GENEX interpreter.

\begin{verbatim}
member(X,[X|_]).
member(X,[_|L]) :- member(X,L).

clause_uses(G,G).
clause_uses(G,Clause) :- genex_clause(G,Body),
                        (member(Clause,Body);
                         member(\+ Clause,Body)).

trivial(G) :- repressible(O),clause_uses(G,inducible(O)).
trivial(G) :- inducible(O),clause_uses(G,repressible(O)).
trivial(G) :- inducer(O,I),clause_uses(G,corepressor(O,C)).
trivial(G) :- corepressor(O,C),clause_uses(G,inducer(O,I)).
trivial(G) :- \+ pos_control(O),clause_uses(G,pos_control(O)).
trivial(G) :- \+ neg_control(O),clause_uses(G,neg_control(O)).
trivial(G) :- genex_clause(G,[]).
trivial(part_of(O,X)).
trivial(assoc(O,X)).
trivial(neg_control(O)).
trivial(pos_control(O)).
trivial(reg_protein(RP)).
trivial(repressor(O,RP)).
trivial(activator(O,RP)).
trivial(gene(X)).
trivial(neg_control(O)).
trivial(print(X)).
\end{verbatim}
\begin{verbatim}

% The following program runs the possible states. The 1ST ARG. %
% is a list of lists of UNCERTAIN VARIABLE COMBINATIONS, %
% representing the possible states that might be in effect. %  
% The 2ND ARG. is the OPERON that we want to simulate.  All %
% possible states in the list of states are tried.  If the %
% result of the simulation matches the observed behavior, then %
% the list of assumptions which were made for the current run of %
% the simulation is printed out, along with highlights of the %
% simulation of the program.  This program assumes that system  %
% variables which are not uncertain will be set up before this %
% program is run. %
try_possible_state([],Operon) :-        % CASE: NO ASSUMPTIONS      %
        (observed_expressed(Operon) -> prove(expressed(Operon)));
         \+ prove(expressed(Operon)).  % if it's not observed expressed %

try_possible_state([A|B], Operon) :-    % CASE: ASSUMPTIONS MADE    %
        try_possible_states([A|B], Operon).

try_possible_states([],_).

try_possible_states([Newstate|Rest],Operon) :- 
        retract_assumptions,
        make_assumptions(Newstate),
        ((genex_clause(observed_expressed(Operon),[]),
          try_prove_expressed(Operon));
         (genex_clause(observed_not_expressed(Operon),[]),
          try_prove_not_expressed(Operon))),
        try_possible_states(Rest,Observed).


try_prove_expressed(O) :- prove(expressed(O)),nl,print('yes'),nl.
try_prove_expressed(O) :- nl,print('no'),nl.

try_prove_not_expressed(O) :- \+ prove(expressed(O)),nl,print('yes'),nl.
try_prove_not_expressed(O) :- nl,print('no'),nl.

% The following program actually interprets the genex_clauses %
% in PROLOG %

prove([]).
prove([Goal|Rest]) :-
   genex_clause(Goal,Body),
   (\+ trivial(Goal) -> (print('goal: '),print(Goal),nl,
                         print('attempting to prove: '),print(Body),nl);true),
   prove(Body),
   (\+ trivial(Goal) -> (print('proved: '),print(Goal),nl); true),
   prove(Rest). % this is for goals with more than one clause %
prove([\+ Goal|Rest]) :-
    (genex_clause(Goal,Body)  -> (\+ prove(Body), prove(Rest)));
    prove(Rest).
prove([asserta(Assertion)]) :- asserta(Assertion).
prove([print(X)|Rest]) :- print(X),prove(Rest).
prove([nl|Rest]) :- nl,prove(Rest).
prove(Goal) :-
   \+ functor(Goal,'.',_), % if goal is not a list %
   prove([Goal]).   
\end{verbatim}
\begin{verbatim}
% MAKE_ASSUMPTIONS asserts assuming(_) for each uncertain variable %
% in the list passed to it.  Must be given a LIST.  Note, however, %
% that GENEX only looks for positive assumptions, the negative ones %
% are used only for explaining the programs results (because in  %
% prolog, if there is no way to prove foo(X), it is the same as if %
% we had explicitly stated  \+ foo(X)...) %

make_assumptions([]).
make_assumptions([First|Rest]) :- 
                asserta(genex_clause(assuming(First),[])),
                print('assuming: '),print(First),nl,
                make_assumptions(Rest).


% RETRACT-ASSUMPTIONS removes every instance of a clause of the %
% form assuming(_) %

retract_assumptions :- genex_clause(assuming(_)), 
                       retract(genex_clause(assuming(_))),fail.
retract_assumptions.

insert(Item,List,[Item|List]).
remove(Item,[Item|List],List).
\end{verbatim}
\begin{verbatim}
% make a list of uncertain variables %

% make states set from list of uncertain variables %
make_uncertain_sets([],[]).
make_uncertain_sets([First|Rest],[New|Newrest]) :-
        make_uncertain_set(First,New),
        make_uncertain_sets(Rest,Newrest),!.

make_uncertain_set([],[]).
make_uncertain_set([X],Set) :-  
                        X =.. [Func|Args],
                        name(Func,N),
                        append("not_",N,Neg),
                        name(N1,Neg),
                        Z =.. [N1|Args],
                        Set=[[X],[Z]].
make_uncertain_set([X|Rest],Uncertain) :-
        make_uncertain_set([X],[X1,X2]),
        make_uncertain_set(Rest,[S1|S2]),
        add_to_set([S1|S2],X1,New1),
        add_to_set([S1|S2],X2,New2),
        append(New1,New2,Uncertain),!.

% add-to-set takes as input a bigset of sets and a newset.  It returns %
% the result of appending newset to each set in bigset. %

add_to_set([],List1,[]).
add_to_set([First|S2],X,[New|Rest]) :- 
        append(First,X,New),
        add_to_set(S2,X,Rest),!.


subtract_sets([],Var_set,[Var_set]).
subtract_sets([X],Var_set,[Newset]) :- subtract(Var_set,X,Newset).
subtract_sets([Subtractee|Rest],Var_set,[Newset|Newrest]) :-
        subtract(Var_set,Subtractee,Newset),
        subtract_sets(Rest,Var_set,Newrest),!.

make_states([],[],[]).
make_states([Uncerts1|UncertsN],[],States) :- [Uncerts1|UncertsN] = States.
make_states([Uncerts1|UncertsN],[Conds1|CondsN],States) :-
        add_to_set(Uncerts1,Conds1,States1),
        make_states(UncertsN,CondsN,StatesN),
        append(States1,StatesN,States),!.

append([A|X],Y,[A|Z]) :- append(X,Y,Z).
append([],Y,Y).

same(X,X).

genex :- print('end every answer with a period followed by a CR!'),
        nl,nl,
        print('solution mode (terse or verbose): '),read(Mode),
        print('name of operon: '),read(O), asserta(genex_clause(operon(O),[])),
        make_parts(O),
        print('are there any mutations in '),print(O),print(' or reg_gene'),
        print(' (yes, no, or unknown) ?'), nl, read(Mut),
        do_mutations(Mut,O,Sites),
        set_uncertain_vars(O,Sites,Uncert_vars),
        listtoset(Uncert_vars,Var_set), %no dup.elts in var_set%
        print('is '),print(O),print(' gene product made?'),nl,
        read(Expressed),
        ((same(Expressed,'yes') -> 
                asserta(genex_clause(observed_expressed(O),[])));
        (same(Expressed,'no') ->
                asserta(genex_clause(observed_not_expressed(O),[])));
        (same(Expressed,'predict') ->
                asserta(genex_clause(predict_expressed(O),[])))),
        print('enter any other information available '),
                nl,
                print('e.g. proportional_to(X,Y), inv_proportional_to(X,Y)'),
                print(', present(Substance), etc.'), nl,
                print('-- end with "done"'), nl,
        any_other_info(O),
% if we are not in predict mode, can use observed behavior of operon to %
% decide on the likely model of its behavior. %
        (( \+ same(Expressed,'predict') ->
% return uncertain vars to be removed and sets of conditions for model %
        (create_model(O,Remove_these,Conditions,Mode),
% the next clause subtracts each of the condition sets from the uncert.  %
% var.set in turn, yielding a number of uncert.var sets in which the  %
% remaining vars do not depend on some set of conditions %
        subtract_sets(Remove_these,Var_set,Newsets),
        listtoset(Newsets,Newsets1), % get rid of dupl. sets %
% make uncertain sets from the remaining uncertain var. sets and merge %
% the conditions into their corresponding uncertain sets %
        make_uncertain_sets(Newsets1,Uncert_sets),
        make_states(Uncert_sets,Conditions ,States),nl));
% in predict mode, we don't have the observed behavior and so cannot %
% reduce the number of uncertain variables, so just use the original set. %
         (same(Expressed,'predict') ->
          make_uncertain_set(Var_set, Uncert_sets))),
        try_possible_state(States,O),
        print('do you want to try positive control? (yes or no)'),nl,
        read(PC),
        do_pos_control(PC,Set,O).

do_pos_control('no',_,_) :- print('end of GENEX session.'),nl.
do_pos_control('yes',Set,O) :- 
                retract(genex_clause(neg_control(Operon))),
                assert(genex_clause(assuming(pos_control(O)),[])),
                print('assuming positive control...'),nl,
                try_possible_state(O),
                assert(genex_clause(neg_control(O),[])),
                print('assuming positive and negative control...'),nl,
                try_possible_state(O).

do_mutations('no',O,[]) :- assert(genex_clause(normal(O),[])).
do_mutations('unknown',O,[promoter,operator,reg_gene,struct_genes,unknown]).
do_mutations('yes',O, Sites) :-
                print('mutation site known (yes or no) ?'),nl,
                read(Ans),
                (same(Ans,'no') -> 
                   (Sites = [promoter,reg_gene,operator,struct_genes,unknown]));
                (same(Ans,'yes') ->
                   (get_mutation_sites(Sites,
                                [promoter,reg_gene,operator,struct_genes]))).

make_parts(O) :- name(O, Oname),
                append(Oname,"_promoter",Pname),
                name(P,Pname),
                asserta(genex_clause(promoter(P),[])),
                append(Oname,"_operator",Opname),
                name(Op,Opname),
                asserta(genex_clause(operator(Op),[])),
                append(Oname,"_reg_gene",Rname),
                name(R,Rname),
                asserta(genex_clause(reg_gene(R),[])),  
                append(Oname,"_reg_protein",RPname),    
                name(RP,RPname),        % hack so we can use reg-protein %
                asserta(genex_clause(product(R,RP),[])),  % in mutation rules %
                append(Oname,"_terminator",Tname),
                name(T,Tname),
                asserta(genex_clause(terminator(T),[])),
                print(O),
                print(' structural genes: '),
                print('enter one at a time, 5prime - 3prime order'),
                nl,
                print(' -- end with "done"'),
                nl,
                make_struct_genes(O),
                print('enter sequence of '),print(O),print(' or []'),
                nl,read(Seq),
                asserta(genex_clause(sequence(O,Seq),[])).

make_struct_genes(O) :- print('structural gene:'), nl,
                        read(X), make_struct_gene(O,X).
make_struct_gene(O,'done').
make_struct_gene(O,X) :- 
                 asserta(genex_clause(structural_gene(O,X),[])),
                 print('what is product of '),print(X),nl,
                 read(Y),
                 asserta(genex_clause(product(X,Y),[])),
                 print('what is purpose of '),print(Y),
                 print(': (synthesis, digestion, or other)'),nl,
                 read(P),
                 asserta(genex_clause(purpose(Y,P),[])),
                 make_purpose(Y,P),
                 make_struct_genes(O).

make_purpose(Y,'synthesis') :- print('what does '),print(Y),
                                print(' synthesize?'),nl,
                                read(End_prod),
                                asserta(genex_clause(end_product(Y,End_prod))).
make_purpose(Y,'digestion') :- print('what does '),print(Y),
                                print(' digest?'),nl,
                                read(Substrate),
                                asserta(genex_clause(substrate(Y,Substrate))).
make_purpose(Y,'other').
get_mutation_sites([],[]).
get_mutation_sites(Sites, [Site|Rest]) :-
                print('mutation in '),print(Site),print(' (yes or no) ?'),
                nl,read(Ans),
                analyse(Ans,Site,Add),
                get_mutation_sites(Rest_of_sites, Rest),
                append(Add,Rest_of_sites,Sites).


analyse('yes',Site,[Site]) :-   genex_clause(X,[]),
                                functor(X,Site,_),
                                arg(1,X,Op_site),
                                asserta(genex_clause(mutated(Op_site),[])).
analyse('no',Site,[]).
analyse('deletion',promoter,[]) :- retract(genex_clause(promoter(X),[])).
analyse('deletion',operator,[]) :- retract(genex_clause(operator(X),[])).
analyse('deletion',reg_gene,[]) :- retract(genex_clause(reg_gene(X),[])).
analyse('deletion',struct_genes,[]) :- 
                               retract(genex_clause(struct_genes(X),[])).

append([],Y,Y).
append([A|X],Y,[A|Z]) :- append(X,Y,Z).

% the following program makes a list of Uncertain_vars (arg3) for the   %
% operon O using the list of mutated regions of the operon (arg2)       %

set_uncertain_vars(_,[],[]).
set_uncertain_vars(O, [Site|Rest], Uncertain_vars) :-
        same(Site,promoter) ->
                (genex_clause(promoter(P),[]),
                 set_uncertain_vars(O,Rest,Rest_of_vars),
                 append([complementary_conform(rna_pol,P)],
                         Rest_of_vars,
                         Uncertain_vars));
        same(Site,operator) ->
                (genex_clause(operator(Op),[]),
                 genex_clause(promoter(P),[]),
                 genex_clause(reg_gene(RG),[]),
                 genex_clause(product(RG,RP),[]),
                 set_uncertain_vars(O,Rest,Rest_of_vars),
                 append([complementary_conform(RP,overlap_region(P,Op)),
                          mutated(overlap_region(P,Op)),
                          mutated(operator_specific(Op))],
                         Rest_of_vars,
                         Uncertain_vars));
        same(Site,struct_genes) -> true;
        same(Site,reg_gene) ->
                (genex_clause(reg_gene(RG),[]),
                 genex_clause(product(RG,RP),[]),
                 genex_clause(operator(Op),[]),
                 genex_clause(promoter(P),[]),
                 set_uncertain_vars(O,Rest,Rest_of_vars),
                 append([complementary_conform(RP,overlap_region(P,Op)),
                         complementary_conform(X,smbs(RP)),
                         part_of(RP,smbs(RP)),
                         mutated(RP),
                         active_smmol_conform(RP)],
                         Rest_of_vars,
                         Uncertain_vars));
        same(Site,unknown) ->   % if mutation site is not known %
                (genex_clause(promoter(P),[]),
                 genex_clause(operator(Op),[]),
                 genex_clause(reg_gene(RG),[]),
                 genex_clause(product(RG,RP),[]),
                 genex_clause(structural_gene(O,X),[]),
                 set_uncertain_vars(O,Rest,Rest_of_vars),
                 append([mutated(P),mutated(Op),mutated(RG),mutated(X),
                        complementary_conform(rna_pol,P),
                        complementary_conform(RP,overlap_region(P,Op)),
                        complementary_conform(Smmol,smbs(RP)),
                        mutated(overlap_region(P,Op)),
                        mutated(operator_specific(Op)),
                         active_smmol_conform(RP)],
                         Rest_of_vars,
                         Uncertain_vars)).

any_other_info(O) :- read(X), do_other_info(O,X).
do_other_info(O,'done').
do_other_info(O, Info) :- asserta(genex_clause(Info,[])),any_other_info(O).

\end{verbatim}

{\small GENEX} also uses a Prolog set manipulation utility package
written by Lawrence Byrd and R.A. O'Keefe.
