Repository /Rseslib/rseslib-3.0.1.jar:rseslib.processing.rules.AQ15OneRuleGenerator


Back

No file description

Source code

/*
 * $RCSfile: AQ15OneRuleGenerator.java,v $
 * $Revision: 1.3 $
 * $Date: 2007/08/10 14:56:50 $
 * $Author: wojna $
 * 
 * Copyright (C) 2002 - 2007 Logic Group, Institute of Mathematics, Warsaw University
 * 
 *  This file is part of Rseslib.
 *
 *  Rseslib is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Rseslib is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


package rseslib.processing.rules;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.Properties;

import rseslib.structure.data.DoubleData;
import rseslib.structure.data.DoubleDataWithDecision;
import rseslib.structure.function.booleanval.BooleanFunction;
//import rseslib.structure.rule.BooleanFunctionRule;
import rseslib.structure.rule.BooleanFunctionRule;
import rseslib.structure.rule.Rule;
import rseslib.structure.table.DoubleDataTable;
import rseslib.system.Configuration;
import rseslib.system.PropertyConfigurationException;


/**
 * AQ15RuleGenerator generates a rule.
 * Based on the AQ15 algorithm.
 *
 * @author	Cezary Tkaczyk
 */

public class AQ15OneRuleGenerator extends Configuration implements OneRuleGenerator{
	
	//TODO: Generować zbiór cięć przy urzyciu np. miary entropii. 
	//		Potem zamiast głupio generować cięcie, to korzystać z tego zbioru.
	//		rseslib.processing.classification.tree.c45.BestGainRatioDiscriminationProvider
	//TODO: Petli sie przy sprzecznych przykladach
	//TODO: Optymalizacja jakas?
	
	int    m_nNoOfDescriptors;
	double m_nMargin;
	
	/**
     * Constructor.
     *
     * @param prop                Parameters of this rule generator. If null,
     *                            parameters are loaded from the configuration directory.
     */
	public AQ15OneRuleGenerator(Properties prop) throws PropertyConfigurationException {
		super(prop);
		m_nMargin    = getDoubleProperty("margin");
	}

	private void testSelectorsAndCandidates() {
		System.out.println("----- test InequalitySelector -----");
        InequalitySelector selector1 = new InequalitySelector(1,5.2d);
        selector1.addValue(5.3d);
        InequalitySelector selector2 = new InequalitySelector(1,5.2d);
        selector2.addValue(5.1d);
        selector2.addValue(5.3d);
        selector2.addValue(5.2d);
        
        System.out.println("----- test IntervalSelector -----");
        IntervalSelector iSelector1 = new IntervalSelector(0,5.0);
        IntervalSelector iSelector2 = new IntervalSelector(1,3.5);
        IntervalSelector iSelector3 = new IntervalSelector(2,3.0);
        IntervalSelector iSelector4 = new IntervalSelector(3,1.0);
        IntervalSelector iSelector5 = new IntervalSelector(2,3.0);
        IntervalSelector iSelector6 = new IntervalSelector(3,1.0);        
        iSelector1.addValue(5.2);        
        iSelector2.addValue(3.2);
        iSelector3.addValue(4.5);
        iSelector4.addValue(1.1);
        iSelector5.addValue(5.5);        
        iSelector6.addValue(1.5);                
        System.out.println("IntervalSelector1: " + iSelector1);
        System.out.println("IntervalSelector5: " + iSelector5);
        System.out.println("compare IntervalSelector1 generality to IntervalSelector2: " 
        		+ iSelector4.compareGenerality(iSelector6));		
        
        
        System.out.println("----- test candidate -----");
        Candidate candidate1 = new Candidate();
        candidate1.add(iSelector1);
        candidate1.add(iSelector2);
        candidate1.add(iSelector3);
        candidate1.add(iSelector4);        
        System.out.println("candidate1: " + candidate1);
        Candidate candidate2 = new Candidate();
        candidate2.add(iSelector1);
        candidate2.add(iSelector2);
        candidate2.add(iSelector5);
        candidate2.add(iSelector6);        
        System.out.println("candidate2: " + candidate2);
        System.out.println("compare candidate1 generality to candidate2: " 
        		+ candidate1.compareGenerality(candidate2));
        System.out.println("compare candidate2 generality to candidate1: " 
        		+ candidate2.compareGenerality(candidate1));
        

		
	}
	
