/*
 * PenalizationFitness.java
 *
 * Created on 20. listopad 2005, 13:44
 *
 * To change this template, choose Tools | Options and locate the template under
 * the Source Creation and Management node. Right-click the template and choose
 * Open. You can then make changes to the template in the Source Editor.
 */

package cz.pcland.ga.fitness;
import cz.pcland.ga.BaseIndividual;
import cz.pcland.ga.BinaryIndividual;
import cz.pcland.knapsack.KnapSack;
import cz.pcland.knapsack.KnapSackItem;
//import java.io.*;
import java.util.*;
/**
 *
 * @author petr
 */
public class PenalizationFitness implements Evaluator{
    double  penalizationFactor; //MAX(P/C), for all items
    double maxCapacity = 0;
    protected KnapSack ks;
    
    
    public void setDataObject(Object instance){
        this.ks = (KnapSack)instance;
    }
    
    public void init(BaseIndividual[] population) {
        
    }
    public void onStart(BaseIndividual[] population){
        setPenalizationFactor();
    }
    
    public void postEvaluate(BaseIndividual[] population, double min, double max) {
        
        if(min < 0){
            for(int ii=0;ii<population.length;++ii){
                population[ii].setFitness( population[ii].getFitness() + Math.abs(min) );
            }
        }
    }
    
    public boolean isEnd(BaseIndividual bi){
        return false;
    }
    
    
    /** Creates a new instance of PenalizationFitness */
    public PenalizationFitness() {
        super();
        penalizationFactor = 0;
    }
    
    public String toString() {
        return "with penalization";
    }
    
    
    double penalization(double sumOfCapacity) {
        
        //System.out.println("penalizationFactor=" + penalizationFactor);
        return ((sumOfCapacity - ks.getCapacity())*this.penalizationFactor);
    }
    
   /* double getMaxPrice() {
        //double ret = penalizationFactor*this.popSize;
        //System.out.println("penalizationFactor*this.popSize=" + ret);
        return  penalizationFactor*this.popSize*maxCapacity;
    }*/
    
    
    void setPenalizationFactor() {
        KnapSackItem temp;
        this.penalizationFactor = 0;
        double penalization = 0;
        
        for(Enumeration e = ks.getItems().elements();e.hasMoreElements();) {
            temp = (KnapSackItem)e.nextElement();
         //   System.out.println("temp.getPrice()=" + temp.getPrice());
         //   System.out.println("temp.getCapacity()=" + temp.getCapacity());
        //    System.out.println("temp.getPrice()/temp.getCapacity())=" + temp.getPrice()/temp.getCapacity());
            penalization = (temp.getPrice()/temp.getCapacity());
            if(this.penalizationFactor < penalization) this.penalizationFactor = penalization;
            if(maxCapacity < temp.getCapacity()) maxCapacity = temp.getCapacity();
        }
        
    }
    
    public double getEvaluation(BaseIndividual str){
        boolean[] bits = ((BinaryIndividual)str).getString();
        int i = 0;
        double sumOfcapacity = 0;
        double sumOfprice = 0;
        KnapSackItem temp;
        
        
        
        for(Enumeration e = ks.getItems().elements();e.hasMoreElements();) {
            temp = (KnapSackItem)e.nextElement();
            if(bits[i]) {
                sumOfcapacity += temp.getCapacity();
                sumOfprice += temp.getPrice();
            }
            i++;
        }
        
        
        if(sumOfcapacity <= ks.getCapacity()){
            return sumOfprice;
            // str.setSumCap(sumOfcapacity);
        } else {
            
            double fit = sumOfprice - this.penalization(sumOfcapacity); //return sumOfPrice - (MAX(P/C)*(sumOfCapacity-capacity));
            
            return fit;
            
            
            // str.setSumCap(sumOfcapacity);
        }
    }
    
    
}
