GuardSimplifier.java :  » Testing » KeY » de » uka » ilkd » key » rule » updatesimplifier » Java Open Source

Java Open Source » Testing » KeY 
KeY » de » uka » ilkd » key » rule » updatesimplifier » GuardSimplifier.java
// This file is part of KeY - Integrated Deductive Software Design
// Copyright (C) 2001-2007 Universitaet Karlsruhe, Germany
//                         Universitaet Koblenz-Landau, Germany
//                         Chalmers University of Technology, Sweden
//
// The KeY system is protected by the GNU General Public License. 
// See LICENSE.TXT for details.
//
//

package de.uka.ilkd.key.rule.updatesimplifier;

import de.uka.ilkd.key.logic.Term;
import de.uka.ilkd.key.logic.TermFactory;
import de.uka.ilkd.key.logic.WaryClashFreeSubst;
import de.uka.ilkd.key.logic.op.*;


/**
 *
 */
public abstract class GuardSimplifier {

    private Term condition;

    private ListOfQuantifiableVariable minimizedVars;

    public GuardSimplifier (Term condition,
                            ArrayOfQuantifiableVariable arMinimizedVars) {
        this.condition = condition;
        this.minimizedVars = toList ( arMinimizedVars );
    }

    public boolean bindsVariables () {
        return !getMinimizedVars().isEmpty ();
    }

    public boolean isValidGuard () {
        return getCondition().op () == Op.TRUE;
    }

    public boolean isUnsatisfiableGuard () {
        return getCondition().op () == Op.FALSE;            
    }
    
    /**
     * @return the formula that is simplified by <code>this</code>
     */
    public Term getCondition () {
        return condition;
    }

    /**
     * @return variables that are supposed to represent minimum individuals for
     *         which the guard is satisfied
     */
    protected ListOfQuantifiableVariable getMinimizedVars () {
        return minimizedVars;
    }

    private boolean isMinimizedVar (Operator op) {
        if ( !( op instanceof QuantifiableVariable ) ) return false;
        return getMinimizedVars().contains ( (QuantifiableVariable)op );
    }

    /**
     * Simplify the treated formula. This removes trivial equations (same left
     * and right term) and employs equations of the shape <tt> x = t </tt>
     * (where <tt>x</tt> is a minimized variable) to substitute the variable
     * with the term <tt>t</tt>. This method is supposed to be called in the
     * end of constructors of subclasses
     */
    protected void simplify () {
        while ( !getMinimizedVars().isEmpty () ) {
            final PairOfQuantifiableVariableAndTerm definingPair =
                findSimpleEquation ( getCondition() );
            if ( definingPair == null ) break;
            substituteTempl ( definingPair.variable, definingPair.term );
        }
        
        this.condition = elimSimpleStuff ( getCondition() );
        
        this.minimizedVars = neededVars ( getMinimizedVars() );
    }

    /**
     * Method that needs to be implemented by subclasses, this determines which
     * of the bound/minimized variables are actually needed. The method is
     * supposed to select certain elements of <code>allVars</code> without
     * changing their order
     */
    private ListOfQuantifiableVariable neededVars (ListOfQuantifiableVariable allVars) {
        ListOfQuantifiableVariable needed = SLListOfQuantifiableVariable.EMPTY_LIST;
        
        ListOfQuantifiableVariable innerVars = allVars;
        while ( !innerVars.isEmpty () ) {
            final QuantifiableVariable var = innerVars.head ();
            innerVars = innerVars.tail ();
            // order is important
            if ( !innerVars.contains ( var ) && isNeededVarTempl ( var ) )
                needed = needed.append ( var );
        }
        return needed;
    }

    /**
     * Template method for deciding whether <code>var</code> is a variable
     * that is necessary or that can be removed
     */
    private boolean isNeededVarTempl (final QuantifiableVariable var) {
        return getCondition ().freeVars ().contains ( var )
               || isNeededVar ( var );
    }

    /**
     * Supposed to be overridding in subclasses
     */
    protected boolean isNeededVar (QuantifiableVariable var) {
        return false;
    }

