/* -*- Mode: Prolog -*-
 * @(#)$Id: weak_fertilize,v 1.4.2.1 1999/02/05 18:42:52 rjb Exp $
 *
 * $Log: weak_fertilize,v $
 * Revision 1.4.2.1  1999/02/05 18:42:52  rjb
 * Fertilization methods now specify the whole hypothesis not just its label.
 *
 * Revision 1.4  1997/10/09 17:20:53  img
 * renaming
 *
 * Revision 1.3  1997/04/07 10:41:48  img
 * Redundant call to ground_sinks removed.
 *
 * Revision 1.2  1996/12/11 15:07:24  img
 * New methods for lazy application of unblocking.
 *
 * Revision 1.7  1996/12/06 15:23:55  img
 * Induction markers carry history of how they have been used in
 * weak-fertilization (the history is in reverse).
 *
 * Revision 1.6  1996/12/04 13:25:02  img
 * Tidy up the manipulation of inductive hypothesis: use
 * inductive_hypothesis/5 to exchange "raw" markers for "notraw"; don't
 * allow "used" induction hypotheses for fertilization.  Bug-fix: use
 * IndHypVars for instantiate/4, since this is not affected by
 * normalization or case-splits higher in the tree (but this is not the
 * best way to do it).
 *
 * Revision 1.5  1996/11/07 11:29:25  img
 * Reinsert header.
 *
 * Revision 1.4  1996/08/05 14:55:36  img
 * Generalize to having some wave-fronts inside sinks.
 *
 * Revision 1.3  1996/06/19 08:32:01  img
 * Use instantiate/4 to ensure that all universals are instantiated
 * during a weak-fertilization, even when there are fewer variables on
 * the left than on the right.
 *
 * Revision 1.2  1995/04/26  16:18:32  img
 *    * Indent code and tidy.
 *
 * Revision 1.1  1994/09/16  09:34:27  dream
 * Initial revision
 */
        % Weak fertilization consists of using the induction hypothesis
        % to rewrite all the wave terms inside a wave front once that
        % wave front is the only one present, and it has bubbled all the
        % way up to the top of one side of the formula. This method
        % applies a fertilization to just one wave term of the top wave
        % front. It gets called iteratively to do the operation on all
        % wave terms in the wave front.  A special case is when the wave
        % front hasnt been rippled to the top of one side of the
        % formula, but has been rippled right out of one side. In that
        % case we can do fertilization on the whole side of that formula
        % (the case where S below is empty). 
        % 
        % For a function symbol ~ for which transitivity holds, we can
        % perform the following transformations on sequents:
        % 
        % 1. L~R |- X~S(R) into L~R |- X~S(L) if R occurs positive in S, or
        % 2. L~R |- S(L)~X into L~R |- S(R)~X if L occurs positive in S, or
        % 3. L~R |- X~S(L) into L~R |- X~S(R) if L occurs negative in S, or
        % 4. L~R |- S(R)~X into L~R |- S(L)~X if R occurs negative in S.
        %
        % where the wave fronts must be: ``S({R})'' etc.
        % These can be reprased as:
        % 
        % 1. substitute R by L in rhs when R occurs positive, or
        % 2. substitute L by R in lhs when L occurs positive, or
        % 3. substitute L by R in rhs when L occurs negative, or
        % 4. substitute R by L in lhs when R occurs negative
        % 
        % If ~ is also symmetrical, we can drop the requirements on polarity.
        % The method below implements 1-2 in one method. It knows about
        % a set of function symbols which are transitive. It then always
        % does a fertilization replacing R by L, but it can assign L and
        % R to either lhs and rhs or vice versa, so we get the symmetry
        % we want.
        % 
        % REMARKS:
        % 1. The set of transitify function symbols this method knows
        % about might of course have to be extended in the future
        % (similary, it knows about one symmetrical function symbol
        % (equality)).
        % 
        % 2. The case where S below is empty can possibly loop (for
        %    instance y:t=>f(g(y))=>f(y) |- z:t=>f(``g({2}''))=>f(z)
        %    gives    y:t=>f(g(y))=>f(y) |- z:t=>f(``g({2}''))=>f(g(z))
        %    (according to 1. above), which in turn gives:
        %             y:t=>f(g(y))=>f(y) |- z:t=>f(``g({2}''))=>f(g(g(z)))
        %    (again according to 1.) above, etc.
        %    The problem with this is of course that there is no
        %    "reducing measure" to stop the iteration of fertilization
        %    (as there is in the wave front case, namely the reducing
        %     number of wave fronts).
        %    When there is no wave front (S empty), then we want to do
        %    only one fertilization step, and not iterate. This is
        %    achieved by always deleting the wave fronts in L after one
        %    fertilization. This will then stop the next iteration
        %    (since L having wave fronts is a condition for
        %    fertilization when R has none). The immediate deletion of
        %    wave front from L will not affect the iteration when R has
        %    wave fronts, since the presence of wave fronts in L is then
        %    immaterial.
        %
        % 3. The below doesn't implement cases 3.-4. above (negative
        %    fertilization), but it can't be very difficult. It would
        %    look very much like the below. I wonder if it can
        %    reasonably be done with one piece of code (once method).
        % 
        % 4. Notice that "in" is used instead of "=" to represent (_=_ in _),
        %    since it makes the code below more uniform (in particular,
        %    it allows the exp_at(_,[0],_) expression).
        %
        % 5. See the file schemes.pl and Blue Book note 539 for a sermon
        %    about "theory free" theorem provers, and how the weak
        %    fertilization method is one of the few places where CLaM
        %    violates this requirement. 
        %
        % 6. The main idea of and motivation for weak fertilization is
        %    also described in Blue Book note 538.
