source: src/main/java/weka/associations/tertius/LiteralSet.java @ 5

Last change on this file since 5 was 4, checked in by gnappo, 14 years ago

Import di weka.

File size: 10.1 KB
Line 
1/*
2 *    This program is free software; you can redistribute it and/or modify
3 *    it under the terms of the GNU General Public License as published by
4 *    the Free Software Foundation; either version 2 of the License, or
5 *    (at your option) any later version.
6 *
7 *    This program is distributed in the hope that it will be useful,
8 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 *    GNU General Public License for more details.
11 *
12 *    You should have received a copy of the GNU General Public License
13 *    along with this program; if not, write to the Free Software
14 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16
17/*
18 *    LiteralSet.java
19 *    Copyright (C) 2003 Peter A. Flach, Nicolas Lachiche
20 *
21 *    Thanks to Amelie Deltour for porting the original C code to Java
22 *    and integrating it into Weka.
23 */
24
25package weka.associations.tertius;
26
27import weka.core.Instance;
28import weka.core.Instances;
29import weka.core.RevisionHandler;
30
31import java.io.Serializable;
32import java.util.ArrayList;
33import java.util.Enumeration;
34import java.util.Iterator;
35
36/**
37 * Class representing a set of literals, being either the body or the head
38 * of a rule.
39 *
40 * @author <a href="mailto:adeltour@netcourrier.com">Amelie Deltour</a>
41 * @version $Revision: 1.7 $
42 */
43
44public abstract class LiteralSet
45  implements Serializable, Cloneable, RevisionHandler {
46 
47  /** for serialization */
48  private static final long serialVersionUID = 6094536488654503152L;
49 
50  /** Literals contained in this set. */
51  private ArrayList m_literals;
52
53  /** Last literal added to this set. */
54  private Literal m_lastLiteral;
55 
56  /** Number of instances in the data the set deals with. */
57  private int m_numInstances;
58
59  /** Set of counter-instances of this part of the rule. */
60  private ArrayList m_counterInstances;
61  /* For a body, counter-instances are the instances satisfying the body.
62   * For a head, conter-instances are the instances satisfying the negation. */
63
64  /** Counter for the number of counter-instances. */
65  private int m_counter;
66
67  /**
68   * Type of properties expressed in this set
69   * (individual or parts properties).
70   */
71  private int m_type;
72 
73  /**
74   * Constructor for a set that does not store its counter-instances.
75   */
76  public LiteralSet() {
77
78    m_literals = new ArrayList();
79    m_lastLiteral = null;
80    m_counterInstances = null;
81    m_type = -1;
82  }
83
84  /**
85   * Constructor initializing the set of counter-instances to all the instances.
86   *
87   * @param instances The dataset.
88   */
89  public LiteralSet(Instances instances) {
90
91    this();
92    m_numInstances = instances.numInstances();
93    m_counterInstances = new ArrayList(m_numInstances);
94    Enumeration enu = instances.enumerateInstances();
95    while (enu.hasMoreElements()) {
96      m_counterInstances.add(enu.nextElement());
97    }
98  }
99
100  /**
101   * Returns a shallow copy of this set.
102   * The structured is copied but the literals themselves are not copied.
103   *
104   * @return A copy of this LiteralSet.
105   */
106  public Object clone() {
107
108    Object result = null;
109    try {
110      result = super.clone();
111      /* Clone the set of literals, but not the literals themselves. */
112      ((LiteralSet) result).m_literals = (ArrayList) m_literals.clone();
113      if (m_counterInstances != null) {
114        /* Clone the set of instances, but not the instances themselves. */
115        ((LiteralSet) result).m_counterInstances 
116          = (ArrayList) m_counterInstances.clone();
117      }
118    } catch(Exception e) {
119      /* An exception is not supposed to happen here. */
120      e.printStackTrace();
121      System.exit(0);
122    }
123    return result;
124  }
125
126  /**
127   * Update the number of counter-instances of this set in the dataset.
128   * This method should be used is the set does not store its counter-instances.
129   *
130   * @param instances The dataset.
131   */
132  public void upDate(Instances instances) {
133
134    Enumeration enu = instances.enumerateInstances();
135    m_numInstances = instances.numInstances();
136    m_counter = 0;
137    while (enu.hasMoreElements()) {
138      if (this.counterInstance((Instance) enu.nextElement())) {
139        m_counter++;
140      }
141    }
142  }
143
144  /**
145   * Get the number of counter-instances of this LiteralSet.
146   *
147   * @return The number of counter-instances.
148   */
149  public int getCounterInstancesNumber() {
150
151    if (m_counterInstances != null) {
152      return m_counterInstances.size();
153    } else {
154      return m_counter;
155    }
156  }
157
158  /**
159   * Get the frequency of counter-instances of this LiteralSet in the data.
160   *
161   * @return The frequency of counter-instances.
162   */
163  public double getCounterInstancesFrequency() {
164
165    return (double) getCounterInstancesNumber() / (double) m_numInstances;
166  }
167
168  /**
169   * Test if this LiteralSet has more counter-instances than the threshold.
170   *
171   * @param minFrequency The frequency threshold.
172   * @return True if there are more counter-instances than the threshold.
173   */
174  public boolean overFrequencyThreshold(double minFrequency) {
175
176    return getCounterInstancesFrequency() >= minFrequency;
177  }
178
179  /**
180   * Test if all the intances are counter-instances.
181   *
182   * @return True if all the instances are counter-instances.
183   */
184  public boolean hasMaxCounterInstances() {
185
186    return getCounterInstancesNumber() == m_numInstances;
187  }
188
189  /**
190   * Add a Literal to this set.
191   *
192   * @param element The element to add.
193   */
194  public void addElement(Literal element) {
195
196    m_literals.add(element);
197    /* Update the last literal. */
198    m_lastLiteral = element;
199    /* Update the type in the case of individual-based learning. */
200    if (element instanceof IndividualLiteral) {
201      int type = ((IndividualLiteral) element).getType();
202      if (type > m_type) {
203        m_type = type;
204      }
205    }
206    /* Update the set of counter-instances. */
207    if (m_counterInstances != null) {
208      for (int i = m_counterInstances.size() - 1; i >= 0; i--) {
209        Instance current = (Instance) m_counterInstances.get(i);
210        if (!canKeep(current, element)) {
211          m_counterInstances.remove(i);
212        }
213      }
214    }
215  }
216
217  /**
218   * Test if this set is empty.
219   *
220   * @return True if the set is empty.
221   */
222  public final boolean isEmpty() {
223
224    return m_literals.size() == 0;
225  }
226
227  /**
228   * Give the number of literals in this set.
229   *
230   * @return The number of literals.
231   */
232  public final int numLiterals() {
233
234    return m_literals.size();
235  }
236
237  /**
238   * Enumerate the literals contained in this set.
239   *
240   * @return An Iterator for the literals.
241   */
242  public final Iterator enumerateLiterals() {
243
244    return m_literals.iterator();
245  }
246
247  /**
248   * Give the last literal added to this set.
249   *
250   * @return The last literal added.
251   */
252  public Literal getLastLiteral() {
253
254    return m_lastLiteral;
255  }
256
257  /**
258   * Test if the negation of this LiteralSet is included in another LiteralSet.
259   *
260   * @param otherSet The other LiteralSet.
261   * @return True if the negation of this LiteralSet is included in
262   * the other LiteralSet.
263   */
264  public boolean negationIncludedIn(LiteralSet otherSet) {
265
266    Iterator iter = this.enumerateLiterals();
267    while (iter.hasNext()) {
268      Literal current = (Literal) iter.next();
269      if (!otherSet.contains(current.getNegation())) {
270        return false;
271      }
272    }     
273    return true;
274  }
275
276  /**
277   * Test if this LiteralSet contains a given Literal.
278   *
279   * @param lit The literal that is looked for.
280   * @return True if this literal is contained in this LiteralSet.
281   */
282  public boolean contains(Literal lit) {
283
284    return m_literals.contains(lit);
285  }
286
287  /**
288   * Give the type of properties in this set (individual or part properties).
289   */
290  public int getType() {
291       
292    return m_type;
293  }
294
295  /**
296   * Test if an individual instance, given a part instance of this individual,
297   * is a counter-instance of this LiteralSet.
298   *
299   * @param individual The individual instance.
300   * @param part The part instance.
301   * @return True if the individual is a counter-instance.
302   */
303  public boolean counterInstance(Instance individual, Instance part) {
304    Iterator iter = this.enumerateLiterals();
305    while (iter.hasNext()) {
306      IndividualLiteral current = (IndividualLiteral) iter.next();
307      if (current.getType() == IndividualLiteral.INDIVIDUAL_PROPERTY
308          && !canKeep(individual, current))  {
309        return false;
310      } else if (current.getType() == IndividualLiteral.PART_PROPERTY
311                 && !canKeep(part, current)) {
312        return false;
313      }
314    }
315    return true;
316  }
317
318  /**
319   * Test if an instance is a counter-instance of this LiteralSet.
320   *
321   * @param instance The instance to test.
322   * @return True if the instance is a counter-instance.
323   */
324  public boolean counterInstance(Instance instance) {
325    if ((instance instanceof IndividualInstance)
326        && (m_type == IndividualLiteral.PART_PROPERTY)) {
327      /* In the case of an individual instance, all the parts of the individual
328       * have to be considered.
329       * Part properties can be found in the body only, so here we test for
330       * an instance satisfying the set.
331       * It satisfies the set if there exists a part satisfying the set.
332       */
333      Enumeration enu
334        = ((IndividualInstance) instance).getParts().enumerateInstances();
335      while (enu.hasMoreElements()) {
336        if (counterInstance(instance, (Instance) enu.nextElement())) {
337          return true;
338        }
339      }
340      return false;
341    } else {
342      /* Usual case. */
343      Iterator iter = this.enumerateLiterals();
344      while (iter.hasNext()) {
345        Literal current = (Literal) iter.next();
346        if (!canKeep(instance, current)) {
347          return false;
348        }
349      }
350      return true;
351    }
352  }
353
354  /**
355   * Test if an instance can be kept as a counter-instance,
356   * given a new literal.
357   *
358   * @param instance The instance to test.
359   * @param newLit The new literal.
360   * @return True if the instance is still a counter-instance.
361   */
362  public abstract boolean canKeep(Instance instance, Literal newLit);
363
364  /**
365   * Test if this LiteralSet is included in a rule.
366   *
367   * @param otherRule The rule to test.
368   * @return True if this set of literals is included in the rule.
369   */
370  public abstract boolean isIncludedIn(Rule otherRule);
371 
372  /**
373   * Gives a String representation for this set of literals.
374   */
375  public abstract String toString(); 
376}
377
378
379
380
381
382
383
Note: See TracBrowser for help on using the repository browser.