    /**
     * Used to implement <code>simplify()</code>, find trivial parts of the
     * guard and remove them
     */
    private Term elimSimpleStuff (Term formula) {
        final UpdateSimplifierTermFactory utf = UpdateSimplifierTermFactory.DEFAULT;
        final TermFactory tf = utf.getBasicTermFactory ();
        
        if ( formula.op () == Op.EQUALS ) {
            if ( formula.sub ( 0 ).equalsModRenaming ( formula.sub ( 1 ) ) )
                return utf.getValidGuard ();
        } else if ( formula.op () instanceof Junctor ) {
            final Junctor junc = (Junctor)formula.op ();
            final Term[] subTerms = new Term [formula.arity ()];
            for ( int i = 0; i != subTerms.length; ++i )
                subTerms[i] = elimSimpleStuff ( formula.sub ( i ) );
            if ( subTerms.length == 2 )
                return tf.createJunctorTermAndSimplify ( junc,
                                                         subTerms[0],
                                                         subTerms[1] );
            return tf.createJunctorTerm ( junc, subTerms );
        }
    
        return formula;
    }

    /**
     * Template method to substitute <code>var</code> with
     * <code>substTerm</code> (called from <code>simplify()</code>)
     * wherever this is necessary. The hole <code>substitute()</code> can be
     * filled by subclasses
     */
    private void substituteTempl (QuantifiableVariable var, Term substTerm) {
        this.minimizedVars = getMinimizedVars().removeAll ( var );

        this.condition = subst ( var, substTerm, getCondition () );

        substitute ( var, substTerm );
    }

    protected Term subst (QuantifiableVariable var,
                          Term substTerm,
                          Term termToBeModified) {
        final WaryClashFreeSubst subst = new WaryClashFreeSubst ( var, substTerm );
        return subst.apply ( termToBeModified );
    }

    /**
     * Substitute <code>var</code> with <code>substTerm</code> (called from
     * <code>doSubstitute()</code>) wherever this is necessary. This can be
     * overridden by subclasses that need this information
     */
    protected void substitute (QuantifiableVariable var, Term substTerm) {}
    
    private ListOfQuantifiableVariable toList (ArrayOfQuantifiableVariable ar) {
        ListOfQuantifiableVariable res = SLListOfQuantifiableVariable.EMPTY_LIST;
        for ( int i = ar.size () - 1; i >= 0; --i )
            res = res.prepend ( ar.getQuantifiableVariable ( i ) );
        return res;
    }

    /**
     * Recursively search for equations <tt> x = t </tt> (or similar)
     * 
     * @return the pair <tt> (x, t) </tt> in case of success (for the first
     *         equation found), <code>null</code> otherwise
     */
    private PairOfQuantifiableVariableAndTerm findSimpleEquation (Term formula) {
        if ( formula.op () == Op.EQUALS ) {
            final PairOfQuantifiableVariableAndTerm pair =
                isSimpleEquation ( formula, 0 );
            if ( pair != null ) return pair;
            
            return isSimpleEquation ( formula, 1 );
        } else if ( formula.op () == Op.AND ) {
            final PairOfQuantifiableVariableAndTerm pair =
                findSimpleEquation ( formula.sub ( 0 ) );
            if ( pair != null ) return pair;
            
            return findSimpleEquation ( formula.sub ( 1 ) );
        }
        
        return null;
    }

    private PairOfQuantifiableVariableAndTerm isSimpleEquation (Term formula,
                                                                int varLocation) {
        if ( !isMinimizedVar ( formula.sub ( varLocation ).op () ) )
            return null;
    
        final QuantifiableVariable var =
            (QuantifiableVariable)formula.sub ( varLocation ).op ();
        final Term value = formula.sub ( 1 - varLocation );
    
        if ( value.freeVars ().contains ( var )
             || !value.sort ().extendsTrans ( var.sort () ) ) return null;
    
        return new PairOfQuantifiableVariableAndTerm ( var, value );
    }

    private static class PairOfQuantifiableVariableAndTerm {
        public final QuantifiableVariable variable;
        public final Term term;
        
        public PairOfQuantifiableVariableAndTerm (QuantifiableVariable variable,
                                                  Term term) {
            this.variable = variable;
            this.term = term;
        }
    }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.