method(weak_fertilize(Dir,Connective,Pos,Hyp-IndHyp),
       H==>G,
       [matrix(Vars,InitM,G),
        maximally_joined(InitM,M),
	transitive_pred( M, [LR,RL], [LRN,RLN], NewG_M ),
        exp_at(M,[0],Connective),
	%% Do fertilization right-to-leftor left-to-right
        ((Dir=right,GL=LR,GR=RL, GLNew=LRN, GRNew = RLN) v 
	 (Dir=left,GL=RL,GR=LR, GLNew=RLN, GRNew = LRN )), 
        (
          (wave_fronts(GR1,[[]-PosL/[Typ,out]],GR), % We must have 1 wave-front in GR,
           select(Pos,PosL,OtherPosL),              % which is on the top ([]-...) and
           NewWFspec = [[]-PosL/[Typ,in]]	    % out-bound. Note change in wave
          ) 					    % direction.
        v
          (wave_fronts(GR1,[[]-PosL/[Typ,in]],GR),  % or if we have 1 wave-front in GR 
	   PosL = [_,_|_],			    % which is on top and in-bound
           select(Pos,PosL,OtherPosL),		    % then we must have mutiple holes.
           NewWFspec = [[]-PosL/[Typ,in]])
         v 
	  (wave_fronts(GR1,[],GR),                 % or we have no wave front in GR, 
           wave_fronts(_,[_-_/[_,out]|_],GL),      % but we require out-bound 
           PosL=[],Pos=[],OtherPosL=[[]],          % wave-fronts in GL,
           NewWFspec = [Pos-OtherPosL/_])
         v 
          (wave_fronts(GR1tmp,[WFPos-[WHPos]/[Typ,_]],GR), % or all wave fronts 
           sinks(GR1,[WFPos],GR1tmp),                      % are sunk in GR.
           sinks(GL1,_,GL),
	   append(WHPos,WFPos,RSinkPos),
	   exp_at(GR1,RSinkPos,Sink),
	   exp_at(GL1,LSinkPos,Sink),
	   NewWFspec = [LSinkPos-[WHPos]/[Typ,out]],
	   Pos=[])
         v
	%% This does not correctly place ingoing
	%% wave front on output
	%% (when there are 2 fertilisation rewrites to do, anyway).
        (wave_fronts(GR1tmp,[[]-PosL/[Typ,out]|SunkFronts],GR), % We must have 1 wave-front in GR,
           select(Pos,PosL,OtherPosL),                       % which is on the top ([]-...) and
           NewWFspec = [[]-PosL/[Typ,in]],	             % out-bound; with all other waves fronts sunk.
           sinks(GR1,SinkPosns,GR1tmp),	
           (forall{PP \ SunkFronts}: (PP = FrontPos-_/[_,_], % 	all fronts in Sunkfronts are in sinks
                     (thereis{ SS \ SinkPosns} : append(SS,_,FrontPos)))))),
        exp_at(GR1,Pos,GR1Sub),
                                        % check for positive occurrence
                                        % or symmetrical function symbol:
        (Connective = (in) orelse polarity(_,_,GR1,Pos,+)),
	inductive_hypothesis(Status,Hyp:IndHyp,H),
	((Status = raw,EarlierFs=[]);
	 Status = notraw(EarlierFs)),		% don't allow 'used'
        matrix(IndHypVars,IndHyp_M,IndHyp),	% find hyp to use for fertilization
        exp_at(IndHyp_M,[0],Connective),
        replace_all(GL,GRNewSub,M,GSub1),
        replace_all(GR,GR1Sub,GSub1,GSub),
	untype(IndHypVars,IndHypVarsNoTypes),
        instantiate(IndHypVarsNoTypes,IndHyp,GSub,Instan),
        wave_fronts(GRNewSub,_,GRNewSub)% and check it doesnt introduce
                                        % more wave-fronts.
       ],
       [replace(Pos,GRNewSub,GR1,GRNew1),% apply the fertilization
        wave_fronts(GRNew1,NewWFspec,GRNew),
        wave_fronts(GLNew,_,GL),        % squash the wave-fronts in L
					% (see remark 2. above).
        sinks(NNewG_M,_,NewG_M),        % squash all sinks

        matrix(Vars,NNewG_M,NewG),
	inductive_hypothesis(Status,Hyp:IndHyp,H,notraw([Dir|EarlierFs]),NewH),
	ann_normal_form(NewG,NewGNF) ],
       [NewH==>NewGNF],
       weak_fertilize(Dir,Connective,Pos,Hyp-IndHyp)).