	public Rule generate(
			DoubleDataTable examples, 
			ArrayList<DoubleDataWithDecision> uncovered, 
			int k, 
			double d) {
        
		m_nNoOfDescriptors = 0;
		for(int i=0; i<examples.attributes().noOfAttr(); i++) {
			if (examples.attributes().attribute(i).isConditional())
				m_nNoOfDescriptors++;
		}
		
        DoubleDataWithDecision e_pos =
        	e_posFind(uncovered, d);
        
        DoubleDataWithDecision e_neg;
        ArrayList<Candidate> candidates = new ArrayList<Candidate>();
        candidates.add(new Candidate());
        
        while (candidatesCoverNoExamples(e_pos, examples, candidates)) {
        //while (whileCondition) {
        	// e_neg = ...
    		e_neg = e_negFind(e_pos, examples, candidates);

    		// selectors
    		Selector[] selectors = 
    			getSelectorsPosConsientNegExcluding(e_pos, e_neg);
    		
    		// update candidates with selectors
    		candidates = updateCandidatesWithSelectors(candidates, selectors);
    		
    		// removing less general
    		candidates = removeLessGeneral(candidates);

    		// retain only k best candidates
    		countPerformance(candidates, e_pos.getDecision(), examples);
    		Collections.sort(candidates);
    		
    		for (int i=candidates.size()-1; i>=k; i--)
    			candidates.remove(i);
    		
        }
        
        //testSelectorsAndCandidates();
        
        Rule rule = null;
        if (candidates.size() > 0) {
        	rule = new BooleanFunctionRule(candidates.get(0), e_pos.getDecision());
        	//System.out.println("Rule" + candidates.get(0));
        }
        return rule;
	}

	private void countPerformance(
			ArrayList<Candidate> candidates, 
			double               dec, 
			DoubleDataTable      examples) {
		
		for (int i=0; i<candidates.size(); i++) {
			candidates.get(i).performance(dec, examples);
		}
	}
	
	private boolean candidatesCoverNoExamples(
			DoubleDataWithDecision e_pos, 
			DoubleDataTable        examples,
			ArrayList<Candidate>   candidates) {			
		
		for (DoubleData e_neg : examples.getDataObjects()) {
			if (((DoubleDataWithDecision)e_neg).getDecision() != e_pos.getDecision()) {
				for (int i = 0; i < candidates.size(); i++) {
					if (candidates.get(i).booleanVal(e_neg)) {
						return true;
					}
				}

			}
		}
		return false;
	}
	
