001: /*
002: * This program is free software; you can redistribute it and/or modify
003: * it under the terms of the GNU General Public License as published by
004: * the Free Software Foundation; either version 2 of the License, or
005: * (at your option) any later version.
006: *
007: * This program is distributed in the hope that it will be useful,
008: * but WITHOUT ANY WARRANTY; without even the implied warranty of
009: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
010: * GNU General Public License for more details.
011: *
012: * You should have received a copy of the GNU General Public License
013: * along with this program; if not, write to the Free Software
014: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
015: */
016:
017: /*
018: * RelationalLocator.java
019: * Copyright (C) 2006 University of Waikato, Hamilton, New Zealand
020: */
021:
022: package weka.core;
023:
024: /**
025: * This class locates and records the indices of relational attributes,
026: *
027: * @author fracpete (fracpete at waikato dot ac dot nz)
028: * @version $Revision: 1.2 $
029: * @see Attribute#RELATIONAL
030: */
031: public class RelationalLocator extends AttributeLocator {
032:
033: /** for serialization */
034:
035: private static final long serialVersionUID = 4646872277151854732L;
036:
037: /**
038: * Initializes the RelationalLocator with the given data.
039: *
040: * @param data the data to work on
041: */
042: public RelationalLocator(Instances data) {
043: super (data, Attribute.RELATIONAL);
044: }
045:
046: /**
047: * Initializes the RelationalLocator with the given data.
048: * Checks only the given range.
049: *
050: * @param data the data to work on
051: * @param fromIndex the first index to inspect (including)
052: * @param toIndex the last index to check (including)
053: */
054: public RelationalLocator(Instances data, int fromIndex, int toIndex) {
055: super (data, Attribute.RELATIONAL, fromIndex, toIndex);
056: }
057:
058: /**
059: * Initializes the RelationalLocator with the given data.
060: * Checks only the specified attribute indices.
061: *
062: * @param data the data to work on
063: * @param indices the attribute indices to check
064: */
065: public RelationalLocator(Instances data, int[] indices) {
066: super (data, Attribute.RELATIONAL, indices);
067: }
068:
069: /**
070: * Copies relational values contained in the instance copied to a new
071: * dataset. The Instance must already be assigned to a dataset. This
072: * dataset and the destination dataset must have the same structure.
073: *
074: * @param inst the Instance containing the relational values
075: * to copy.
076: * @param destDataset the destination set of Instances
077: * @param strAtts an AttributeLocator containing the indices of
078: * any relational attributes in the dataset.
079: */
080: public static void copyRelationalValues(Instance inst,
081: Instances destDataset, AttributeLocator strAtts) {
082:
083: if (inst.dataset() == null) {
084: throw new IllegalArgumentException(
085: "Instance has no dataset assigned!!");
086: } else if (inst.dataset().numAttributes() != destDataset
087: .numAttributes()) {
088: throw new IllegalArgumentException(
089: "Src and Dest differ in # of attributes!!");
090: }
091: copyRelationalValues(inst, true, inst.dataset(), strAtts,
092: destDataset, strAtts);
093: }
094:
095: /**
096: * Takes relational values referenced by an Instance and copies them from a
097: * source dataset to a destination dataset. The instance references are
098: * updated to be valid for the destination dataset. The instance may have the
099: * structure (i.e. number and attribute position) of either dataset (this
100: * affects where references are obtained from). Only works if the number
101: * of relational attributes is the same in both indices (implicitly these
102: * relational attributes should be semantically same but just with shifted
103: * positions).
104: *
105: * @param instance the instance containing references to relations
106: * in the source dataset that will have references
107: * updated to be valid for the destination dataset.
108: * @param instSrcCompat true if the instance structure is the same as
109: * the source, or false if it is the same as the
110: * destination (i.e. which of the relational
111: * attribute indices contains the correct
112: * locations for this instance).
113: * @param srcDataset the dataset for which the current instance
114: * relationvalue references are valid (after any
115: * position mapping if needed)
116: * @param srcLoc an AttributeLocator containing the indices of
117: * relational attributes in the source datset.
118: * @param destDataset the dataset for which the current instance
119: * relation references need to be inserted (after
120: * any position mapping if needed)
121: * @param destLoc an AttributeLocator containing the indices of
122: * relational attributes in the destination datset.
123: */
124: public static void copyRelationalValues(Instance instance,
125: boolean instSrcCompat, Instances srcDataset,
126: AttributeLocator srcLoc, Instances destDataset,
127: AttributeLocator destLoc) {
128: if (srcDataset == destDataset)
129: return;
130:
131: if (srcLoc.getAttributeIndices().length != destLoc
132: .getAttributeIndices().length)
133: throw new IllegalArgumentException(
134: "Src and Dest relational indices differ in length!!");
135:
136: if (srcLoc.getLocatorIndices().length != destLoc
137: .getLocatorIndices().length)
138: throw new IllegalArgumentException(
139: "Src and Dest locator indices differ in length!!");
140:
141: for (int i = 0; i < srcLoc.getAttributeIndices().length; i++) {
142: int instIndex = instSrcCompat ? srcLoc
143: .getActualIndex(srcLoc.getAttributeIndices()[i])
144: : destLoc.getActualIndex(destLoc
145: .getAttributeIndices()[i]);
146: Attribute src = srcDataset.attribute(srcLoc
147: .getActualIndex(srcLoc.getAttributeIndices()[i]));
148: Attribute dest = destDataset.attribute(destLoc
149: .getActualIndex(destLoc.getAttributeIndices()[i]));
150: if (!instance.isMissing(instIndex)) {
151: int valIndex = dest.addRelation(src
152: .relation((int) instance.value(instIndex)));
153: instance.setValue(instIndex, (double) valIndex);
154: }
155: }
156:
157: // recurse if necessary
158: int[] srcIndices = srcLoc.getLocatorIndices();
159: int[] destIndices = destLoc.getLocatorIndices();
160: for (int i = 0; i < srcIndices.length; i++) {
161: int index = instSrcCompat ? srcLoc
162: .getActualIndex(srcIndices[i]) : destLoc
163: .getActualIndex(destIndices[i]);
164: if (instance.isMissing(index))
165: continue;
166: Instances rel = instSrcCompat ? instance
167: .relationalValue(index) : instance
168: .relationalValue(index);
169: AttributeLocator srcRelAttsNew = srcLoc
170: .getLocator(srcIndices[i]);
171: Instances srcDatasetNew = srcRelAttsNew.getData();
172: AttributeLocator destRelAttsNew = destLoc
173: .getLocator(destIndices[i]);
174: Instances destDatasetNew = destRelAttsNew.getData();
175: for (int n = 0; n < rel.numInstances(); n++) {
176: copyRelationalValues(rel.instance(n), instSrcCompat,
177: srcDatasetNew, srcRelAttsNew, destDatasetNew,
178: destRelAttsNew);
179: }
180: }
181: }
182: }
|