0001: /*
0002: * This program is free software; you can redistribute it and/or modify
0003: * it under the terms of the GNU General Public License as published by
0004: * the Free Software Foundation; either version 2 of the License, or
0005: * (at your option) any later version.
0006: *
0007: * This program is distributed in the hope that it will be useful,
0008: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0009: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0010: * GNU General Public License for more details.
0011: *
0012: * You should have received a copy of the GNU General Public License
0013: * along with this program; if not, write to the Free Software
0014: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
0015: */
0016:
0017: /*
0018: * Capabilities.java
0019: * Copyright (C) 2006 University of Waikato, Hamilton, New Zealand
0020: */
0021:
0022: package weka.core;
0023:
0024: import weka.core.converters.ConverterUtils.DataSource;
0025:
0026: import java.io.Serializable;
0027: import java.util.Collections;
0028: import java.util.HashSet;
0029: import java.util.Iterator;
0030: import java.util.Properties;
0031: import java.util.Vector;
0032:
0033: /**
0034: * A class that describes the capabilites (e.g., handling certain types of
0035: * attributes, missing values, types of classes, etc.) of a specific
0036: * classifier. By default, the classifier is capable of nothing. This
0037: * ensures that new features have to be enabled explicitly. <p/>
0038: *
0039: * A common code fragment for making use of the capabilities in a classifier
0040: * would be this:
0041: * <pre>
0042: * public void <b>buildClassifier</b>(Instances instances) throws Exception {
0043: * // can the classifier handle the data?
0044: * getCapabilities().<b>testWithFail(instances)</b>;
0045: * ...
0046: * // possible deletion of instances with missing class labels, etc.
0047: * </pre>
0048: * For only testing a single attribute, use this:
0049: * <pre>
0050: * ...
0051: * Attribute att = instances.attribute(0);
0052: * getCapabilities().<b>testWithFail(att)</b>;
0053: * ...
0054: * </pre>
0055: * Or for testing the class attribute (uses the capabilities that are
0056: * especially for the class):
0057: * <pre>
0058: * ...
0059: * Attribute att = instances.classAttribute();
0060: * getCapabilities().<b>testWithFail(att, <i>true</i>)</b>;
0061: * ...
0062: * </pre>
0063: *
0064: * @author FracPete (fracpete at waikato dot ac dot nz)
0065: * @version $Revision: 1.20 $
0066: */
0067: public class Capabilities implements Cloneable, Serializable {
0068:
0069: /** serialversion UID */
0070: static final long serialVersionUID = -5478590032325567849L;
0071:
0072: /** the properties file for managing the tests */
0073: public final static String PROPERTIES_FILE = "weka/core/Capabilities.props";
0074:
0075: /** the actual properties */
0076: protected static Properties PROPERTIES;
0077:
0078: /** defines an attribute type */
0079: private final static int ATTRIBUTE = 1;
0080:
0081: /** defines a class type */
0082: private final static int CLASS = 2;
0083:
0084: /** defines an attribute capability */
0085: private final static int ATTRIBUTE_CAPABILITY = 4;
0086:
0087: /** defines a class capability */
0088: private final static int CLASS_CAPABILITY = 8;
0089:
0090: /** defines a other capability */
0091: private final static int OTHER_CAPABILITY = 16;
0092:
0093: /** enumeration of all capabilities */
0094: public enum Capability {
0095: // attributes
0096: /** can handle nominal attributes */
0097: NOMINAL_ATTRIBUTES(ATTRIBUTE + ATTRIBUTE_CAPABILITY,
0098: "Nominal attributes"),
0099: /** can handle binary attributes */
0100: BINARY_ATTRIBUTES(ATTRIBUTE + ATTRIBUTE_CAPABILITY,
0101: "Binary attributes"),
0102: /** can handle unary attributes */
0103: UNARY_ATTRIBUTES(ATTRIBUTE + ATTRIBUTE_CAPABILITY,
0104: "Unary attributes"),
0105: /** can handle empty nominal attributes */
0106: EMPTY_NOMINAL_ATTRIBUTES(ATTRIBUTE + ATTRIBUTE_CAPABILITY,
0107: "Empty nominal attributes"),
0108: /** can handle numeric attributes */
0109: NUMERIC_ATTRIBUTES(ATTRIBUTE + ATTRIBUTE_CAPABILITY,
0110: "Numeric attributes"),
0111: /** can handle date attributes */
0112: DATE_ATTRIBUTES(ATTRIBUTE + ATTRIBUTE_CAPABILITY,
0113: "Date attributes"),
0114: /** can handle string attributes */
0115: STRING_ATTRIBUTES(ATTRIBUTE + ATTRIBUTE_CAPABILITY,
0116: "String attributes"),
0117: /** can handle relational attributes */
0118: RELATIONAL_ATTRIBUTES(ATTRIBUTE + ATTRIBUTE_CAPABILITY,
0119: "Relational attributes"),
0120: /** can handle missing values in attributes */
0121: MISSING_VALUES(ATTRIBUTE_CAPABILITY, "Missing values"),
0122: // class
0123: /** can handle data without class attribute, eg clusterers */
0124: NO_CLASS(CLASS_CAPABILITY, "No class"),
0125: /** can handle nominal classes */
0126: NOMINAL_CLASS(CLASS + CLASS_CAPABILITY, "Nominal class"),
0127: /** can handle binary classes */
0128: BINARY_CLASS(CLASS + CLASS_CAPABILITY, "Binary class"),
0129: /** can handle unary classes */
0130: UNARY_CLASS(CLASS + CLASS_CAPABILITY, "Unary class"),
0131: /** can handle empty nominal classes */
0132: EMPTY_NOMINAL_CLASS(CLASS + CLASS_CAPABILITY,
0133: "Empty nominal class"),
0134: /** can handle numeric classes */
0135: NUMERIC_CLASS(CLASS + CLASS_CAPABILITY, "Numeric class"),
0136: /** can handle date classes */
0137: DATE_CLASS(CLASS + CLASS_CAPABILITY, "Date class"),
0138: /** can handle string classes */
0139: STRING_CLASS(CLASS + CLASS_CAPABILITY, "String class"),
0140: /** can handle relational classes */
0141: RELATIONAL_CLASS(CLASS + CLASS_CAPABILITY, "Relational class"),
0142: /** can handle missing values in class attribute */
0143: MISSING_CLASS_VALUES(CLASS_CAPABILITY, "Missing class values"),
0144: // other
0145: /** can handle multi-instance data */
0146: ONLY_MULTIINSTANCE(OTHER_CAPABILITY, "Only multi-Instance data");
0147:
0148: /** the flags for the capabilities */
0149: private int m_Flags = 0;
0150:
0151: /** the display string */
0152: private String m_Display;
0153:
0154: /**
0155: * initializes the capability with the given flags
0156: *
0157: * @param flags "meta-data" for the capability
0158: * @param display the display string (must be unique!)
0159: */
0160: private Capability(int flags, String display) {
0161: m_Flags = flags;
0162: m_Display = display;
0163: }
0164:
0165: /**
0166: * returns true if the capability is an attribute
0167: *
0168: * @return true if the capability is an attribute
0169: */
0170: public boolean isAttribute() {
0171: return ((m_Flags & ATTRIBUTE) == ATTRIBUTE);
0172: }
0173:
0174: /**
0175: * returns true if the capability is a class
0176: *
0177: * @return true if the capability is a class
0178: */
0179: public boolean isClass() {
0180: return ((m_Flags & CLASS) == CLASS);
0181: }
0182:
0183: /**
0184: * returns true if the capability is an attribute capability
0185: *
0186: * @return true if the capability is an attribute capability
0187: */
0188: public boolean isAttributeCapability() {
0189: return ((m_Flags & ATTRIBUTE_CAPABILITY) == ATTRIBUTE_CAPABILITY);
0190: }
0191:
0192: /**
0193: * returns true if the capability is a class capability
0194: *
0195: * @return true if the capability is a class capability
0196: */
0197: public boolean isOtherCapability() {
0198: return ((m_Flags & OTHER_CAPABILITY) == OTHER_CAPABILITY);
0199: }
0200:
0201: /**
0202: * returns true if the capability is a other capability
0203: *
0204: * @return true if the capability is a other capability
0205: */
0206: public boolean isClassCapability() {
0207: return ((m_Flags & CLASS_CAPABILITY) == CLASS_CAPABILITY);
0208: }
0209:
0210: /**
0211: * returns the display string of the capability
0212: *
0213: * @return the display string
0214: */
0215: public String toString() {
0216: return m_Display;
0217: }
0218: };
0219:
0220: /** the object that owns this capabilities instance */
0221: protected CapabilitiesHandler m_Owner;
0222:
0223: /** the hashset for storing the active capabilities */
0224: protected HashSet m_Capabilities;
0225:
0226: /** the hashset for storing dependent capabilities, eg for meta-classifiers */
0227: protected HashSet m_Dependencies;
0228:
0229: /** the reason why the test failed, used to throw an exception */
0230: protected Exception m_FailReason = null;
0231:
0232: /** the minimum number of instances in a dataset */
0233: protected int m_MinimumNumberInstances = 1;
0234:
0235: /** whether to perform any tests at all */
0236: protected boolean m_Test;
0237:
0238: /** whether to perform data based tests */
0239: protected boolean m_InstancesTest;
0240:
0241: /** whether to perform attribute based tests */
0242: protected boolean m_AttributeTest;
0243:
0244: /** whether to test for missing values */
0245: protected boolean m_MissingValuesTest;
0246:
0247: /** whether to test for missing class values */
0248: protected boolean m_MissingClassValuesTest;
0249:
0250: /** whether to test for minimum number of instances */
0251: protected boolean m_MinimumNumberInstancesTest;
0252:
0253: /**
0254: * initializes the capabilities for the given owner
0255: *
0256: * @param owner the object that produced this Capabilities instance
0257: */
0258: public Capabilities(CapabilitiesHandler owner) {
0259: super ();
0260:
0261: setOwner(owner);
0262: m_Capabilities = new HashSet();
0263: m_Dependencies = new HashSet();
0264:
0265: // load properties
0266: if (PROPERTIES == null) {
0267: try {
0268: PROPERTIES = Utils.readProperties(PROPERTIES_FILE);
0269: } catch (Exception e) {
0270: e.printStackTrace();
0271: PROPERTIES = new Properties();
0272: }
0273: }
0274:
0275: m_Test = Boolean.parseBoolean(PROPERTIES.getProperty("Test",
0276: "true"));
0277: m_InstancesTest = Boolean.parseBoolean(PROPERTIES.getProperty(
0278: "InstancesTest", "true"))
0279: && m_Test;
0280: m_AttributeTest = Boolean.parseBoolean(PROPERTIES.getProperty(
0281: "AttributeTest", "true"))
0282: && m_Test;
0283: m_MissingValuesTest = Boolean.parseBoolean(PROPERTIES
0284: .getProperty("MissingValuesTest", "true"))
0285: && m_Test;
0286: m_MissingClassValuesTest = Boolean.parseBoolean(PROPERTIES
0287: .getProperty("MissingClassValuesTest", "true"))
0288: && m_Test;
0289: m_MinimumNumberInstancesTest = Boolean.parseBoolean(PROPERTIES
0290: .getProperty("MinimumNumberInstancesTest", "true"))
0291: && m_Test;
0292: }
0293:
0294: /**
0295: * Creates and returns a copy of this object.
0296: *
0297: * @return a clone of this object
0298: */
0299: public Object clone() {
0300: Capabilities result;
0301:
0302: result = new Capabilities(m_Owner);
0303: result.assign(this );
0304:
0305: return result;
0306: }
0307:
0308: /**
0309: * retrieves the data from the given Capabilities object
0310: *
0311: * @param c the capabilities object to initialize with
0312: */
0313: public void assign(Capabilities c) {
0314: for (Capability cap : Capability.values()) {
0315: // capability
0316: if (c.handles(cap))
0317: enable(cap);
0318: else
0319: disable(cap);
0320: // dependency
0321: if (c.hasDependency(cap))
0322: enableDependency(cap);
0323: else
0324: disableDependency(cap);
0325: }
0326:
0327: setMinimumNumberInstances(c.getMinimumNumberInstances());
0328: }
0329:
0330: /**
0331: * performs an AND conjunction with the capabilities of the given
0332: * Capabilities object and updates itself
0333: *
0334: * @param c the capabilities to AND with
0335: */
0336: public void and(Capabilities c) {
0337: for (Capability cap : Capability.values()) {
0338: // capability
0339: if (handles(cap) && c.handles(cap))
0340: m_Capabilities.add(cap);
0341: else
0342: m_Capabilities.remove(cap);
0343: // dependency
0344: if (hasDependency(cap) && c.hasDependency(cap))
0345: m_Dependencies.add(cap);
0346: else
0347: m_Dependencies.remove(cap);
0348: }
0349:
0350: // minimum number of instances that both handlers need at least to work
0351: if (c.getMinimumNumberInstances() > getMinimumNumberInstances())
0352: setMinimumNumberInstances(c.getMinimumNumberInstances());
0353: }
0354:
0355: /**
0356: * performs an OR conjunction with the capabilities of the given
0357: * Capabilities object and updates itself
0358: *
0359: * @param c the capabilities to OR with
0360: */
0361: public void or(Capabilities c) {
0362: for (Capability cap : Capability.values()) {
0363: // capability
0364: if (handles(cap) || c.handles(cap))
0365: m_Capabilities.add(cap);
0366: else
0367: m_Capabilities.remove(cap);
0368: // dependency
0369: if (hasDependency(cap) || c.hasDependency(cap))
0370: m_Dependencies.add(cap);
0371: else
0372: m_Dependencies.remove(cap);
0373: }
0374:
0375: if (c.getMinimumNumberInstances() < getMinimumNumberInstances())
0376: setMinimumNumberInstances(c.getMinimumNumberInstances());
0377: }
0378:
0379: /**
0380: * Returns true if the currently set capabilities support at least all of
0381: * the capabiliites of the given Capabilities object (checks only the enum!)
0382: *
0383: * @param c the capabilities to support at least
0384: * @return true if all the requested capabilities are supported
0385: */
0386: public boolean supports(Capabilities c) {
0387: boolean result;
0388:
0389: result = true;
0390:
0391: for (Capability cap : Capability.values()) {
0392: if (c.handles(cap) && !handles(cap)) {
0393: result = false;
0394: break;
0395: }
0396: }
0397:
0398: return result;
0399: }
0400:
0401: /**
0402: * Returns true if the currently set capabilities support (or have a
0403: * dependency) at least all of the capabilities of the given Capabilities
0404: * object (checks only the enum!)
0405: *
0406: * @param c the capabilities (or dependencies) to support at least
0407: * @return true if all the requested capabilities are supported (or at
0408: * least have a dependency)
0409: */
0410: public boolean supportsMaybe(Capabilities c) {
0411: boolean result;
0412:
0413: result = true;
0414:
0415: for (Capability cap : Capability.values()) {
0416: if (c.handles(cap) && !(handles(cap) || hasDependency(cap))) {
0417: result = false;
0418: break;
0419: }
0420: }
0421:
0422: return result;
0423: }
0424:
0425: /**
0426: * sets the owner of this capabilities object
0427: *
0428: * @param value the new owner
0429: */
0430: public void setOwner(CapabilitiesHandler value) {
0431: m_Owner = value;
0432: }
0433:
0434: /**
0435: * returns the owner of this capabilities object
0436: *
0437: * @return the current owner of this capabilites object
0438: */
0439: public CapabilitiesHandler getOwner() {
0440: return m_Owner;
0441: }
0442:
0443: /**
0444: * sets the minimum number of instances that have to be in the dataset
0445: *
0446: * @param value the minimum number of instances
0447: */
0448: public void setMinimumNumberInstances(int value) {
0449: if (value >= 0)
0450: m_MinimumNumberInstances = value;
0451: }
0452:
0453: /**
0454: * returns the minimum number of instances that have to be in the dataset
0455: *
0456: * @return the minimum number of instances
0457: */
0458: public int getMinimumNumberInstances() {
0459: return m_MinimumNumberInstances;
0460: }
0461:
0462: /**
0463: * Returns an Iterator over the stored capabilities
0464: *
0465: * @return iterator over the current capabilities
0466: */
0467: public Iterator capabilities() {
0468: return m_Capabilities.iterator();
0469: }
0470:
0471: /**
0472: * Returns an Iterator over the stored dependencies
0473: *
0474: * @return iterator over the current dependencies
0475: */
0476: public Iterator dependencies() {
0477: return m_Dependencies.iterator();
0478: }
0479:
0480: /**
0481: * enables the given capability
0482: *
0483: * @param c the capability to enable
0484: */
0485: public void enable(Capability c) {
0486: // attributes
0487: if (c == Capability.NOMINAL_ATTRIBUTES) {
0488: enable(Capability.BINARY_ATTRIBUTES);
0489: } else if (c == Capability.BINARY_ATTRIBUTES) {
0490: enable(Capability.UNARY_ATTRIBUTES);
0491: } else if (c == Capability.UNARY_ATTRIBUTES) {
0492: enable(Capability.EMPTY_NOMINAL_ATTRIBUTES);
0493: }
0494: // class
0495: else if (c == Capability.NOMINAL_CLASS) {
0496: enable(Capability.BINARY_CLASS);
0497: } else if (c == Capability.BINARY_CLASS) {
0498: enable(Capability.UNARY_CLASS);
0499: } else if (c == Capability.UNARY_CLASS) {
0500: enable(Capability.EMPTY_NOMINAL_CLASS);
0501: }
0502:
0503: m_Capabilities.add(c);
0504: }
0505:
0506: /**
0507: * enables the dependency flag for the given capability
0508: *
0509: * @param c the capability to enable the dependency flag for
0510: */
0511: public void enableDependency(Capability c) {
0512: // attributes
0513: if (c == Capability.NOMINAL_ATTRIBUTES) {
0514: enableDependency(Capability.BINARY_ATTRIBUTES);
0515: } else if (c == Capability.BINARY_ATTRIBUTES) {
0516: enableDependency(Capability.UNARY_ATTRIBUTES);
0517: } else if (c == Capability.UNARY_ATTRIBUTES) {
0518: enableDependency(Capability.EMPTY_NOMINAL_ATTRIBUTES);
0519: }
0520: // class
0521: else if (c == Capability.NOMINAL_CLASS) {
0522: enableDependency(Capability.BINARY_CLASS);
0523: } else if (c == Capability.BINARY_CLASS) {
0524: enableDependency(Capability.UNARY_CLASS);
0525: } else if (c == Capability.UNARY_CLASS) {
0526: enableDependency(Capability.EMPTY_NOMINAL_CLASS);
0527: }
0528:
0529: m_Dependencies.add(c);
0530: }
0531:
0532: /**
0533: * enables all class types
0534: *
0535: * @see #disableAllClasses()
0536: * @see #getClassCapabilities()
0537: */
0538: public void enableAllClasses() {
0539: for (Capability cap : Capability.values()) {
0540: if (cap.isClass())
0541: enable(cap);
0542: }
0543: }
0544:
0545: /**
0546: * enables all class type dependencies
0547: *
0548: * @see #disableAllClassDependencies()
0549: * @see #getClassCapabilities()
0550: */
0551: public void enableAllClassDependencies() {
0552: for (Capability cap : Capability.values()) {
0553: if (cap.isClass())
0554: enableDependency(cap);
0555: }
0556: }
0557:
0558: /**
0559: * enables all attribute types
0560: *
0561: * @see #disableAllAttributes()
0562: * @see #getAttributeCapabilities()
0563: */
0564: public void enableAllAttributes() {
0565: for (Capability cap : Capability.values()) {
0566: if (cap.isAttribute())
0567: enable(cap);
0568: }
0569: }
0570:
0571: /**
0572: * enables all attribute type dependencies
0573: *
0574: * @see #disableAllAttributeDependencies()
0575: * @see #getAttributeCapabilities()
0576: */
0577: public void enableAllAttributeDependencies() {
0578: for (Capability cap : Capability.values()) {
0579: if (cap.isAttribute())
0580: enableDependency(cap);
0581: }
0582: }
0583:
0584: /**
0585: * disables the given capability
0586: *
0587: * @param c the capability to disable
0588: */
0589: public void disable(Capability c) {
0590: // attributes
0591: if (c == Capability.NOMINAL_ATTRIBUTES) {
0592: disable(Capability.BINARY_ATTRIBUTES);
0593: } else if (c == Capability.BINARY_ATTRIBUTES) {
0594: disable(Capability.UNARY_ATTRIBUTES);
0595: } else if (c == Capability.UNARY_ATTRIBUTES) {
0596: disable(Capability.EMPTY_NOMINAL_ATTRIBUTES);
0597: }
0598: // class
0599: else if (c == Capability.NOMINAL_CLASS) {
0600: disable(Capability.BINARY_CLASS);
0601: } else if (c == Capability.BINARY_CLASS) {
0602: disable(Capability.UNARY_CLASS);
0603: } else if (c == Capability.UNARY_CLASS) {
0604: disable(Capability.EMPTY_NOMINAL_CLASS);
0605: }
0606:
0607: m_Capabilities.remove(c);
0608: }
0609:
0610: /**
0611: * disables the dependency of the given capability
0612: *
0613: * @param c the capability to disable the dependency flag for
0614: */
0615: public void disableDependency(Capability c) {
0616: // attributes
0617: if (c == Capability.NOMINAL_ATTRIBUTES) {
0618: disableDependency(Capability.BINARY_ATTRIBUTES);
0619: } else if (c == Capability.BINARY_ATTRIBUTES) {
0620: disableDependency(Capability.UNARY_ATTRIBUTES);
0621: } else if (c == Capability.UNARY_ATTRIBUTES) {
0622: disableDependency(Capability.EMPTY_NOMINAL_ATTRIBUTES);
0623: }
0624: // class
0625: else if (c == Capability.NOMINAL_CLASS) {
0626: disableDependency(Capability.BINARY_CLASS);
0627: } else if (c == Capability.BINARY_CLASS) {
0628: disableDependency(Capability.UNARY_CLASS);
0629: } else if (c == Capability.UNARY_CLASS) {
0630: disableDependency(Capability.EMPTY_NOMINAL_CLASS);
0631: }
0632:
0633: m_Dependencies.remove(c);
0634: }
0635:
0636: /**
0637: * disables all class types
0638: *
0639: * @see #enableAllClasses()
0640: * @see #getClassCapabilities()
0641: */
0642: public void disableAllClasses() {
0643: for (Capability cap : Capability.values()) {
0644: if (cap.isClass())
0645: disable(cap);
0646: }
0647: }
0648:
0649: /**
0650: * disables all class type dependencies
0651: *
0652: * @see #enableAllClassDependencies()
0653: * @see #getClassCapabilities()
0654: */
0655: public void disableAllClassDependencies() {
0656: for (Capability cap : Capability.values()) {
0657: if (cap.isClass())
0658: disableDependency(cap);
0659: }
0660: }
0661:
0662: /**
0663: * disables all attribute types
0664: *
0665: * @see #enableAllAttributes()
0666: * @see #getAttributeCapabilities()
0667: */
0668: public void disableAllAttributes() {
0669: for (Capability cap : Capability.values()) {
0670: if (cap.isAttribute())
0671: disable(cap);
0672: }
0673: }
0674:
0675: /**
0676: * disables all attribute type dependencies
0677: *
0678: * @see #enableAllAttributeDependencies()
0679: * @see #getAttributeCapabilities()
0680: */
0681: public void disableAllAttributeDependencies() {
0682: for (Capability cap : Capability.values()) {
0683: if (cap.isAttribute())
0684: disableDependency(cap);
0685: }
0686: }
0687:
0688: /**
0689: * returns all class capabilities
0690: *
0691: * @return all capabilities regarding the class
0692: * @see #enableAllClasses()
0693: * @see #disableAllClasses()
0694: */
0695: public Capabilities getClassCapabilities() {
0696: Capabilities result;
0697:
0698: result = new Capabilities(getOwner());
0699:
0700: for (Capability cap : Capability.values()) {
0701: if (cap.isClassCapability()) {
0702: if (handles(cap))
0703: result.enable(cap);
0704: }
0705: }
0706:
0707: return result;
0708: }
0709:
0710: /**
0711: * returns all attribute capabilities
0712: *
0713: * @return all capabilities regarding attributes
0714: * @see #enableAllAttributes()
0715: * @see #disableAllAttributes()
0716: */
0717: public Capabilities getAttributeCapabilities() {
0718: Capabilities result;
0719:
0720: result = new Capabilities(getOwner());
0721:
0722: for (Capability cap : Capability.values()) {
0723: if (cap.isAttributeCapability()) {
0724: if (handles(cap))
0725: result.enable(cap);
0726: }
0727: }
0728:
0729: return result;
0730: }
0731:
0732: /**
0733: * returns all other capabilities, besides class and attribute related ones
0734: *
0735: * @return all other capabilities, besides class and attribute
0736: * related ones
0737: */
0738: public Capabilities getOtherCapabilities() {
0739: Capabilities result;
0740:
0741: result = new Capabilities(getOwner());
0742:
0743: for (Capability cap : Capability.values()) {
0744: if (cap.isOtherCapability()) {
0745: if (handles(cap))
0746: result.enable(cap);
0747: }
0748: }
0749:
0750: return result;
0751: }
0752:
0753: /**
0754: * returns true if the classifier handler has the specified capability
0755: *
0756: * @param c the capability to test
0757: * @return true if the classifier handler has the capability
0758: */
0759: public boolean handles(Capability c) {
0760: return m_Capabilities.contains(c);
0761: }
0762:
0763: /**
0764: * returns true if the classifier handler has a dependency for the specified
0765: * capability
0766: *
0767: * @param c the capability to test
0768: * @return true if the classifier handler has a dependency for the
0769: * capability
0770: */
0771: public boolean hasDependency(Capability c) {
0772: return m_Dependencies.contains(c);
0773: }
0774:
0775: /**
0776: * Checks whether there are any dependencies at all
0777: *
0778: * @return true if there is at least one dependency for a capability
0779: */
0780: public boolean hasDependencies() {
0781: return (m_Dependencies.size() > 0);
0782: }
0783:
0784: /**
0785: * returns the reason why the tests failed, is null if tests succeeded
0786: *
0787: * @return the reason why the tests failed
0788: */
0789: public Exception getFailReason() {
0790: return m_FailReason;
0791: }
0792:
0793: /**
0794: * Generates the message for, e.g., an exception. Adds the classname before the
0795: * actual message and returns that string.
0796: *
0797: * @param msg the actual content of the message, e.g., exception
0798: * @return the new message
0799: */
0800: protected String createMessage(String msg) {
0801: String result;
0802:
0803: result = "";
0804:
0805: if (getOwner() != null)
0806: result = getOwner().getClass().getName();
0807: else
0808: result = "<anonymous>";
0809:
0810: result += ": " + msg;
0811:
0812: return result;
0813: }
0814:
0815: /**
0816: * Test the given attribute, whether it can be processed by the handler,
0817: * given its capabilities. The method assumes that the specified attribute
0818: * is not the class attribute.
0819: *
0820: * @param att the attribute to test
0821: * @return true if all the tests succeeded
0822: * @see #test(Attribute, boolean)
0823: */
0824: public boolean test(Attribute att) {
0825: return test(att, false);
0826: }
0827:
0828: /**
0829: * Test the given attribute, whether it can be processed by the handler,
0830: * given its capabilities.
0831: *
0832: * @param att the attribute to test
0833: * @param isClass whether this attribute is the class attribute
0834: * @return true if all the tests succeeded
0835: * @see #m_AttributeTest
0836: */
0837: public boolean test(Attribute att, boolean isClass) {
0838: boolean result;
0839: Capability cap;
0840: Capability capBinary;
0841: Capability capUnary;
0842: Capability capEmpty;
0843: String errorStr;
0844:
0845: result = true;
0846:
0847: // shall we test the data?
0848: if (!m_AttributeTest)
0849: return result;
0850:
0851: // for exception
0852: if (isClass)
0853: errorStr = "class";
0854: else
0855: errorStr = "attributes";
0856:
0857: switch (att.type()) {
0858: case Attribute.NOMINAL:
0859: if (isClass) {
0860: cap = Capability.NOMINAL_CLASS;
0861: capBinary = Capability.BINARY_CLASS;
0862: capUnary = Capability.UNARY_CLASS;
0863: capEmpty = Capability.EMPTY_NOMINAL_CLASS;
0864: } else {
0865: cap = Capability.NOMINAL_ATTRIBUTES;
0866: capBinary = Capability.BINARY_ATTRIBUTES;
0867: capUnary = Capability.UNARY_ATTRIBUTES;
0868: capEmpty = Capability.EMPTY_NOMINAL_ATTRIBUTES;
0869: }
0870:
0871: if (handles(cap) && (att.numValues() > 2))
0872: break;
0873: else if (handles(capBinary) && (att.numValues() == 2))
0874: break;
0875: else if (handles(capUnary) && (att.numValues() == 1))
0876: break;
0877: else if (handles(capEmpty) && (att.numValues() == 0))
0878: break;
0879:
0880: if (att.numValues() == 0) {
0881: m_FailReason = new UnsupportedAttributeTypeException(
0882: createMessage("Cannot handle empty nominal "
0883: + errorStr + "!"));
0884: result = false;
0885: }
0886: if (att.numValues() == 1) {
0887: m_FailReason = new UnsupportedAttributeTypeException(
0888: createMessage("Cannot handle unary " + errorStr
0889: + "!"));
0890: result = false;
0891: } else if (att.numValues() == 2) {
0892: m_FailReason = new UnsupportedAttributeTypeException(
0893: createMessage("Cannot handle binary "
0894: + errorStr + "!"));
0895: result = false;
0896: } else {
0897: m_FailReason = new UnsupportedAttributeTypeException(
0898: createMessage("Cannot handle nominal "
0899: + errorStr + "!"));
0900: result = false;
0901: }
0902: break;
0903:
0904: case Attribute.NUMERIC:
0905: if (isClass)
0906: cap = Capability.NUMERIC_CLASS;
0907: else
0908: cap = Capability.NUMERIC_ATTRIBUTES;
0909:
0910: if (!handles(cap)) {
0911: m_FailReason = new UnsupportedAttributeTypeException(
0912: createMessage("Cannot handle numeric "
0913: + errorStr + "!"));
0914: result = false;
0915: }
0916: break;
0917:
0918: case Attribute.DATE:
0919: if (isClass)
0920: cap = Capability.DATE_CLASS;
0921: else
0922: cap = Capability.DATE_ATTRIBUTES;
0923:
0924: if (!handles(cap)) {
0925: m_FailReason = new UnsupportedAttributeTypeException(
0926: createMessage("Cannot handle date " + errorStr
0927: + "!"));
0928: result = false;
0929: }
0930: break;
0931:
0932: case Attribute.STRING:
0933: if (isClass)
0934: cap = Capability.STRING_CLASS;
0935: else
0936: cap = Capability.STRING_ATTRIBUTES;
0937:
0938: if (!handles(cap)) {
0939: m_FailReason = new UnsupportedAttributeTypeException(
0940: createMessage("Cannot handle string "
0941: + errorStr + "!"));
0942: result = false;
0943: }
0944: break;
0945:
0946: case Attribute.RELATIONAL:
0947: if (isClass)
0948: cap = Capability.RELATIONAL_CLASS;
0949: else
0950: cap = Capability.RELATIONAL_ATTRIBUTES;
0951:
0952: if (!handles(cap)) {
0953: m_FailReason = new UnsupportedAttributeTypeException(
0954: createMessage("Cannot handle relational "
0955: + errorStr + "!"));
0956: result = false;
0957: }
0958: // attributes in the relation of this attribute must be tested
0959: // separately with a different Capabilites object
0960: break;
0961:
0962: default:
0963: m_FailReason = new UnsupportedAttributeTypeException(
0964: createMessage("Cannot handle unknown attribute type '"
0965: + att.type() + "'!"));
0966: result = false;
0967: }
0968:
0969: return result;
0970: }
0971:
0972: /**
0973: * Tests the given data, whether it can be processed by the handler,
0974: * given its capabilities. Classifiers implementing the
0975: * <code>MultiInstanceCapabilitiesHandler</code> interface are checked
0976: * automatically for their multi-instance Capabilities (if no bags, then
0977: * only the bag-structure, otherwise only the first bag).
0978: *
0979: * @param data the data to test
0980: * @return true if all the tests succeeded
0981: * @see #test(Instances, int, int)
0982: */
0983: public boolean test(Instances data) {
0984: return test(data, 0, data.numAttributes() - 1);
0985: }
0986:
0987: /**
0988: * Tests a certain range of attributes of the given data, whether it can be
0989: * processed by the handler, given its capabilities. Classifiers
0990: * implementing the <code>MultiInstanceCapabilitiesHandler</code> interface
0991: * are checked automatically for their multi-instance Capabilities (if no
0992: * bags, then only the bag-structure, otherwise only the first bag).
0993: *
0994: * @param data the data to test
0995: * @param fromIndex the range of attributes - start (incl.)
0996: * @param toIndex the range of attributes - end (incl.)
0997: * @return true if all the tests succeeded
0998: * @see MultiInstanceCapabilitiesHandler
0999: * @see #m_InstancesTest
1000: * @see #m_MissingValuesTest
1001: * @see #m_MissingClassValuesTest
1002: * @see #m_MinimumNumberInstancesTest
1003: */
1004: public boolean test(Instances data, int fromIndex, int toIndex) {
1005: int i;
1006: int n;
1007: int m;
1008: Attribute att;
1009: Instance inst;
1010: boolean testClass;
1011: Capabilities cap;
1012: boolean missing;
1013: Iterator iter;
1014:
1015: // shall we test the data?
1016: if (!m_InstancesTest)
1017: return true;
1018:
1019: // no Capabilities? -> warning
1020: if ((m_Capabilities.size() == 0)
1021: || ((m_Capabilities.size() == 1) && handles(Capability.NO_CLASS)))
1022: System.err.println(createMessage("No capabilities set!"));
1023:
1024: // any attributes?
1025: if (toIndex - fromIndex < 0) {
1026: m_FailReason = new WekaException(
1027: createMessage("No attributes!"));
1028: return false;
1029: }
1030:
1031: // do wee need to test the class attribute, i.e., is the class attribute
1032: // within the range of attributes?
1033: testClass = (data.classIndex() > -1)
1034: && (data.classIndex() >= fromIndex)
1035: && (data.classIndex() <= toIndex);
1036:
1037: // attributes
1038: for (i = fromIndex; i <= toIndex; i++) {
1039: att = data.attribute(i);
1040:
1041: // class is handled separately
1042: if (i == data.classIndex())
1043: continue;
1044:
1045: // check attribute types
1046: if (!test(att))
1047: return false;
1048: }
1049:
1050: // class
1051: if (!handles(Capability.NO_CLASS) && (data.classIndex() == -1)) {
1052: m_FailReason = new UnassignedClassException(
1053: createMessage("Class attribute not set!"));
1054: return false;
1055: }
1056:
1057: // special case: no class attribute can be handled
1058: if (handles(Capability.NO_CLASS) && (data.classIndex() > -1)) {
1059: cap = getClassCapabilities();
1060: cap.disable(Capability.NO_CLASS);
1061: iter = cap.capabilities();
1062: if (!iter.hasNext()) {
1063: m_FailReason = new UnassignedClassException(
1064: createMessage("Cannot handle any class attribute!"));
1065: return false;
1066: }
1067: }
1068:
1069: if (testClass && !handles(Capability.NO_CLASS)) {
1070: att = data.classAttribute();
1071: if (!test(att, true))
1072: return false;
1073:
1074: // special handling of RELATIONAL class
1075: // TODO: store additional Capabilities for this case
1076:
1077: // missing class labels
1078: if (m_MissingClassValuesTest) {
1079: if (!handles(Capability.MISSING_CLASS_VALUES)) {
1080: for (i = 0; i < data.numInstances(); i++) {
1081: if (data.instance(i).classIsMissing()) {
1082: m_FailReason = new WekaException(
1083: createMessage("Cannot handle missing class values!"));
1084: return false;
1085: }
1086: }
1087: } else {
1088: if (m_MinimumNumberInstancesTest) {
1089: int hasClass = 0;
1090:
1091: for (i = 0; i < data.numInstances(); i++) {
1092: if (!data.instance(i).classIsMissing())
1093: hasClass++;
1094: }
1095:
1096: // not enough instances with class labels?
1097: if (hasClass < getMinimumNumberInstances()) {
1098: m_FailReason = new WekaException(
1099: createMessage("Not enough training instances with class labels (required: "
1100: + getMinimumNumberInstances()
1101: + ", provided: "
1102: + hasClass
1103: + ")!"));
1104: return false;
1105: }
1106: }
1107: }
1108: }
1109: }
1110:
1111: // missing values
1112: if (m_MissingValuesTest) {
1113: if (!handles(Capability.MISSING_VALUES)) {
1114: missing = false;
1115: for (i = 0; i < data.numInstances(); i++) {
1116: inst = data.instance(i);
1117:
1118: if (inst instanceof SparseInstance) {
1119: for (m = 0; m < inst.numValues(); m++) {
1120: n = inst.index(m);
1121:
1122: // out of scope?
1123: if (n < fromIndex)
1124: continue;
1125: if (n > toIndex)
1126: break;
1127:
1128: // skip class
1129: if (n == inst.classIndex())
1130: continue;
1131:
1132: if (inst.isMissing(n)) {
1133: missing = true;
1134: break;
1135: }
1136: }
1137: } else {
1138: for (n = fromIndex; n < toIndex; n++) {
1139: // skip class
1140: if (n == inst.classIndex())
1141: continue;
1142:
1143: if (inst.isMissing(n)) {
1144: missing = true;
1145: break;
1146: }
1147: }
1148: }
1149:
1150: if (missing) {
1151: m_FailReason = new NoSupportForMissingValuesException(
1152: createMessage("Cannot handle missing values!"));
1153: return false;
1154: }
1155: }
1156: }
1157: }
1158:
1159: // instances
1160: if (m_MinimumNumberInstancesTest) {
1161: if (data.numInstances() < getMinimumNumberInstances()) {
1162: m_FailReason = new WekaException(
1163: createMessage("Not enough training instances (required: "
1164: + getMinimumNumberInstances()
1165: + ", provided: "
1166: + data.numInstances()
1167: + ")!"));
1168: return false;
1169: }
1170: }
1171:
1172: // Multi-Instance? -> check structure (regardless of attribute range!)
1173: if (handles(Capability.ONLY_MULTIINSTANCE)) {
1174: // number of attributes?
1175: if (data.numAttributes() != 3) {
1176: m_FailReason = new WekaException(
1177: createMessage("Incorrect Multi-Instance format, must be 'bag-id, bag, class'!"));
1178: return false;
1179: }
1180:
1181: // type of attributes and position of class?
1182: if (!data.attribute(0).isNominal()
1183: || !data.attribute(1).isRelationValued()
1184: || (data.classIndex() != data.numAttributes() - 1)) {
1185: m_FailReason = new WekaException(
1186: createMessage("Incorrect Multi-Instance format, must be 'NOMINAL att, RELATIONAL att, CLASS att'!"));
1187: return false;
1188: }
1189:
1190: // check data immediately
1191: if (getOwner() instanceof MultiInstanceCapabilitiesHandler) {
1192: MultiInstanceCapabilitiesHandler handler = (MultiInstanceCapabilitiesHandler) getOwner();
1193: cap = handler.getMultiInstanceCapabilities();
1194: boolean result;
1195: if (data.numInstances() > 0)
1196: result = cap.test(data.attribute(1).relation(0));
1197: else
1198: result = cap.test(data.attribute(1).relation());
1199:
1200: if (!result) {
1201: m_FailReason = cap.m_FailReason;
1202: return false;
1203: }
1204: }
1205: }
1206:
1207: // passed all tests!
1208: return true;
1209: }
1210:
1211: /**
1212: * tests the given attribute by calling the test(Attribute,boolean) method
1213: * and throws an exception if the test fails. The method assumes that the
1214: * specified attribute is not the class attribute.
1215: *
1216: * @param att the attribute to test
1217: * @throws Exception in case the attribute doesn't pass the tests
1218: * @see #test(Attribute,boolean)
1219: */
1220: public void testWithFail(Attribute att) throws Exception {
1221: test(att, false);
1222: }
1223:
1224: /**
1225: * tests the given attribute by calling the test(Attribute,boolean) method
1226: * and throws an exception if the test fails.
1227: *
1228: * @param att the attribute to test
1229: * @param isClass whether this attribute is the class attribute
1230: * @throws Exception in case the attribute doesn't pass the tests
1231: * @see #test(Attribute,boolean)
1232: */
1233: public void testWithFail(Attribute att, boolean isClass)
1234: throws Exception {
1235: if (!test(att, isClass))
1236: throw m_FailReason;
1237: }
1238:
1239: /**
1240: * tests the given data by calling the test(Instances,int,int) method and
1241: * throws an exception if the test fails.
1242: *
1243: * @param data the data to test
1244: * @param fromIndex the range of attributes - start (incl.)
1245: * @param toIndex the range of attributes - end (incl.)
1246: * @throws Exception in case the data doesn't pass the tests
1247: * @see #test(Instances,int,int)
1248: */
1249: public void testWithFail(Instances data, int fromIndex, int toIndex)
1250: throws Exception {
1251: if (!test(data, fromIndex, toIndex))
1252: throw m_FailReason;
1253: }
1254:
1255: /**
1256: * tests the given data by calling the test(Instances) method and throws
1257: * an exception if the test fails.
1258: *
1259: * @param data the data to test
1260: * @throws Exception in case the data doesn't pass the tests
1261: * @see #test(Instances)
1262: */
1263: public void testWithFail(Instances data) throws Exception {
1264: if (!test(data))
1265: throw m_FailReason;
1266: }
1267:
1268: /**
1269: * returns a string representation of the capabilities
1270: *
1271: * @return a string representation of this object
1272: */
1273: public String toString() {
1274: Vector sorted;
1275: StringBuffer result;
1276:
1277: result = new StringBuffer();
1278:
1279: // capabilities
1280: sorted = new Vector(m_Capabilities);
1281: Collections.sort(sorted);
1282: result.append("Capabilities: " + sorted.toString() + "\n");
1283:
1284: // dependencies
1285: sorted = new Vector(m_Dependencies);
1286: Collections.sort(sorted);
1287: result.append("Dependencies: " + sorted.toString() + "\n");
1288:
1289: // other stuff
1290: result.append("min # Instance: " + getMinimumNumberInstances()
1291: + "\n");
1292:
1293: return result.toString();
1294: }
1295:
1296: /**
1297: * returns a Capabilities object specific for this data. The multi-instance
1298: * capability is not checked as well as the minimum number of instances
1299: * is not set.
1300: *
1301: * @param data the data to base the capabilities on
1302: * @return a data-specific capabilities object
1303: * @throws Exception in case an error occurrs, e.g., an unknown attribute
1304: * type
1305: */
1306: public static Capabilities forInstances(Instances data)
1307: throws Exception {
1308: return forInstances(data, false);
1309: }
1310:
1311: /**
1312: * returns a Capabilities object specific for this data. The minimum number
1313: * of instances is not set, the check for multi-instance data is optional.
1314: *
1315: * @param data the data to base the capabilities on
1316: * @param multi if true then the structure is checked, too
1317: * @return a data-specific capabilities object
1318: * @throws Exception in case an error occurrs, e.g., an unknown attribute
1319: * type
1320: */
1321: public static Capabilities forInstances(Instances data,
1322: boolean multi) throws Exception {
1323: Capabilities result;
1324: Capabilities multiInstance;
1325: int i;
1326: int n;
1327: int m;
1328: Instance inst;
1329: boolean missing;
1330:
1331: result = new Capabilities(null);
1332:
1333: // class
1334: if (data.classIndex() == -1) {
1335: result.enable(Capability.NO_CLASS);
1336: } else {
1337: switch (data.classAttribute().type()) {
1338: case Attribute.NOMINAL:
1339: if (data.classAttribute().numValues() == 1)
1340: result.enable(Capability.UNARY_CLASS);
1341: else if (data.classAttribute().numValues() == 2)
1342: result.enable(Capability.BINARY_CLASS);
1343: else
1344: result.enable(Capability.NOMINAL_CLASS);
1345: break;
1346:
1347: case Attribute.NUMERIC:
1348: result.enable(Capability.NUMERIC_CLASS);
1349: break;
1350:
1351: case Attribute.STRING:
1352: result.enable(Capability.STRING_CLASS);
1353: break;
1354:
1355: case Attribute.DATE:
1356: result.enable(Capability.DATE_CLASS);
1357: break;
1358:
1359: case Attribute.RELATIONAL:
1360: result.enable(Capability.RELATIONAL_CLASS);
1361: break;
1362:
1363: default:
1364: throw new UnsupportedAttributeTypeException(
1365: "Unknown class attribute type '"
1366: + data.classAttribute() + "'!");
1367: }
1368:
1369: // missing class values
1370: for (i = 0; i < data.numInstances(); i++) {
1371: if (data.instance(i).classIsMissing()) {
1372: result.enable(Capability.MISSING_CLASS_VALUES);
1373: break;
1374: }
1375: }
1376: }
1377:
1378: // attributes
1379: for (i = 0; i < data.numAttributes(); i++) {
1380: // skip class
1381: if (i == data.classIndex())
1382: continue;
1383:
1384: switch (data.attribute(i).type()) {
1385: case Attribute.NOMINAL:
1386: result.enable(Capability.UNARY_ATTRIBUTES);
1387: if (data.attribute(i).numValues() == 2)
1388: result.enable(Capability.BINARY_ATTRIBUTES);
1389: else if (data.attribute(i).numValues() > 2)
1390: result.enable(Capability.NOMINAL_ATTRIBUTES);
1391: break;
1392:
1393: case Attribute.NUMERIC:
1394: result.enable(Capability.NUMERIC_ATTRIBUTES);
1395: break;
1396:
1397: case Attribute.DATE:
1398: result.enable(Capability.DATE_ATTRIBUTES);
1399: break;
1400:
1401: case Attribute.STRING:
1402: result.enable(Capability.STRING_ATTRIBUTES);
1403: break;
1404:
1405: case Attribute.RELATIONAL:
1406: result.enable(Capability.RELATIONAL_ATTRIBUTES);
1407: break;
1408:
1409: default:
1410: throw new UnsupportedAttributeTypeException(
1411: "Unknown attribute type '"
1412: + data.attribute(i).type() + "'!");
1413: }
1414: }
1415:
1416: // missing values
1417: missing = false;
1418: for (i = 0; i < data.numInstances(); i++) {
1419: inst = data.instance(i);
1420:
1421: if (inst instanceof SparseInstance) {
1422: for (m = 0; m < inst.numValues(); m++) {
1423: n = inst.index(m);
1424:
1425: // skip class
1426: if (n == inst.classIndex())
1427: continue;
1428:
1429: if (inst.isMissing(n)) {
1430: missing = true;
1431: break;
1432: }
1433: }
1434: } else {
1435: for (n = 0; n < data.numAttributes(); n++) {
1436: // skip class
1437: if (n == inst.classIndex())
1438: continue;
1439:
1440: if (inst.isMissing(n)) {
1441: missing = true;
1442: break;
1443: }
1444: }
1445: }
1446:
1447: if (missing) {
1448: result.enable(Capability.MISSING_VALUES);
1449: break;
1450: }
1451: }
1452:
1453: // multi-instance data?
1454: if (multi) {
1455: if ((data.numAttributes() == 3)
1456: && (data.attribute(0).isNominal()) // bag-id
1457: && (data.attribute(1).isRelationValued()) // bag
1458: && (data.classIndex() == data.numAttributes() - 1)) {
1459: multiInstance = new Capabilities(null);
1460: multiInstance.or(result.getClassCapabilities());
1461: multiInstance.enable(Capability.NOMINAL_ATTRIBUTES);
1462: multiInstance.enable(Capability.RELATIONAL_ATTRIBUTES);
1463: multiInstance.enable(Capability.ONLY_MULTIINSTANCE);
1464: result.assign(multiInstance);
1465: }
1466: }
1467:
1468: return result;
1469: }
1470:
1471: /**
1472: * loads the given dataset and prints the Capabilities necessary to
1473: * process it. <p/>
1474: *
1475: * Valid parameters: <p/>
1476: *
1477: * -file filename <br/>
1478: * the file to load
1479: *
1480: * -c index
1481: * the explicit index of the class attribute (default: none)
1482: *
1483: * @param args the commandline arguments
1484: * @throws Exception if something goes wrong
1485: */
1486: public static void main(String[] args) throws Exception {
1487: String tmpStr;
1488: String filename;
1489: DataSource source;
1490: Instances data;
1491: int classIndex;
1492: Capabilities cap;
1493: Iterator iter;
1494:
1495: if (args.length == 0) {
1496: System.out.println("\nUsage: "
1497: + Capabilities.class.getName()
1498: + " -file <dataset> [-c <class index>]\n");
1499: return;
1500: }
1501:
1502: // get parameters
1503: tmpStr = Utils.getOption("file", args);
1504: if (tmpStr.length() == 0)
1505: throw new Exception("No file provided with option '-file'!");
1506: else
1507: filename = tmpStr;
1508:
1509: tmpStr = Utils.getOption("c", args);
1510: if (tmpStr.length() != 0) {
1511: if (tmpStr.equals("first"))
1512: classIndex = 0;
1513: else if (tmpStr.equals("last"))
1514: classIndex = -2; // last
1515: else
1516: classIndex = Integer.parseInt(tmpStr) - 1;
1517: } else {
1518: classIndex = -3; // not set
1519: }
1520:
1521: // load data
1522: source = new DataSource(filename);
1523: if (classIndex == -3)
1524: data = source.getDataSet();
1525: else if (classIndex == -2)
1526: data = source.getDataSet(source.getStructure()
1527: .numAttributes() - 1);
1528: else
1529: data = source.getDataSet(classIndex);
1530:
1531: // determine and print capabilities
1532: cap = forInstances(data);
1533: System.out.println("File: " + filename);
1534: System.out.println("Class index: "
1535: + ((data.classIndex() == -1) ? "not set" : ""
1536: + (data.classIndex() + 1)));
1537: System.out.println("Capabilities:");
1538: iter = cap.capabilities();
1539: while (iter.hasNext())
1540: System.out.println("- " + iter.next());
1541: }
1542: }
|