/* **********************************
 *   ComputeQuality.java
 *     ComputeQuality
 * **********************************/
package admin.hidden;

import edu.neu.ccs.demeterf.demfgen.lib.List;
import edu.neu.ccs.evergreen.ir.Relation;
import gen.*;

public class ComputeQuality{
    /** Compute the quality of an assignment == satRatio(reduce(rm,a)) */
    public static Quality quality(RawMaterial rm, Assignment a){
        RawMaterial reduced = 
            a.literals.fold(new List.Fold<Literal,RawMaterial>(){
                public RawMaterial fold(Literal lit, RawMaterial r){ return reduce(r, lit); }
            },rm);
        return new Quality(satisfiedRatio(reduced));
    }
    /** Reduce a given RawMaterial based on a single Literal assignment */
    public static RawMaterial reduce(RawMaterial s, final Literal lit){
        return new RawMaterial(new RawMaterialInstance(s.instance.cs.map(new List.Map<Constraint,Constraint>(){
            public Constraint map(Constraint c){
                int i = c.vs.index(lit.var);
                if(i < 0 || (c.r.v == 255))return c;
                return new Constraint(c.w, new RelationNr(new Relation(3, c.r.v)
                               .reduce(i, lit.value.sign())), c.vs);
            }})));
    }
    /** Accumulation for the satisfaction ratio */
    static class R{
        double top, bot;
        R(double t, double b){ top = t; bot = b; }
        R add(int t, int b){ return new R(top+t, bot+b); }
        double result(){ return bot==0.0?1.0:top/(double)bot; }
    }
    /** Calculate the satifaction ratio of a (reduced) RawMaterial */
    public static double satisfiedRatio(RawMaterial rm){
        return rm.instance.cs.fold(new List.Fold<Constraint,R>(){
            public R fold(Constraint c, R r){ return r.add((c.r.v == 255)?c.w.v:0, c.w.v); }
        }, new R(0,0)).result();
    }
}