	private ArrayList<Candidate> updateCandidatesWithSelectors(
			ArrayList<Candidate> candidates, Selector[] selectors) {
		
		ArrayList<Candidate> newCandidates = 
			new ArrayList<Candidate>(candidates.size());
		
		for(int i=0; i<selectors.length; i++) {
			Iterator<Candidate> it = candidates.iterator();
			for(;it.hasNext();) {
				Candidate candidate = it.next();
				try {
					Candidate newCandidate = candidate.deeperCopy();
					newCandidate.add(selectors[i].deeperCopy());
					if (!existsEqual(newCandidates, newCandidate))
						newCandidates.add(newCandidate);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		return newCandidates;
	}
	
	private boolean existsEqual(ArrayList<Candidate> candidates, Candidate candidate) {
		Iterator<Candidate> it = candidates.iterator();
		Candidate next;
		for(;it.hasNext();) {
			next = it.next();
			int comparison = candidate.compareGenerality(next);
			if ((candidate != next) && (comparison == Selector.EQUAL))
				return true;
		}
		return false;
	}
	
	/** Retains only the most general candidates */
	private ArrayList<Candidate> removeLessGeneral(ArrayList<Candidate> candidates) {
		ArrayList<Candidate> newCandidates = new ArrayList<Candidate>();
		int ln = candidates.size();
		for(int i=0; i<ln; i++) {
			if (!existsMoreGeneral(candidates, candidates.get(i)))
				newCandidates.add(candidates.get(i));
		}
		return newCandidates;
	}
	
	/** Returns true if there exists more or equal general candidate 
	 *  in <code>candidates</code>. Considers only elements from idx to size().
	 */
	private boolean existsMoreGeneral(ArrayList<Candidate> candidates, int idx, Candidate candidate) {
		for(int i=idx; i < candidates.size(); i++) {
			int comparison = candidate.compareGenerality(candidates.get(i));
			if ((comparison == Selector.EQUAL) 
					|| (comparison == Selector.THAT_MORE_GENERAL)) {
				return true;
			}
		}
		return false;
	}
	
	/** Returns true if there exists more general candidate 
	 *  in <code>candidates</code>
	 */
	private boolean existsMoreGeneral(ArrayList<Candidate> candidates, Candidate candidate) {
		Iterator<Candidate> it = candidates.iterator();
		Candidate next;
		for(;it.hasNext();) {
			next = it.next();
			int comparison = candidate.compareGenerality(next);
			if ((candidate != next) && 
				(comparison == Selector.THAT_MORE_GENERAL)) {
					return true;
			}
		}
		return false;
	}
	
	/**
	 * Returns array of Selectors consistent with e_pos excluding e_neg
	 * @param e_pos
	 * @param e_neg
	 * @return
	 */
	private Selector[] getSelectorsPosConsientNegExcluding(
			DoubleDataWithDecision e_pos, 
			DoubleDataWithDecision e_neg) {
		
		int dissimilarity = m_nNoOfDescriptors - similarity(e_pos, e_neg);
		Selector[] selectors = new Selector[dissimilarity];

		for (int i=0, j=0; i<m_nNoOfDescriptors; i++) {
			if (e_pos.get(i) != e_neg.get(i)) {
				if (e_pos.attributes().attribute(i).isNominal()) {
					selectors[j++] = new InequalitySelector(i,e_neg.get(i));
				}
				if (e_pos.attributes().attribute(i).isNumeric()) {
					IntervalSelector selector =
						new IntervalSelector(i,e_pos.get(i));
					selector.addValue(e_neg.get(i));
					selectors[j++] = selector;
				}
			}
		}
		return selectors;
	}

	private DoubleDataWithDecision e_posFind(
			ArrayList<DoubleDataWithDecision> examples,
			double	 						  dec) {
		int count  = examples.size();
		
		int random = (int)Math.round(Math.random()*count - 0.5d);
		if (random <0) random = 0;
		if (random > count-1) random = count-1;
		
		if (examples.size() == 0) return null;
		else return examples.get(random);
	}
	/**
	 * Finds random example with decision <code>dec</code>
	 */
	private DoubleDataWithDecision e_posFind(
			DoubleDataTable        examples,
			double				   dec) {
		
		int count  = 0;
		int random = 0;
		//ArrayList<DoubleDataWithDecision> candidates = new ArrayList<DoubleDataWithDecision>();
		for (DoubleData example : examples.getDataObjects()) {
			if (((DoubleDataWithDecision)example).getDecision() == dec)
				count++;
		}
		random = (int)Math.round(Math.random()*count - 0.5d);
		if (random <0) random = 0;
		if (random > count-1) random = count-1;
		
		count = -1;
		for (DoubleData example : examples.getDataObjects()) {
			if (((DoubleDataWithDecision)example).getDecision() == dec)
				count++;
			if (count == random)
				return (DoubleDataWithDecision)example;
		}
		return null;
	}
	private DoubleDataWithDecision e_negFind(
				DoubleDataWithDecision e_pos, 
				DoubleDataTable        examples,
				ArrayList<Candidate>   candidates) {
		
    	ArrayList<DoubleDataWithDecision> e_negCandidates = 
    		new ArrayList<DoubleDataWithDecision>(100);
		for (DoubleData e_neg : examples.getDataObjects()) {
    		if (((DoubleDataWithDecision)e_neg).getDecision() != e_pos.getDecision()) {
    			for (int i=0; i<candidates.size(); i++) {
    				if (candidates.get(i).booleanVal(e_neg)) {
    					e_negCandidates.add((DoubleDataWithDecision)e_neg);
    					break;
    				}
    			}
    			
    		}
    	}
    	
    	//find e_neg the most similar to e_pos
		DoubleDataWithDecision e_neg;
    	Iterator e_negIterator = e_negCandidates.iterator();
    	DoubleDataWithDecision e_negBest = e_negCandidates.get(0);
    	int e_negBestSimilarity = similarity(e_negBest, e_pos);
    	while   (e_negIterator.hasNext()) {
    		e_neg = (DoubleDataWithDecision) e_negIterator.next();

			int similarity = similarity(e_neg, e_pos);

    		if (e_negBestSimilarity < similarity) {
    			e_negBestSimilarity = similarity;
    			e_negBest           = e_neg;
    		}
    	}
		return e_negBest;
	}
	
	private int similarity (DoubleDataWithDecision e_pos,
							 DoubleDataWithDecision e_neg) {
		int similarity = 0;
		for(int i = 0; i < m_nNoOfDescriptors; i++) {
			if (e_neg.get(i) == e_pos.get(i)) similarity++; 
		}
		return similarity;
	}
	
	
	class Candidate implements BooleanFunction, Comparable {
		private Selector[] m_nSelectors;
		private int        m_nPerformance;
		
		Candidate() {
			m_nSelectors = new Selector[m_nNoOfDescriptors];
		}
		
		public void set(Selector selector) {
			set(selector.getAttrIndex(), selector);
		}
		
		private void set(int idx, Selector selector) {
			m_nSelectors[idx] = selector;
		}
		
		public void add(Selector selector) {
			add(selector.getAttrIndex(),selector);
		}
		
		private void add(int idx, Selector selector) {
			if (m_nSelectors[idx] == null)
				set(idx,selector);
			m_nSelectors[idx].addAll(selector);
		}
			
		public int compareGenerality(Candidate candidate) {
			Selector[] thisSelectors = m_nSelectors;
			Selector[] thatSelectors = candidate.m_nSelectors;
			int thisMinusThat = 0;
			int thatMinusThis = 0;
			int common = 0;
			boolean possibleThisMoreGeneral = false;
			boolean possibleThatMoreGeneral = false;
			for (int i = 0; i < thisSelectors.length; i++) {
				if ((thisSelectors[i] == null) && (thatSelectors[i] == null)) {
				} else if (thisSelectors[i] == null) {
					thatMinusThis++;
				} else if (thatSelectors[i] == null) {
					thisMinusThat++;
				} else {
					int comparison = thisSelectors[i].compareGenerality(thatSelectors[i]);
					switch (comparison) {
					case Selector.THIS_MORE_GENERAL:
						possibleThisMoreGeneral = true;
						break;
					case Selector.THAT_MORE_GENERAL:
						possibleThatMoreGeneral = true;
						break;
					case Selector.EQUAL:
						break;
					case Selector.NOT_COMPARABLE:
						return Selector.NOT_COMPARABLE;
						//possibleThisMoreGeneral = true;						
						//possibleThatMoreGeneral = true;
					}
					common++;
				}
			}

			if ((thisMinusThat > 0) && (thatMinusThis == 0) 
					&& (!possibleThatMoreGeneral))
				return Selector.THIS_MORE_GENERAL;
			else if ((thisMinusThat == 0) && (thatMinusThis > 0)
					&& (!possibleThisMoreGeneral))
				return Selector.THAT_MORE_GENERAL;
			else if ((thisMinusThat == 0) && (thatMinusThis == 0))
				if ((!possibleThisMoreGeneral) && (!possibleThatMoreGeneral))
					return Selector.EQUAL;
				else if ((!possibleThisMoreGeneral) && (possibleThatMoreGeneral))
					return Selector.THAT_MORE_GENERAL;
				else if ((possibleThisMoreGeneral) && (!possibleThatMoreGeneral))
					return Selector.THIS_MORE_GENERAL;
				else
					return Selector.NOT_COMPARABLE;
			else
				return Selector.NOT_COMPARABLE;
		}

		public int compareGenerality2(Candidate candidate) {
			Selector[] thisSelectors = m_nSelectors;
			Selector[] thatSelectors = candidate.m_nSelectors;
			int thisMinusThat = 0;
			int thatMinusThis = 0;			
			for (int i = 0; i < thisSelectors.length; i++) {
				if ((thisSelectors[i] == null) && (thatSelectors[i] == null)) {
				} else if (thisSelectors[i] == null) {
					thatMinusThis++;
				} else if (thatSelectors[i] == null) {
					thisMinusThat++;
				} else {
					int comparison = thisSelectors[i].compareGenerality(thatSelectors[i]);
					switch (comparison) {
					case Selector.THIS_MORE_GENERAL:
						thisMinusThat++;
						break;
					case Selector.THAT_MORE_GENERAL:
						thatMinusThis++;
						break;
					case Selector.EQUAL:
						break;
					case Selector.NOT_COMPARABLE:
						return Selector.NOT_COMPARABLE;
					}
				}
			} //for
			
			if ((thisMinusThat > 0) && (thatMinusThis == 0))
				return Selector.THIS_MORE_GENERAL;
			else if ((thisMinusThat == 0) && (thatMinusThis > 0))
				return Selector.THAT_MORE_GENERAL;
			else if ((thisMinusThat == 0) && (thatMinusThis == 0))
				return Selector.EQUAL;
			else
				return Selector.NOT_COMPARABLE;
		}
		
		public boolean booleanVal(DoubleData dObj) {
			for (int i=0; i<m_nSelectors.length; i++) {
				if (m_nSelectors[i] != null) {
					if (!m_nSelectors[i].booleanVal(dObj)) return false;
				}
			}
			return true;
		}
		
		private int performance(double dec, DoubleDataTable examples) {
			// e_pos_included + e_neg_excluded
			int e_posIncluded = 0;
			int e_negExcluded = 0;
			for (DoubleData example : examples.getDataObjects()) {
				if (this.booleanVal(example)) {
					if (((DoubleDataWithDecision)example).getDecision() == dec)
						e_posIncluded++;
				}
				else {
					if (((DoubleDataWithDecision)example).getDecision() != dec)
						e_negExcluded++;
				}
			}
			
			m_nPerformance = e_posIncluded + e_negExcluded; 
			return m_nPerformance;
		}
		
		public String toString() {
			String str = new String();
			for (int i=0; i<m_nSelectors.length; i++) {
				if (m_nSelectors[i] != null) {
					str += m_nSelectors[i].toString();
				}
			}
			return str;// + "\n";
		}
		
		/** Makes deeper copy than clone(). It doesn't deep copy arrayOfDescriptors */
		public Candidate deeperCopy() {
			Candidate nw = new Candidate();
			for(int i=0;i<m_nSelectors.length; i++) {
				if (m_nSelectors[i] != null)
					nw.m_nSelectors[i] = m_nSelectors[i].deeperCopy();
			}
			return nw;
		}

		public int compareTo(Object o) throws ClassCastException {
			Candidate that = (Candidate) o;
			return -(this.m_nPerformance - that.m_nPerformance); //TODO: było bez -
		}
	}//class Candidate
	
	
	abstract class Selector implements BooleanFunction, Comparable {
		
		public static final int THIS_MORE_GENERAL = 0;
		public static final int THAT_MORE_GENERAL = 1;
		public static final int EQUAL             = 2;
		public static final int NOT_COMPARABLE    = 3;
		
		/** The index of an attribute to be tested. */
	    int m_nAttributeIndex;

	    Selector(int attrIndex) {
	    	setAttrIndex(attrIndex);
	    }
	    
		public void setAttrIndex(int attrIndex) {
			this.m_nAttributeIndex = attrIndex;
		}

		public int  getAttrIndex() {
			return m_nAttributeIndex;
		}
	    
		public int compareTo(Object o) throws ClassCastException {
			Selector selector = (Selector) o; //this may throw excption
			return (m_nAttributeIndex - selector.m_nAttributeIndex);
		}		
		
		abstract public int compareGenerality(Selector selector);
		
		abstract public void addValue(double val);
		
		abstract public void addAll(Selector selector);
		
		abstract public boolean booleanVal(DoubleData dObj);
		
		/** Makes deeper copy than clone(). Actually, now it is deep copy. */
		abstract public Selector deeperCopy();
	}
	
	class InequalitySelector extends Selector {
		
	    /** The value to be compared. */
	    ArrayList<Double> m_nAttributeValues;
	    
	    InequalitySelector(int attrIndex) {
	    	super(attrIndex);
	    	m_nAttributeValues = new ArrayList<Double>();
	    }
	    
	    InequalitySelector(int attrIndex, double attrValue) {
	    	super(attrIndex);	    	
	    	m_nAttributeValues = new ArrayList<Double>();
	    	addValue(attrValue);
	    }
	    
		public boolean booleanVal(DoubleData dObj) {
			boolean  match   = true;
			Iterator it      = m_nAttributeValues.iterator();
			Double   dObjVal = new Double(dObj.get(m_nAttributeIndex));
			for(;it.hasNext();) {
				if (dObjVal.equals(it.next()))	{
					match = false;
					break;
				}
			}
			return match;
		}
		
		
	    public void addValue(double val) {
	    	m_nAttributeValues.add(val);
	    	Collections.sort(m_nAttributeValues);
	    	makeUniqueArrayListDouble(m_nAttributeValues);
	    }

	    public void addAll(Selector sel) throws ClassCastException {
	    	InequalitySelector selector = (InequalitySelector) sel;
	    	m_nAttributeValues.addAll(selector.m_nAttributeValues);
	    	Collections.sort(m_nAttributeValues);
	    	makeUniqueArrayListDouble(m_nAttributeValues);	    	
	    }
	    
	    /** Removes not unique elements. Assumes, that list is sorted. */
	    public void makeUniqueArrayListDouble(ArrayList<Double> list) {
	    	if (list.size() != 1) {
	    		Double last  = list.get(0);
				Double[]tmp  = list.toArray(new Double[0]);
				list.clear();

				list.add(last);
				for (int i = 1; i < tmp.length; i++) {
					if (!last.equals(tmp[i])) {
						last = tmp[i];
						list.add(last);
					}
				}
	    	}
	    }
	    
	    public int compareGenerality(Selector selector) throws ClassCastException{
	    	InequalitySelector thatSelector = (InequalitySelector) selector;
	    	if (m_nAttributeIndex != thatSelector.m_nAttributeIndex) {
	    		return NOT_COMPARABLE;
	    	} else {
	    		double[] thisValues = new double[m_nAttributeValues.size()+1];
	    		for (int i=0; i<m_nAttributeValues.size(); i++) {
	    			thisValues[i] = m_nAttributeValues.get(i).doubleValue();
	    		}
	    		thisValues[m_nAttributeValues.size()] = Double.MAX_VALUE;
	    		
	    		double[] thatValues = new double[thatSelector.m_nAttributeValues.size()+1]; 
	    		for (int i=0; i<thatSelector.m_nAttributeValues.size(); i++) {
	    			thatValues[i] = thatSelector.m_nAttributeValues.get(i).doubleValue();
	    		}
	    		thatValues[thatSelector.m_nAttributeValues.size()] = Double.MAX_VALUE;
	    		
	    		int thisMinusThat = 0;
	    		int thatMinusThis = 0;
	    		int common        = 0;
	    		for(int i=0, j=0; (i<thisValues.length-1) || (j<thatValues.length-1);) {
	    			if (thisValues[i] < thatValues[j]) {
	    				i++;
	    				thisMinusThat++;
	    			}
	    			else if (thisValues[i] > thatValues[j]) {
	    				j++;
	    				thatMinusThis++;
	    			}
	    			else {
	    				i++; j++;
	    				common++;
	    			}
	    		}

	    		if ((thisMinusThat> 0) && (thatMinusThis == 0)) 
	    			return THIS_MORE_GENERAL;
	    		else if ((thisMinusThat == 0) && (thatMinusThis > 0))
	    			return THAT_MORE_GENERAL;
	    		else if ((thisMinusThat == 0) && (thatMinusThis == 0))
	    			return EQUAL;
	    		else 
	    			return NOT_COMPARABLE;
	    	}
	    }


		
		
	    /** Makes deeper copy than clone(). Actually, now it is deep copy. */
	    @Override
		public InequalitySelector deeperCopy() {
			InequalitySelector nw = new InequalitySelector(m_nAttributeIndex);
			for(int i=0; i<m_nAttributeValues.size();i++) {
				nw.m_nAttributeValues.add(new Double(m_nAttributeValues.get(i)));
			}
			return nw;
		}
		
	    public String toString() {
	    	String str;
	    	str = "(attr" + m_nAttributeIndex + " != ";
	    	Iterator it = m_nAttributeValues.iterator();
	    	if (it.hasNext()) str += it.next(); 
	    	for(;it.hasNext();) {
	    		str += ", ";
	    		str += it.next();
	    	}
	    	str += ")";
	    	return str;
	    }

	}//class InequalitySelector
	
	class IntervalSelector extends Selector {
	    
	    Double m_nLeftBound;
	    Double m_nRightBound;
	    Double m_nPositiveExample;
	    
	    	    
	    IntervalSelector(int attrIndex, double positiveExample) {
	    	super(attrIndex);
	    	m_nLeftBound  = Double.NEGATIVE_INFINITY;
	    	m_nRightBound = Double.POSITIVE_INFINITY;
	    	m_nPositiveExample = positiveExample;
	    }

	    public void addValue(double val) {
	    	//addValueWithoutMargin(val);
	    	addValueWithMargin(val, m_nMargin);
	    }
	    
	    private void addValueWithoutMargin(double val) {
	    	if ((val > m_nLeftBound) && (val < m_nRightBound)) {
	    		if (val < m_nPositiveExample)
	    			m_nLeftBound = val;
	    			
	    		if (val > m_nPositiveExample)
	    			m_nRightBound = val;
	    	}
	    }
	    
	    /**
	     * @param part is in [0;1], the percent size of margin
	     */
	    private void addValueWithMargin(double val, double part) {
	    	if ((val + (m_nPositiveExample - val)*part > m_nLeftBound) 
	    	&&  (val - (val - m_nPositiveExample)*part < m_nRightBound)) {
	    		if (val < m_nPositiveExample)
	    			m_nLeftBound = val + (m_nPositiveExample - val)*part;
	    			
	    		if (val > m_nPositiveExample)
	    			m_nRightBound = val - (val - m_nPositiveExample)*part;
	    	}
	    }
	    
	    public void addAll(Selector sel) throws ClassCastException {
	    	IntervalSelector selector = (IntervalSelector) sel;
	    	this.addValue(selector.m_nLeftBound);
	    	this.addValue(selector.m_nRightBound);
	    }

	    public int compareGenerality(Selector selector) throws ClassCastException {
	    	IntervalSelector thatSelector = (IntervalSelector) selector;
	    	
	    	if ((compareDoubles(this.m_nLeftBound, thatSelector.m_nLeftBound) == 0)
	    		&&
	    		(compareDoubles(this.m_nRightBound, thatSelector.m_nRightBound) == 0))
	    		return EQUAL;
	    	
	    	if ((compareDoubles(this.m_nLeftBound, thatSelector.m_nLeftBound) <= 0)
	    		&&
	    		(compareDoubles(this.m_nRightBound, thatSelector.m_nRightBound) >= 0))
	    		return THAT_MORE_GENERAL;
	    	

	    	if ((compareDoubles(this.m_nLeftBound, thatSelector.m_nLeftBound) >= 0)
	    		&&
	    		(compareDoubles(this.m_nRightBound, thatSelector.m_nRightBound) <= 0))
	    		return THIS_MORE_GENERAL;

	    	return NOT_COMPARABLE;
	    }
	    
	    private Double compareDoubles(Double a, Double b) {
	    	if (a.isInfinite() && b.isInfinite()) return new Double(0.0);
	    	else return a-b;
	    }
	    
		public boolean booleanVal(DoubleData dObj) {
			// maybe change Interval:
			// [m_nLeftBound + (positiveExample - m_nLeftBound)/2, etc.]
			Double   dObjVal = new Double(dObj.get(m_nAttributeIndex));
			if ((dObjVal > m_nLeftBound) && (dObjVal < m_nRightBound))
				return true;
			//if ((dObjVal > m_nLeftBound + Math.abs(m_nPositiveExample - m_nLeftBound)/2)
			//	&&	(dObjVal < m_nRightBound - Math.abs(m_nPositiveExample - m_nRightBound)/2))
			//	return true;
			return false;
		}
		
		@Override
		public String toString() {
	    	String str;
	    	str = "(attr" + m_nAttributeIndex 
	    				  + " in <" + m_nLeftBound + ", " + m_nRightBound + ">"
	    	    + ")";
	    	return str;
	    }

		@Override
		public IntervalSelector deeperCopy() {
			IntervalSelector nw = new IntervalSelector(m_nAttributeIndex, m_nPositiveExample);
			nw.m_nLeftBound     = this.m_nLeftBound;
			nw.m_nRightBound    = this.m_nRightBound;
			return nw;			
		}
	}//class IntervalSelector
}

Copyright © 2008-2011 by TunedIT
Design by luksite