diff options
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/utilities')
195 files changed, 5507 insertions, 1464 deletions
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/Base64.java b/src/de/lmu/ifi/dbs/elki/utilities/Base64.java new file mode 100644 index 00000000..da3b52a7 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/Base64.java @@ -0,0 +1,100 @@ +package de.lmu.ifi.dbs.elki.utilities; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +/** + * Class to wrap various Base64 encoders that could be available. + * + * This is a rather ugly hack; it would maybe have been sensible to just import + * one of the publicly available (and fast) Base64 encoders. The expectation was + * that at some point, Oracle will acutally include a public and fast Base64 + * encoder in Java. + * + * @author Erich Schubert + */ +public final class Base64 { + /** + * Instance of sun.misc.BASE64Encoder + */ + private static Object sunj6i; + + /** + * Encode method + */ + private static Method sunj6m; + + /** + * Instance of java.util.prefs.Base64 + */ + private static Object jup6i; + + /** + * Encode method + */ + private static Method jup6m; + + // Initialize + static { + // Try Java 6 + { + try { + Class<?> c = ClassLoader.getSystemClassLoader().loadClass("sun.misc.BASE64Encoder"); + sunj6i = c.newInstance(); + sunj6m = c.getMethod("encode", byte[].class); + } + catch(Throwable e) { + // de.lmu.ifi.dbs.elki.logging.LoggingUtil.exception(e); + // Ignore. + sunj6i = null; + sunj6m = null; + } + } + // Try private class in Java6 preferences + { + try { + Class<?> c = ClassLoader.getSystemClassLoader().loadClass("java.util.prefs.Base64"); + Constructor<?> cons = c.getDeclaredConstructor(); + cons.setAccessible(true); + jup6i = cons.newInstance(); + jup6m = c.getDeclaredMethod("byteArrayToBase64", byte[].class); + jup6m.setAccessible(true); + } + catch(Throwable e) { + // de.lmu.ifi.dbs.elki.logging.LoggingUtil.exception(e); + // Ignore. + jup6i = null; + jup6m = null; + } + } + if(sunj6i == null && jup6i == null) { + de.lmu.ifi.dbs.elki.logging.LoggingUtil.warning("No usable Base64 encoders detected."); + } + } + + /** + * Encode a string as Base64. + * + * @param s Bytes to encode + * @return Result string + */ + public static final String encodeBase64(byte[] s) { + if(jup6i != null && jup6m != null) { + try { + return (String) jup6m.invoke(jup6i, s); + } + catch(Exception e) { + throw new RuntimeException("java.util.prefs.Base64 is not working."); + } + } + if(sunj6i != null && sunj6m != null) { + try { + return (String) sunj6m.invoke(sunj6i, s); + } + catch(Exception e) { + throw new RuntimeException("sun.misc.BASE64Encoder is not working."); + } + } + throw new RuntimeException("No usable Base64 encoder detected."); + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/BitsUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/BitsUtil.java new file mode 100644 index 00000000..d2dc6733 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/BitsUtil.java @@ -0,0 +1,1140 @@ +package de.lmu.ifi.dbs.elki.utilities; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.Arrays; + +/** + * Utilities for bit operations. + * + * Implementation note: words are stored in little-endian word order. This can + * be a bit confusing, because a shift-right means "left" on the word level. + * + * Naming: methods with a <code>C</code> return a copy, methods with + * <code>I</code> modify in-place. + * + * @author Erich Schubert + */ +public final class BitsUtil { + /** + * Shift factor for a long: 2^6 == 64 == Long.SIZE + */ + private static final int LONG_LOG2_SIZE = 6; + + /** + * Masking for long shifts. + */ + private static final int LONG_LOG2_MASK = 0x3f; // 6 bits + + /** + * Long with all bits set + */ + private static final long LONG_ALL_BITS = -1L; + + /** + * Allocate a new long[]. + * + * @param bits Number of bits in storage + * @return New array + */ + public static long[] zero(int bits) { + return new long[((bits - 1) >>> LONG_LOG2_SIZE) + 1]; + } + + /** + * Allocate a new long[]. + * + * @param bits Number of bits in storage + * @param init Initial value (of at most the size of a long, remaining bits + * will be 0) + * @return New array + */ + public static long[] make(int bits, long init) { + long[] v = new long[((bits - 1) >>> LONG_LOG2_SIZE) + 1]; + v[0] = init; + return v; + } + + /** + * Create a vector initialized with "bits" ones. + * + * @param bits Size + * @return new vector + */ + public static long[] ones(int bits) { + long[] v = new long[((bits - 1) >>> LONG_LOG2_SIZE) + 1]; + final int fillWords = bits >>> LONG_LOG2_SIZE; + final int fillBits = bits & LONG_LOG2_MASK; + Arrays.fill(v, 0, fillWords, LONG_ALL_BITS); + v[v.length - 1] = (1L << fillBits) - 1; + return v; + } + + /** + * Copy a bitset + * + * @param v Array to copy + * @return Copy + */ + public static long[] copy(long[] v) { + return Arrays.copyOf(v, v.length); + } + + /** + * Copy a bitset. + * + * Note: Bits beyond mincap <em>may</em> be retained! + * + * @param v Array to copy + * @param mincap Target <em>minimum</em> capacity + * @return Copy with space for at least "capacity" bits + */ + public static long[] copy(long[] v, int mincap) { + int words = ((mincap - 1) >>> LONG_LOG2_SIZE) + 1; + if(v.length == words) { + return Arrays.copyOf(v, v.length); + } + long[] ret = new long[words]; + System.arraycopy(v, 0, ret, 0, Math.min(v.length, words)); + return ret; + } + + /** + * Copy a bitset. + * + * Note: Bits beyond mincap <em>may</em> be retained! + * + * @param v Array to copy + * @param mincap Target <em>minimum</em> capacity + * @param shift Number of bits to shift left + * @return Copy with space for at least "capacity" bits + */ + public static long[] copy(long[] v, int mincap, int shift) { + int words = ((mincap - 1) >>> LONG_LOG2_SIZE) + 1; + if(v.length == words && shift == 0) { + return Arrays.copyOf(v, v.length); + } + long[] ret = new long[words]; + final int shiftWords = shift >>> LONG_LOG2_SIZE; + final int shiftBits = shift & LONG_LOG2_MASK; + // Simple case - multiple of word size + if(shiftBits == 0) { + for(int i = shiftWords; i < ret.length; i++) { + ret[i] |= v[i - shiftWords]; + } + return ret; + } + // Overlapping case + final int unshiftBits = Long.SIZE - shiftBits; + final int end = Math.min(ret.length, v.length + shiftWords) - 1; + for(int i = end; i > shiftWords; i--) { + final int src = i - shiftWords; + ret[i] |= (v[src] << shiftBits) | (v[src - 1] >>> unshiftBits); + } + ret[shiftWords] |= v[0] << shiftBits; + return ret; + } + + /** + * Compute corresponding gray code as v XOR (v >>> 1) + * + * @param v Value + * @return Gray code + */ + public static long grayC(long v) { + return v ^ (v >>> 1); + } + + /** + * Compute corresponding gray code as v XOR (v >>> 1) + * + * @param v Value + * @return Gray code + */ + public static long[] grayI(long[] v) { + // TODO: copy less + long[] t = copy(v); + shiftRightI(t, 1); + xorI(v, t); + return v; + } + + /** + * Compute the inverted gray code, v XOR (v >>> 1) XOR (v >>> 2) ... + * + * @param v Value + * @return Inverted gray code + */ + public static long invgrayC(long v) { + v ^= (v >>> 1); + v ^= (v >>> 2); + v ^= (v >>> 4); + v ^= (v >>> 8); + v ^= (v >>> 16); + v ^= (v >>> 32); + return v; + } + + /** + * Compute the inverted gray code, v XOR (v >>> 1) XOR (v >>> 2) ... + * + * @param v Value + * @return Inverted gray code + */ + public static long[] invgrayI(long[] v) { + final int last = v.length - 1; + int o; + // Sub word level: + for(o = 1; o < Long.SIZE; o <<= 1) { + for(int i = 0; i < last; i++) { + v[i] ^= (v[i] >>> o) ^ (v[i + 1] << (Long.SIZE - o)); + } + v[last] ^= (v[last] >>> o); + } + // Word level: + for(o = 1; o <= last; o <<= 1) { + for(int i = o; i <= last; i++) { + v[i - o] ^= v[i]; + } + } + return v; + } + + /** + * Test for the bitstring to be all-zero. + * + * @param v Bitstring + * @return true when all zero + */ + public static boolean isZero(long[] v) { + for(int i = 0; i < v.length; i++) { + if(v[i] != 0) { + return false; + } + } + return true; + } + + /** + * Compute the cardinality (number of set bits) + * + * @param v Value + * @return Number of bits set in long + */ + public static int cardinality(long v) { + return Long.bitCount(v); + } + + /** + * Compute the cardinality (number of set bits) + * + * Low-endian layout for the array. + * + * @param v Value + * @return Number of bits set in long[] + */ + public static long cardinality(long[] v) { + int sum = 0; + for(int i = 0; i < v.length; i++) { + sum += Long.bitCount(v[i]); + } + return sum; + } + + /** + * Invert bit number "off" in v. + * + * @param v Buffer + * @param off Offset to flip + */ + public static long flipC(long v, int off) { + v ^= (1L << off); + return v; + } + + /** + * Invert bit number "off" in v. + * + * Low-endian layout for the array. + * + * @param v Buffer + * @param off Offset to flip + */ + public static long[] flipI(long[] v, int off) { + final int wordindex = off >>> LONG_LOG2_SIZE; + v[wordindex] ^= (1L << off); + return v; + } + + /** + * Set bit number "off" in v. + * + * @param v Buffer + * @param off Offset to set + */ + public static long setC(long v, int off) { + v |= (1L << off); + return v; + } + + /** + * Set bit number "off" in v. + * + * Low-endian layout for the array. + * + * @param v Buffer + * @param off Offset to set + */ + public static long[] setI(long[] v, int off) { + final int wordindex = off >>> LONG_LOG2_SIZE; + v[wordindex] |= (1L << off); + return v; + } + + /** + * Clear bit number "off" in v. + * + * @param v Buffer + * @param off Offset to clear + */ + public static long clearC(long v, int off) { + v &= ~(1L << off); + return v; + } + + /** + * Clear bit number "off" in v. + * + * Low-endian layout for the array. + * + * @param v Buffer + * @param off Offset to clear + */ + public static long[] clearI(long[] v, int off) { + final int wordindex = off >>> LONG_LOG2_SIZE; + v[wordindex] &= ~(1L << off); + return v; + } + + /** + * Set bit number "off" in v. + * + * @param v Buffer + * @param off Offset to set + */ + public static boolean get(long v, int off) { + return (v & (1L << off)) != 0; + } + + /** + * Set bit number "off" in v. + * + * Low-endian layout for the array. + * + * @param v Buffer + * @param off Offset to set + */ + public static boolean get(long[] v, int off) { + final int wordindex = off >>> LONG_LOG2_SIZE; + return (v[wordindex] & (1L << off)) != 0; + } + + /** + * Zero the given set + * + * Low-endian layout for the array. + * + * @param v existing set + * @return array set to zero + */ + public static long[] zeroI(long[] v) { + Arrays.fill(v, 0); + return v; + } + + /** + * XOR o onto v inplace, i.e. v ^= o + * + * @param v Primary object + * @param o data to xor + * @return v + */ + public static long[] xorI(long[] v, long[] o) { + assert (o.length <= v.length) : "Bit set sizes do not agree."; + for(int i = 0; i < o.length; i++) { + v[i] ^= o[i]; + } + return v; + } + + /** + * XOR o onto v inplace, i.e. v ^= (o << off) + * + * @param v Primary object + * @param o data to or + * @param off Offset + * @return v + */ + public static long[] xorI(long[] v, long[] o, int off) { + if(off == 0) { + return xorI(v, o); + } + if(off < 0) { + throw new UnsupportedOperationException("Negative shifts are not supported."); + } + // Break shift into integers to shift and bits to shift + final int shiftWords = off >>> LONG_LOG2_SIZE; + final int shiftBits = off & LONG_LOG2_MASK; + + if(shiftWords >= v.length) { + return v; + } + // Simple case - multiple of word size + if(shiftBits == 0) { + final int end = Math.min(v.length, o.length + shiftWords); + for(int i = shiftWords; i < end; i++) { + v[i] ^= o[i - shiftWords]; + } + return v; + } + // Overlapping case + final int unshiftBits = Long.SIZE - shiftBits; + final int end = Math.min(v.length, o.length + shiftWords) - 1; + for(int i = end; i > shiftWords; i--) { + final int src = i - shiftWords; + v[i] ^= (o[src] << shiftBits) | (o[src - 1] >>> unshiftBits); + } + v[shiftWords] ^= o[0] << shiftBits; + return v; + } + + /** + * OR o onto v inplace, i.e. v |= o + * + * @param v Primary object + * @param o data to or + * @return v + */ + public static long[] orI(long[] v, long[] o) { + assert (o.length <= v.length) : "Bit set sizes do not agree."; + final int max = Math.min(v.length, o.length); + for(int i = 0; i < max; i++) { + v[i] |= o[i]; + } + return v; + } + + /** + * OR o onto v inplace, i.e. v |= (o << off) + * + * Note: Bits that are shifted outside of the size of v are discarded. + * + * @param v Primary object + * @param o data to or + * @param off Offset + * @return v + */ + public static long[] orI(long[] v, long[] o, int off) { + if(off == 0) { + return orI(v, o); + } + if(off < 0) { + throw new UnsupportedOperationException("Negative shifts are not supported."); + } + // Break shift into integers to shift and bits to shift + final int shiftWords = off >>> LONG_LOG2_SIZE; + final int shiftBits = off & LONG_LOG2_MASK; + + if(shiftWords >= v.length) { + return v; + } + // Simple case - multiple of word size + if(shiftBits == 0) { + final int end = Math.min(v.length, o.length + shiftWords); + for(int i = shiftWords; i < end; i++) { + v[i] |= o[i - shiftWords]; + } + return v; + } + // Overlapping case + final int unshiftBits = Long.SIZE - shiftBits; + final int end = Math.min(v.length, o.length + shiftWords) - 1; + for(int i = end; i > shiftWords; i--) { + final int src = i - shiftWords; + v[i] |= (o[src] << shiftBits) | (o[src - 1] >>> unshiftBits); + } + v[shiftWords] |= o[0] << shiftBits; + return v; + } + + /** + * AND o onto v inplace, i.e. v &= o + * + * @param v Primary object + * @param o data to and + * @return v + */ + public static long[] andI(long[] v, long[] o) { + int i = 0; + for(; i < o.length; i++) { + v[i] |= o[i]; + } + // Zero higher words + Arrays.fill(v, i, v.length, 0); + return v; + } + + /** + * AND o onto v inplace, i.e. v &= (o << off) + * + * @param v Primary object + * @param o data to or + * @param off Offset + * @return v + */ + public static long[] andI(long[] v, long[] o, int off) { + if(off == 0) { + return andI(v, o); + } + if(off < 0) { + throw new UnsupportedOperationException("Negative shifts are not supported."); + } + // Break shift into integers to shift and bits to shift + final int shiftWords = off >>> LONG_LOG2_SIZE; + final int shiftBits = off & LONG_LOG2_MASK; + + if(shiftWords >= v.length) { + return v; + } + // Simple case - multiple of word size + if(shiftBits == 0) { + final int end = Math.min(v.length, o.length + shiftWords); + for(int i = shiftWords; i < end; i++) { + v[i] &= o[i - shiftWords]; + } + // Clear bottom words + Arrays.fill(v, 0, shiftWords, 0); + return v; + } + // Overlapping case + final int unshiftBits = Long.SIZE - shiftBits; + final int end = Math.min(v.length, o.length + shiftWords) - 1; + Arrays.fill(v, end + 1, v.length, 0); + for(int i = end; i > shiftWords; i--) { + final int src = i - shiftWords; + v[i] &= (o[src] << shiftBits) | (o[src - 1] >>> unshiftBits); + } + v[shiftWords] &= o[0] << shiftBits; + // Clear bottom words + Arrays.fill(v, 0, shiftWords, 0); + return v; + } + + /** + * Invert v inplace. + * + * @param v Object to invert + * @return v + */ + public static long[] invertI(long[] v) { + for(int i = 0; i < v.length; i++) { + v[i] = ~v[i]; + } + return v; + } + + /** + * Shift a long[] bitset inplace. + * + * Low-endian layout for the array. + * + * @param v existing bitset + * @param off Offset to shift by + * @return Bitset + */ + public static long[] shiftRightI(long[] v, int off) { + if(off == 0) { + return v; + } + if(off < 0) { + return shiftLeftI(v, -off); + } + // Break shift into integers to shift and bits to shift + final int shiftWords = off >>> LONG_LOG2_SIZE; + final int shiftBits = off & LONG_LOG2_MASK; + + if(shiftWords >= v.length) { + return zeroI(v); + } + // Simple case - multiple of word size + if(shiftBits == 0) { + // Move whole words down + System.arraycopy(v, shiftWords, v, 0, v.length - shiftWords); + // Fill top words with zeros + Arrays.fill(v, v.length - shiftWords, v.length, 0); + return v; + } + // Overlapping case + final int unshiftBits = Long.SIZE - shiftBits; + // Bottom-up to not overlap the operations. + for(int i = 0; i < v.length - shiftWords - 1; i++) { + final int src = i + shiftWords; + v[i] = (v[src + 1] << unshiftBits) | (v[src] >>> shiftBits); + } + // The last original word + v[v.length - shiftWords - 1] = v[v.length - 1] >>> shiftBits; + // Fill whole words "lost" by the shift + Arrays.fill(v, v.length - shiftWords, v.length, 0); + return v; + } + + /** + * Shift a long[] bitset inplace. + * + * Low-endian layout for the array. + * + * @param v existing bitset + * @param off Offset to shift by + * @return Bitset + */ + public static long[] shiftLeftI(long[] v, int off) { + if(off == 0) { + return v; + } + if(off < 0) { + return shiftRightI(v, -off); + } + // Break shift into integers to shift and bits to shift + final int shiftWords = off >>> LONG_LOG2_SIZE; + final int shiftBits = off & LONG_LOG2_MASK; + + if(shiftWords >= v.length) { + return zeroI(v); + } + // Simple case - multiple of word size + if(shiftBits == 0) { + // Move whole words up + System.arraycopy(v, 0, v, shiftWords, v.length - shiftWords); + // Fill the initial words with zeros + Arrays.fill(v, 0, shiftWords, 0); + return v; + } + // Overlapping case + final int unshiftBits = Long.SIZE - shiftBits; + // Top-Down to not overlap the operations. + for(int i = v.length - 1; i > shiftWords; i--) { + final int src = i - shiftWords; + v[i] = (v[src] << shiftBits) | (v[src - 1] >>> unshiftBits); + } + v[shiftWords] = v[0] << shiftBits; + // Fill the initial words with zeros + Arrays.fill(v, 0, shiftWords, 0); + return v; + } + + /** + * Rotate a long to the right, cyclic with length len + * + * @param v Bits + * @param shift Shift value + * @param len Length + * @return cycled bit set + */ + public static long cycleRightC(long v, int shift, int len) { + if(shift == 0) { + return v; + } + if(shift < 0) { + return cycleLeftC(v, -shift, len); + } + final long ones = (1 << len) - 1; + return (((v) >>> (shift)) | ((v) << ((len) - (shift)))) & ones; + } + + /** + * Cycle a bitstring to the right. + * + * @param v Bit string + * @param shift Number of steps to cycle + * @param len Length + */ + public static long[] cycleRightI(long[] v, int shift, int len) { + long[] t = copy(v, len, len - shift); + truncateI(t, len); + shiftRightI(v, shift); + orI(v, t); + return v; + } + + /** + * Truncate a bit string to the given length (setting any higher bit to 0). + * + * @param v String to process + * @param len Length (in bits) to truncate to + */ + public static long[] truncateI(long[] v, int len) { + final int zap = (v.length * Long.SIZE) - len; + final int zapWords = (zap >>> LONG_LOG2_SIZE); + final int zapbits = zap & LONG_LOG2_MASK; + Arrays.fill(v, v.length - zapWords, v.length, 0); + if(zapbits > 0) { + v[v.length - zapWords - 1] &= (LONG_ALL_BITS >>> zapbits); + } + return v; + } + + /** + * Rotate a long to the left, cyclic with length len + * + * @param v Bits + * @param shift Shift value + * @param len Length + * @return cycled bit set + */ + public static long cycleLeftC(long v, int shift, int len) { + if(shift == 0) { + return v; + } + if(shift < 0) { + return cycleRightC(v, -shift, len); + } + final long ones = (1 << len) - 1; + return (((v) << (shift)) | ((v) >>> ((len) - (shift)))) & ones; + } + + /** + * Cycle a bitstring to the right. + * + * @param v Bit string + * @param shift Number of steps to cycle + * @param len Length + */ + public static long[] cycleLeftI(long[] v, int shift, int len) { + long[] t = copy(v, len, shift); + truncateI(t, len); + shiftRightI(v, len - shift); + orI(v, t); + return v; + } + + /** + * Convert bitset to a string consisting of "0" and "1", in high-endian order. + * + * @param v Value to process + * @return String representation + */ + public static String toString(long[] v) { + final int mag = magnitude(v); + if(v.length == 0 || mag == 0) { + return "0"; + } + final int words = ((mag - 1) >>> LONG_LOG2_SIZE) + 1; + char[] digits = new char[mag]; + + int pos = mag - 1; + for(int w = 0; w < words; w++) { + long f = 1l; + for(int i = 0; i < Long.SIZE; i++) { + digits[pos] = ((v[w] & f) == 0) ? '0' : '1'; + pos--; + f <<= 1; + if(pos < 0) { + break; + } + } + } + return new String(digits); + } + + /** + * Convert bitset to a string consisting of "0" and "1", in high-endian order. + * + * @param v Value to process + * @param minw Minimum width + * @return String representation + */ + public static String toString(long[] v, int minw) { + final int mag = Math.max(magnitude(v), minw); + if(v.length == 0 || mag == 0) { + return "0"; + } + final int words = ((mag - 1) >>> LONG_LOG2_SIZE) + 1; + char[] digits = new char[mag]; + + int pos = mag - 1; + for(int w = 0; w < words; w++) { + long f = 1l; + for(int i = 0; i < Long.SIZE; i++) { + digits[pos] = ((v[w] & f) == 0) ? '0' : '1'; + pos--; + f <<= 1; + if(pos < 0) { + break; + } + } + } + return new String(digits); + } + + /** + * Convert bitset to a string consisting of "0" and "1", in high-endian order. + * + * @param v Value to process + * @return String representation + */ + public static String toString(long v) { + final int mag = magnitude(v); + if(mag == 0) { + return "0"; + } + char[] digits = new char[mag]; + + int pos = mag - 1; + long f = 1l; + for(int i = 0; i < Long.SIZE; i++) { + digits[pos] = ((v & f) == 0) ? '0' : '1'; + pos--; + f <<= 1; + if(pos < 0) { + break; + } + } + return new String(digits); + } + + /** + * Find the number of trailing zeros. + * + * @param v Bitset + * @return Position of first set bit, -1 if no set bit was found. + */ + public static int numberOfTrailingZerosSigned(long[] v) { + for(int p = 0;; p++) { + if(p == v.length) { + return -1; + } + if(v[p] != 0) { + return Long.numberOfTrailingZeros(v[p]) + p * Long.SIZE; + } + } + } + + /** + * Find the number of trailing zeros. + * + * @param v Bitset + * @return Position of first set bit, v.length * 64 if no set bit was found. + */ + public static int numberOfTrailingZeros(long[] v) { + for(int p = 0;; p++) { + if(p == v.length) { + return p * Long.SIZE; + } + if(v[p] != 0) { + return Long.numberOfTrailingZeros(v[p]) + p * Long.SIZE; + } + } + } + + /** + * Find the number of trailing zeros. + * + * Note: this has different semantics to {@link Long#numberOfLeadingZeros} + * when the number is 0. + * + * @param v Long + * @return Position of first set bit, -1 if no set bit was found. + */ + public static int numberOfTrailingZerosSigned(long v) { + return Long.numberOfTrailingZeros(v); + } + + /** + * Find the number of trailing zeros. + * + * Note: this is the same as {@link Long#numberOfTrailingZeros} + * + * @param v Long + * @return Position of first set bit, 64 if no set bit was found. + */ + public static int numberOfTrailingZeros(long v) { + return Long.numberOfTrailingZeros(v); + } + + /** + * Find the number of leading zeros. + * + * @param v Bitset + * @return Position of first set bit, -1 if no set bit was found. + */ + public static int numberOfLeadingZerosSigned(long[] v) { + for(int p = 0, ip = v.length - 1;; p++, ip--) { + if(p == v.length) { + return -1; + } + if(v[ip] != 0) { + return Long.numberOfLeadingZeros(v[ip]) + p * Long.SIZE; + } + } + } + + /** + * Find the number of leading zeros. + * + * @param v Bitset + * @return Position of first set bit, v.length * 64 if no set bit was found. + */ + public static int numberOfLeadingZeros(long[] v) { + for(int p = 0, ip = v.length - 1;; p++, ip--) { + if(p == v.length) { + return p * Long.SIZE; + } + if(v[ip] != 0) { + return Long.numberOfLeadingZeros(v[ip]) + p * Long.SIZE; + } + } + } + + /** + * Find the number of leading zeros; -1 if all zero + * + * Note: this has different semantics to {@link Long#numberOfLeadingZeros} + * when the number is 0. + * + * @param v Bitset + * @return Position of first set bit, -1 if no set bit was found. + */ + public static int numberOfLeadingZerosSigned(long v) { + if(v == 0) { + return -1; + } + return Long.numberOfLeadingZeros(v); + } + + /** + * Find the number of leading zeros; 64 if all zero + * + * Note: this the same as {@link Long#numberOfLeadingZeros}. + * + * @param v Bitset + * @return Position of first set bit, 64 if no set bit was found. + */ + public static int numberOfLeadingZeros(long v) { + return Long.numberOfLeadingZeros(v); + } + + /** + * Find the previous set bit. + * + * @param v Values to process + * @param start Start position (inclusive) + * @return Position of previous set bit, or -1. + */ + public static int previousSetBit(long[] v, int start) { + if(start == -1) { + return -1; + } + int wordindex = start >>> LONG_LOG2_SIZE; + if(wordindex >= v.length) { + return magnitude(v) - 1; + } + // Initial word + final int off = Long.SIZE - 1 - (start & LONG_LOG2_MASK); + long cur = v[wordindex] & (LONG_ALL_BITS >>> off); + for(;;) { + if(cur != 0) { + return (wordindex + 1) * Long.SIZE - 1 - Long.numberOfLeadingZeros(cur); + } + if(wordindex == 0) { + return -1; + } + wordindex--; + cur = v[wordindex]; + } + } + + /** + * Find the previous clear bit. + * + * @param v Values to process + * @param start Start position (inclusive) + * @return Position of previous clear bit, or -1. + */ + public static int previousClearBit(long[] v, int start) { + if(start == -1) { + return -1; + } + int wordindex = start >>> LONG_LOG2_SIZE; + if(wordindex >= v.length) { + return magnitude(v); + } + final int off = Long.SIZE + 1 - (start & LONG_LOG2_MASK); + // Initial word + long cur = ~v[wordindex] & (LONG_ALL_BITS >>> off); + for(;;) { + if(cur != 0) { + return (wordindex + 1) * Long.SIZE - 1 - Long.numberOfTrailingZeros(cur); + } + if(wordindex == 0) { + return -1; + } + wordindex--; + cur = ~v[wordindex]; + } + } + + /** + * Find the next set bit. + * + * @param v Value to process + * @param start Start position (inclusive) + * @return Position of next set bit, or -1. + */ + public static int nextSetBit(long[] v, int start) { + int wordindex = start >>> LONG_LOG2_SIZE; + if(wordindex >= v.length) { + return -1; + } + + // Initial word + long cur = v[wordindex] & (LONG_ALL_BITS << start); + for(;;) { + if(cur != 0) { + return (wordindex * Long.SIZE) + Long.numberOfTrailingZeros(cur); + } + wordindex++; + if(wordindex == v.length) { + return -1; + } + cur = v[wordindex]; + } + } + + /** + * Find the next clear bit. + * + * @param v Value to process + * @param start Start position (inclusive) + * @return Position of next clear bit, or -1. + */ + public static int nextClearBit(long[] v, int start) { + int wordindex = start >>> LONG_LOG2_SIZE; + if(wordindex >= v.length) { + return -1; + } + + // Initial word + long cur = ~v[wordindex] & (LONG_ALL_BITS << start); + for(; wordindex < v.length;) { + if(cur != 0) { + return (wordindex * Long.SIZE) + Long.numberOfTrailingZeros(cur); + } + wordindex++; + cur = ~v[wordindex]; + } + return -1; + } + + /** + * The magnitude is the position of the highest bit set + * + * @param v Vector v + * @return position of highest bit set, or 0. + */ + public static int magnitude(long[] v) { + final int l = numberOfLeadingZerosSigned(v); + if(l < 0) { + return 0; + } + return capacity(v) - l; + } + + /** + * The magnitude is the position of the highest bit set + * + * @param v Vector v + * @return position of highest bit set, or 0. + */ + public static int magnitude(long v) { + final int l = numberOfLeadingZerosSigned(v); + if(l < 0) { + return 0; + } + return Long.SIZE - l; + } + + /** + * Capacity of the vector v. + * + * @param v Vector v + * @return Capacity + */ + public static int capacity(long[] v) { + return v.length * Long.SIZE; + } + + /** + * Compare two bitsets. + * + * @param x First bitset + * @param y Second bitset + * @return Comparison result + */ + public static int compare(long[] x, long[] y) { + int p = Math.min(x.length, y.length) - 1; + for(int i = x.length - 1; i > p; i--) { + if(x[i] != 0) { + return +1; + } + } + for(int i = y.length - 1; i > p; i--) { + if(y[i] != 0) { + return -1; + } + } + for(; p >= 0; p--) { + final long xp = x[p]; + final long yp = y[p]; + if(xp != yp) { + if(xp < 0) { + if(yp < 0) { + return (yp < xp) ? -1 : ((yp == xp) ? 0 : 1); + } + else { + return +1; + } + } + else { + if(yp < 0) { + return -1; + } + else { + return (xp < yp) ? -1 : ((xp == yp) ? 0 : 1); + } + } + } + } + return 0; + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/ClassGenericsUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/ClassGenericsUtil.java index 2c81fbf9..bdd9924f 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/ClassGenericsUtil.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/ClassGenericsUtil.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -68,6 +68,11 @@ public final class ClassGenericsUtil { private static final Logging logger = Logging.getLogger(ClassGenericsUtil.class); /** + * Class loader. + */ + private static final ClassLoader loader = ClassLoader.getSystemClassLoader(); + + /** * Name for a static "parameterize" factory method. */ public static final String FACTORY_METHOD_NAME = "parameterize"; @@ -93,11 +98,11 @@ public final class ClassGenericsUtil { T instance; try { try { - instance = type.cast(Class.forName(className).newInstance()); + instance = type.cast(loader.loadClass(className).newInstance()); } catch(ClassNotFoundException e) { // try package of type - instance = type.cast(Class.forName(type.getPackage().getName() + "." + className).newInstance()); + instance = type.cast(loader.loadClass(type.getPackage().getName() + "." + className).newInstance()); } } catch(InstantiationException e) { @@ -144,11 +149,11 @@ public final class ClassGenericsUtil { // (probably not because generics are implemented via erasure. try { try { - instance = ((Class<T>) type).cast(Class.forName(className).newInstance()); + instance = ((Class<T>) type).cast(loader.loadClass(className).newInstance()); } catch(ClassNotFoundException e) { // try package of type - instance = ((Class<T>) type).cast(Class.forName(type.getPackage().getName() + "." + className).newInstance()); + instance = ((Class<T>) type).cast(loader.loadClass(type.getPackage().getName() + "." + className).newInstance()); } } catch(InstantiationException e) { diff --git a/src/de/lmu/ifi/dbs/elki/utilities/ConstantObject.java b/src/de/lmu/ifi/dbs/elki/utilities/ConstantObject.java index 6d8f2f78..9c24c500 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/ConstantObject.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/ConstantObject.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/DatabaseUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/DatabaseUtil.java index 199c1048..23eba080 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/DatabaseUtil.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/DatabaseUtil.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -256,8 +256,8 @@ public final class DatabaseUtil { } } NV factory = assumeVectorField(database).getFactory(); - NV min = factory.newInstance(mins); - NV max = factory.newInstance(maxs); + NV min = factory.newNumberVector(mins); + NV max = factory.newNumberVector(maxs); return new Pair<NV, NV>(min, max); } @@ -316,7 +316,7 @@ public final class DatabaseUtil { } /** - * Guess a potentially label-like representation. + * Guess a potentially label-like representation, preferring class labels. * * @param database * @return string representation diff --git a/src/de/lmu/ifi/dbs/elki/utilities/ELKIServiceLoader.java b/src/de/lmu/ifi/dbs/elki/utilities/ELKIServiceLoader.java new file mode 100644 index 00000000..b9a79d4a --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/ELKIServiceLoader.java @@ -0,0 +1,207 @@ +package de.lmu.ifi.dbs.elki.utilities; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; + +import de.lmu.ifi.dbs.elki.logging.Logging; +import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; + +/** + * Class that emulates the behavior of an java ServiceLoader, except that the + * classes are <em>not</em> automatically instantiated. This is more lazy, but + * also we need to do the instantiations our way with the parameterizable API. + * + * @author Erich Schubert + */ +public class ELKIServiceLoader implements Iterator<Class<?>> { + /** + * Class logger. + */ + private static final Logging logger = Logging.getLogger(ELKIServiceLoader.class); + + /** + * Prefix for the ELKI functionality discovery. + */ + public static final String PREFIX = "META-INF/elki/"; + + /** + * Comment character + */ + public static final char COMMENT_CHAR = '#'; + + /** + * Parent class + */ + private Class<?> parent; + + /** + * Classloader + */ + private ClassLoader cl; + + /** + * Enumeration of configuration files + */ + private Enumeration<URL> configfiles; + + /** + * Current iterator + */ + private Iterator<Class<?>> curiter = null; + + /** + * Next class to return + */ + private Class<?> nextclass; + + /** + * Constructor. + * + * @param parent Parent class + * @param cl Classloader to use + */ + public ELKIServiceLoader(Class<?> parent, ClassLoader cl) { + this.parent = parent; + this.cl = cl; + } + + /** + * Constructor, using the system class loader. + * + * @param parent Parent class + */ + public ELKIServiceLoader(Class<?> parent) { + this(parent, ClassLoader.getSystemClassLoader()); + getServiceFiles(parent); + } + + /** + * Get services files for a given class. + * + * @param parent Parent class + */ + private void getServiceFiles(Class<?> parent) { + try { + String fullName = PREFIX + parent.getName(); + configfiles = cl.getResources(fullName); + } + catch(IOException x) { + throw new AbortException("Could not load service configuration files.", x); + } + } + + @Override + public boolean hasNext() { + if(nextclass != null) { + return true; + } + // Find next iterator + while((curiter == null) || !curiter.hasNext()) { + if(!configfiles.hasMoreElements()) { + return false; + } + curiter = parseFile(configfiles.nextElement()); + } + nextclass = curiter.next(); + return true; + } + + private Iterator<Class<?>> parseFile(URL nextElement) { + ArrayList<Class<?>> classes = new ArrayList<Class<?>>(); + try { + BufferedReader r = new BufferedReader(new InputStreamReader(nextElement.openStream(), "utf-8")); + while(parseLine(r.readLine(), classes, nextElement)) { + // Continue + } + } + catch(IOException x) { + throw new AbortException("Error reading configuration file", x); + } + return classes.iterator(); + } + + private boolean parseLine(String line, ArrayList<Class<?>> classes, URL nextElement) throws IOException { + if(line == null) { + return false; + } + // Ignore comments, trim whitespace + { + int begin = 0; + int end = line.indexOf(COMMENT_CHAR); + if(end < 0) { + end = line.length(); + } + while(begin < end && line.charAt(begin) == ' ') { + begin++; + } + while(end - 1 > begin && line.charAt(end - 1) == ' ') { + end--; + } + if(begin > 0 || end < line.length()) { + line = line.substring(begin, end); + } + } + if(line.length() <= 0) { + return true; // Empty/comment lines are okay, continue + } + // Try to load the class + try { + Class<?> cls = cl.loadClass(line); + // Should not happen. Check anyway. + if(cls == null) { + assert (cls != null); + return true; + } + if(parent.isAssignableFrom(cls)) { + classes.add(cls); + } + else { + logger.warning("Class " + line + " does not implement " + parent + " but listed in service file " + nextElement); + } + } + catch(ClassNotFoundException e) { + logger.warning("Class not found: " + line + "; listed in service file " + nextElement, e); + } + return true; + } + + @Override + public Class<?> next() { + Class<?> ret = nextclass; + nextclass = null; + return ret; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/FileUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/FileUtil.java index 5d2a6a83..8c1c7fc7 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/FileUtil.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/FileUtil.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/FormatUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/FormatUtil.java index e26a9a49..c61fdb10 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/FormatUtil.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/FormatUtil.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -34,7 +34,6 @@ import java.util.List; import java.util.Locale; import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix; -import de.lmu.ifi.dbs.elki.math.linearalgebra.MatrixLike; import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector; /** @@ -47,6 +46,11 @@ public final class FormatUtil { public static final NumberFormat NF = NumberFormat.getInstance(Locale.US); /** + * Number Formatter (0 digits) for output purposes. + */ + public static final NumberFormat NF0 = NumberFormat.getInstance(Locale.US); + + /** * Number Formatter (2 digits) for output purposes. */ public static final NumberFormat NF2 = NumberFormat.getInstance(Locale.US); @@ -70,6 +74,9 @@ public final class FormatUtil { NF.setMinimumFractionDigits(0); NF.setMaximumFractionDigits(10); NF.setGroupingUsed(false); + NF0.setMinimumFractionDigits(0); + NF0.setMaximumFractionDigits(0); + NF0.setGroupingUsed(false); NF2.setMinimumFractionDigits(2); NF2.setMaximumFractionDigits(2); NF2.setGroupingUsed(false); @@ -595,7 +602,7 @@ public final class FormatUtil { * @return a string representation of this matrix */ // TODO: in use? - public static String format(MatrixLike<?> m, int w, int d) { + public static String format(Matrix m, int w, int d) { DecimalFormat format = new DecimalFormat(); format.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US)); format.setMinimumIntegerDigits(1); @@ -624,13 +631,46 @@ public final class FormatUtil { } /** + * Returns a string representation of this matrix. + * + * @param w column width + * @param d number of digits after the decimal + * @return a string representation of this matrix + */ + // TODO: in use? + public static String format(Vector v, int w, int d) { + DecimalFormat format = new DecimalFormat(); + format.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US)); + format.setMinimumIntegerDigits(1); + format.setMaximumFractionDigits(d); + format.setMinimumFractionDigits(d); + format.setGroupingUsed(false); + + int width = w + 1; + StringBuffer msg = new StringBuffer(); + msg.append("\n"); // start on new line. + for(int i = 0; i < v.getDimensionality(); i++) { + String s = format.format(v.get(i)); // format the number + int padding = Math.max(1, width - s.length()); // At _least_ 1 + // space + for(int k = 0; k < padding; k++) { + msg.append(' '); + } + msg.append(s); + } + // msg.append("\n"); + + return msg.toString(); + } + + /** * Returns a string representation of this matrix. In each line the specified * String <code>pre</code> is prefixed. * * @param pre the prefix of each line * @return a string representation of this matrix */ - public static String format(MatrixLike<?> m, String pre) { + public static String format(Matrix m, String pre) { StringBuffer output = new StringBuffer(); output.append(pre).append("[\n").append(pre); for(int i = 0; i < m.getRowDimensionality(); i++) { @@ -719,13 +759,34 @@ public final class FormatUtil { /** * Returns a string representation of this matrix. In each line the specified + * String <code>pre</code> is prefixed. + * + * @param pre the prefix of each line + * @return a string representation of this matrix + */ + public static String format(Vector v, String pre) { + StringBuffer output = new StringBuffer(); + output.append(pre).append("[\n").append(pre); + for(int j = 0; j < v.getDimensionality(); j++) { + output.append(" ").append(v.get(j)); + if(j < v.getDimensionality() - 1) { + output.append(","); + } + } + output.append("]\n").append(pre); + + return (output.toString()); + } + + /** + * Returns a string representation of this matrix. In each line the specified * String <code>pre<\code> is prefixed. * * @param nf number format for output accuracy * @param pre the prefix of each line * @return a string representation of this matrix */ - public static String format(MatrixLike<?> m, String pre, NumberFormat nf) { + public static String format(Matrix m, String pre, NumberFormat nf) { if(nf == null) { return FormatUtil.format(m, pre); } diff --git a/src/de/lmu/ifi/dbs/elki/utilities/HandlerList.java b/src/de/lmu/ifi/dbs/elki/utilities/HandlerList.java index 02630233..8b5fcaca 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/HandlerList.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/HandlerList.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/InspectionUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/InspectionUtil.java index 67dad564..66ecde64 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/InspectionUtil.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/InspectionUtil.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,23 +23,27 @@ package de.lmu.ifi.dbs.elki.utilities; along with this program. If not, see <http://www.gnu.org/licenses/>. */ +import gnu.trove.set.hash.THashSet; + import java.io.File; import java.io.IOException; -import java.lang.ref.WeakReference; import java.lang.reflect.Modifier; +import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; import java.util.Iterator; import java.util.List; -import java.util.Stack; -import java.util.Vector; +import java.util.WeakHashMap; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.logging.LoggingUtil; +import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ClassParameter; +import de.lmu.ifi.dbs.elki.utilities.pairs.Pair; /** * A collection of inspection-related utility functions. @@ -50,25 +54,32 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ClassParameter; */ public class InspectionUtil { /** + * Class logger + */ + private static final Logging logger = Logging.getLogger(InspectionUtil.class); + + /** * Default package ignores. */ private static final String[] DEFAULT_IGNORES = { - // Sun Java + // Sun Java "java.", "com.sun.", - // Batik classes + // Batik classes "org.apache.", - // W3C / SVG / XML classes + // W3C / SVG / XML classes "org.w3c.", "org.xml.", "javax.xml.", - // JUnit + // JUnit "org.junit.", "junit.", "org.hamcrest.", - // Eclipse + // Eclipse "org.eclipse.", - // ApiViz + // ApiViz "org.jboss.apiviz.", - // JabRef + // JabRef "spin.", "osxadapter.", "antlr.", "ca.odell.", "com.jgoodies.", "com.michaelbaranov.", "com.mysql.", "gnu.dtools.", "net.sf.ext.", "net.sf.jabref.", "org.antlr.", "org.gjt.", "org.java.plugin.", "org.jempbox.", "org.pdfbox.", "wsi.ra.", - // Wrappers don't have important own parameters, they just set some defaults - "experimentalcode.shared.wrapper." }; + // GNU trove + "gnu.trove.", + // + }; /** * If we have a non-static classpath, we do more extensive scanning for user @@ -88,7 +99,15 @@ public class InspectionUtil { NONSTATIC_CLASSPATH = hasnonstatic; } - private static WeakReference<List<Class<?>>> CLASS_CACHE = new WeakReference<List<Class<?>>>(null); + /** + * Weak hash map for class lookups + */ + private static WeakHashMap<Class<?>, List<Class<?>>> CLASS_CACHE = new WeakHashMap<Class<?>, List<Class<?>>>(); + + /** + * (Non-weak) cache for all "frequently scanned" classes. + */ + private static List<Class<?>> MASTER_CACHE = null; /** * Cached version of "findAllImplementations". For Parameterizable classes @@ -98,29 +117,15 @@ public class InspectionUtil { * @return Found implementations */ public static List<Class<?>> cachedFindAllImplementations(Class<?> c) { - if (c == null) { + if(c == null) { return Collections.emptyList(); } - if(InspectionUtilFrequentlyScanned.class.isAssignableFrom(c)) { - List<Class<?>> cache = CLASS_CACHE.get(); - if(cache == null) { - cache = findAllImplementations(InspectionUtilFrequentlyScanned.class, false); - CLASS_CACHE = new WeakReference<List<Class<?>>>(cache); - } - ArrayList<Class<?>> list = new ArrayList<Class<?>>(); - for(Class<?> cls : cache) { - if(c.isAssignableFrom(cls)) { - list.add(cls); - } - } - return list; - } - else { - // Need to scan - not cached. - // LoggingUtil.logExpensive(Level.FINE, - // "Slow scan for implementations: "+c.getName()); - return findAllImplementations(c, false); + List<Class<?>> res = CLASS_CACHE.get(c); + if(res == null) { + res = findAllImplementations(c, false); + CLASS_CACHE.put(c, res); } + return res; } /** @@ -133,71 +138,107 @@ public class InspectionUtil { * @return List of found classes. */ public static List<Class<?>> findAllImplementations(Class<?> c, boolean everything) { - String[] classpath = System.getProperty("java.class.path").split(System.getProperty("path.separator")); - return findAllImplementations(classpath, c, DEFAULT_IGNORES, everything); + ArrayList<Class<?>> list = new ArrayList<Class<?>>(); + // Add all from service files (i.e. jars) + { + Iterator<Class<?>> iter = new ELKIServiceLoader(c); + while(iter.hasNext()) { + list.add(iter.next()); + } + } + if(!InspectionUtil.NONSTATIC_CLASSPATH) { + if(list.size() == 0) { + logger.warning("No implementations for " + c.getName() + " were found using index files."); + } + } + else { + // Duplicate checking + THashSet<Class<?>> dupes = new THashSet<Class<?>>(list); + // Scan for additional ones in class path + Iterator<Class<?>> iter; + // If possible, reuse an existing scan result + if(InspectionUtilFrequentlyScanned.class.isAssignableFrom(c)) { + iter = getFrequentScan(); + } + else { + iter = slowScan(c).iterator(); + } + while(iter.hasNext()) { + Class<?> cls = iter.next(); + // skip abstract / private classes. + if(!everything && (Modifier.isInterface(cls.getModifiers()) || Modifier.isAbstract(cls.getModifiers()) || Modifier.isPrivate(cls.getModifiers()))) { + continue; + } + if(c.isAssignableFrom(cls) && !dupes.contains(cls)) { + list.add(cls); + dupes.add(cls); + } + } + } + return list; } /** - * Find all implementations of a given class. + * Get (or create) the result of a scan for any "frequent scanned" class. * - * @param classpath Classpath to use (JARs and folders supported) - * @param c Class restriction - * @param ignorepackages List of packages to ignore - * @param everything include interfaces, abstract and private classes - * @return List of found classes. + * @return Scan result */ - public static List<Class<?>> findAllImplementations(String[] classpath, Class<?> c, String[] ignorepackages, boolean everything) { - // Collect iterators - Vector<Iterable<String>> iters = new Vector<Iterable<String>>(classpath.length); - for(String path : classpath) { - File p = new File(path); - if(path.endsWith(".jar")) { - iters.add(new JarClassIterator(path)); - } - else if(p.isDirectory()) { - iters.add(new DirClassIterator(p)); - } + private static Iterator<Class<?>> getFrequentScan() { + if(MASTER_CACHE == null) { + MASTER_CACHE = slowScan(InspectionUtilFrequentlyScanned.class); } + return MASTER_CACHE.iterator(); + } + /** + * Perform a full (slow) scan for classes. + * + * @param cond Class to include + * @return List with the scan result + */ + private static List<Class<?>> slowScan(Class<?> cond) { ArrayList<Class<?>> res = new ArrayList<Class<?>>(); - ClassLoader cl = ClassLoader.getSystemClassLoader(); - for(Iterable<String> iter : iters) { - for(String classname : iter) { - boolean ignore = false; - for(String pkg : ignorepackages) { - if(classname.startsWith(pkg)) { - ignore = true; - break; - } - } - if(ignore) { - continue; - } - try { - Class<?> cls = cl.loadClass(classname); - // skip abstract / private classes. - if(!everything && (Modifier.isInterface(cls.getModifiers()) || Modifier.isAbstract(cls.getModifiers()) || Modifier.isPrivate(cls.getModifiers()))) { - continue; + try { + ClassLoader cl = ClassLoader.getSystemClassLoader(); + Enumeration<URL> cps = cl.getResources(""); + while(cps.hasMoreElements()) { + URL u = cps.nextElement(); + // Scan file sources only. + if(u.getProtocol() == "file") { + Iterator<String> it = new DirClassIterator(new File(u.getFile()), DEFAULT_IGNORES); + while(it.hasNext()) { + String classname = it.next(); + try { + Class<?> cls = cl.loadClass(classname); + // skip classes where we can't get a full name. + if(cls.getCanonicalName() == null) { + continue; + } + // Implements the right interface? + if(cond != null && !cond.isAssignableFrom(cls)) { + continue; + } + res.add(cls); + } + catch(ClassNotFoundException e) { + continue; + } + catch(NoClassDefFoundError e) { + continue; + } + catch(Exception e) { + continue; + } + catch(Error e) { + continue; + } } - // skip classes where we can't get a full name. - if(cls.getCanonicalName() == null) { - continue; - } - if(c.isAssignableFrom(cls)) { - res.add(cls); - } - } - catch(ClassNotFoundException e) { - continue; - } - catch(NoClassDefFoundError e) { - continue; - } - catch(Exception e) { - continue; } } } + catch(IOException e) { + logger.exception(e); + } Collections.sort(res, new ClassSorter()); return res; } @@ -205,21 +246,27 @@ public class InspectionUtil { /** * Class to iterate over a Jar file. * + * Note: this is currently unused, as we now require all jar files to include + * an index in the form of service-style files in META-INF/elki/ + * * @author Erich Schubert * * @apiviz.exclude */ - static class JarClassIterator implements Iterator<String>, Iterable<String> { + static class JarClassIterator implements IterableIterator<String> { private Enumeration<JarEntry> jarentries; private String ne; + private String[] ignorepackages; + /** * Constructor from Jar file. * * @param path Jar file entries to iterate over. */ - public JarClassIterator(String path) { + public JarClassIterator(String path, String[] ignorepackages) { + this.ignorepackages = ignorepackages; try { JarFile jf = new JarFile(path); this.jarentries = jf.entries(); @@ -244,13 +291,18 @@ public class InspectionUtil { * @return next entry or null */ private String findNext() { - while(jarentries.hasMoreElements()) { + nextfile: while(jarentries.hasMoreElements()) { JarEntry je = jarentries.nextElement(); String name = je.getName(); if(name.endsWith(".class")) { - String classname = name.substring(0, name.length() - ".class".length()); + String classname = name.substring(0, name.length() - ".class".length()).replace('/', '.'); + for(String pkg : ignorepackages) { + if(classname.startsWith(pkg)) { + continue nextfile; + } + } if(classname.endsWith(ClassParameter.FACTORY_POSTFIX) || !classname.contains("$")) { - return classname.replace("/", "."); + return classname.replace('/', '.'); } } } @@ -283,73 +335,92 @@ public class InspectionUtil { * * @apiviz.exclude */ - static class DirClassIterator implements Iterator<String>, Iterable<String> { + static class DirClassIterator implements IterableIterator<String> { + private static final String CLASS_EXT = ".class"; + + private static final String FACTORY_FILE_EXT = ClassParameter.FACTORY_POSTFIX + CLASS_EXT; + + private static final int CLASS_EXT_LENGTH = CLASS_EXT.length(); + private String prefix; - private Stack<File> set = new Stack<File>(); + private ArrayList<String> files = new ArrayList<String>(100); + + private ArrayList<Pair<File, String>> folders = new ArrayList<Pair<File, String>>(100); - private String cur; + private String[] ignorepackages; /** * Constructor from Directory * * @param path Directory to iterate over */ - public DirClassIterator(File path) { + public DirClassIterator(File path, String[] ignorepackages) { + this.ignorepackages = ignorepackages; this.prefix = path.getAbsolutePath(); - this.set.push(path); - this.cur = findNext(); + if(prefix.charAt(prefix.length() - 1) != File.separatorChar) { + prefix = prefix + File.separatorChar; + } + + this.folders.add(new Pair<File, String>(path, "")); } @Override public boolean hasNext() { - // Do we have a next entry? - return (cur != null); + if(files.size() == 0) { + findNext(); + } + return (files.size() > 0); } /** - * Find the next entry, since we need to skip some jar file entries. - * - * @return next entry or null + * Find the next entry, since we need to skip some directories. */ - private String findNext() { - while(set.size() > 0) { - File f = set.pop(); + private void findNext() { + while(folders.size() > 0) { + Pair<File, String> pair = folders.remove(folders.size() - 1); // recurse into directories - if(f.isDirectory()) { - // TODO: do not recurse into ignored packages!. - for(File newf : f.listFiles()) { - set.push(newf); - } - continue; - } - String name = f.getAbsolutePath(); - if(name.startsWith(prefix)) { - int l = prefix.length(); - if(name.charAt(l) == File.separatorChar) { - l += 1; - } - name = name.substring(l); - } - else { - LoggingUtil.warning("I was expecting all directories to start with '" + prefix + "' but '" + name + "' did not."); - } - if(name.endsWith(".class")) { - String classname = name.substring(0, name.length() - ".class".length()); - if(classname.endsWith(ClassParameter.FACTORY_POSTFIX) || !classname.contains("$")) { - return classname.replace(File.separator, "."); + if(pair.first.isDirectory()) { + nextfile: for(String localname : pair.first.list()) { + // Ignore unix-hidden files/dirs + if(localname.charAt(0) == '.') { + continue; + } + // Classes + if(localname.endsWith(CLASS_EXT)) { + if(localname.indexOf('$') >= 0) { + if(!localname.endsWith(FACTORY_FILE_EXT)) { + continue; + } + } + files.add(pair.second + localname.substring(0, localname.length() - CLASS_EXT_LENGTH)); + continue; + } + // Recurse into directories + File newf = new File(pair.first, localname); + if(newf.isDirectory()) { + String newpref = pair.second + localname + '.'; + for(String ignore : ignorepackages) { + if(ignore.equals(newpref)) { + continue nextfile; + } + } + folders.add(new Pair<File, String>(newf, newpref)); + } } } } - return null; } @Override public String next() { - // Return the previously stored entry. - String ret = this.cur; - this.cur = findNext(); - return ret; + if(files.size() == 0) { + findNext(); + } + if(files.size() > 0) { + return files.remove(files.size() - 1); + } + return null; } @Override diff --git a/src/de/lmu/ifi/dbs/elki/utilities/InspectionUtilFrequentlyScanned.java b/src/de/lmu/ifi/dbs/elki/utilities/InspectionUtilFrequentlyScanned.java index b666e077..11ea1da8 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/InspectionUtilFrequentlyScanned.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/InspectionUtilFrequentlyScanned.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/QueryStatistic.java b/src/de/lmu/ifi/dbs/elki/utilities/QueryStatistic.java index b5afc32b..91acad87 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/QueryStatistic.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/QueryStatistic.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/Util.java b/src/de/lmu/ifi/dbs/elki/utilities/Util.java index fcaca269..6f79c1fa 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/Util.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/Util.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,21 +23,20 @@ package de.lmu.ifi.dbs.elki.utilities; along with this program. If not, see <http://www.gnu.org/licenses/>. */ +import gnu.trove.map.hash.TIntFloatHashMap; + import java.io.PrintStream; -import java.util.AbstractCollection; import java.util.ArrayList; import java.util.BitSet; -import java.util.Collection; -import java.util.HashMap; +import java.util.Comparator; import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.Random; -import java.util.Set; import java.util.StringTokenizer; import de.lmu.ifi.dbs.elki.data.DoubleVector; import de.lmu.ifi.dbs.elki.data.SparseFloatVector; +import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayLikeUtil; /** * This class collects various static helper methods. @@ -50,34 +49,6 @@ import de.lmu.ifi.dbs.elki.data.SparseFloatVector; */ public final class Util { /** - * Returns the prefix of the specified fileName (i.e. the name of the file - * without extension). - * - * @param fileName the name of the file - * @return the prefix of the specified fileName - */ - public static String getFilePrefix(final String fileName) { - final int index = fileName.lastIndexOf(Character.getNumericValue('.')); - if(index < 0) { - return fileName; - } - return fileName.substring(0, index); - } - - /** - * Returns a new String array containing the same objects as are contained in - * the given array. - * - * @param array an array to copy - * @return the copied array - */ - public static String[] copy(String[] array) { - String[] copy = new String[array.length]; - System.arraycopy(array, 0, copy, 0, array.length); - return copy; - } - - /** * Returns a new double array containing the same objects as are contained in * the given array. * @@ -91,49 +62,6 @@ public final class Util { } /** - * Returns the unboxed double array of the given Object Double array. - * - * @param array the array to be unboxed - * @return the unboxed double array - */ - public static double[] unbox(Double[] array) { - double[] unboxed = new double[array.length]; - // noinspection ManualArrayCopy - for(int i = 0; i < unboxed.length; i++) { - unboxed[i] = array[i]; - } - return unboxed; - } - - /** - * Returns the unboxed double array of the given Object Number array. - * - * @param array the array to be unboxed - * @return the unboxed double array - */ - public static double[] unbox(Number[] array) { - double[] unboxed = new double[array.length]; - for(int i = 0; i < unboxed.length; i++) { - unboxed[i] = array[i].doubleValue(); - } - return unboxed; - } - - /** - * Returns the unboxed float array of the given Object Number array. - * - * @param array the array to be unboxed - * @return the unboxed float array - */ - public static float[] unboxToFloat(Number[] array) { - float[] unboxed = new float[array.length]; - for(int i = 0; i < unboxed.length; i++) { - unboxed[i] = array[i].floatValue(); - } - return unboxed; - } - - /** * Returns a new <code>Double</code> array initialized to the values * represented by the specified <code>String</code> and separated by comma, as * performed by the <code>valueOf</code> method of class <code>Double</code>. @@ -148,81 +76,7 @@ public final class Util { String d = tokenizer.nextToken(); result.add(Double.parseDouble(d)); } - return unbox(result.toArray(new Double[result.size()])); - } - - /** - * Returns a new <code>Float</code> array initialized to the values - * represented by the specified <code>String</code> and separated by comma, as - * performed by the <code>valueOf</code> method of class <code>Float</code>. - * - * @param s the string to be parsed. - * @return a new <code>Float</code> array represented by s - */ - public static float[] parseFloats(String s) { - List<Float> result = new ArrayList<Float>(); - StringTokenizer tokenizer = new StringTokenizer(s, ","); - while(tokenizer.hasMoreTokens()) { - String d = tokenizer.nextToken(); - result.add(Float.parseFloat(d)); - } - return unboxToFloat(result.toArray(new Float[result.size()])); - } - - /** - * Converts the specified list of double objects to a list of float objects. - * - * @param values the list of double objects to be converted - * @return the converted list of float objects - */ - public static List<Float> convertToFloat(List<Double> values) { - List<Float> result = new ArrayList<Float>(values.size()); - for(Double value : values) { - result.add(new Float(value)); - } - return result; - } - - /** - * Converts the specified array of doubles to an array of floats. - * - * @param values the array of doubles to be converted - * @return the converted array of floats - */ - public static float[] convertToFloat(double[] values) { - float[] result = new float[values.length]; - for(int i = 0; i < values.length; i++) { - result[i] = (float) values[i]; - } - return result; - } - - /** - * Converts the specified array of doubles to an array of floats. - * - * @param values the array of doubles to be converted - * @return the converted array of floats - */ - public static double[] convertToDoubles(float[] values) { - double[] result = new double[values.length]; - for(int i = 0; i < values.length; i++) { - result[i] = values[i]; - } - return result; - } - - /** - * Converts the specified list of Double objects to an array of doubles. - * - * @param values the list of Double objects to be converted - * @return the converted array of doubles - */ - public static double[] convertToDoubles(List<Double> values) { - double[] result = new double[values.size()]; - for(int i = 0; i < result.length; i++) { - result[i] = values.get(i); - } - return result; + return ArrayLikeUtil.toPrimitiveDoubleArray(result); } /** @@ -246,105 +100,6 @@ public final class Util { } /** - * Returns the index of the maximum of the given values. If no value is bigger - * than the first, the index of the first entry is returned. - * - * @param values the values to find the index of the maximum - * @return the index of the maximum in the given values - * @throws ArrayIndexOutOfBoundsException if <code>values.length==0</code> - */ - public static int getIndexOfMaximum(double[] values) throws ArrayIndexOutOfBoundsException { - int index = 0; - double max = values[index]; - for(int i = 0; i < values.length; i++) { - if(values[i] > max) { - max = values[i]; - index = i; - } - } - return index; - } - - /** - * Returns a new <code>BitSet</code> initialized to the values represented by - * the specified <code>String</code> only containing 0 and 1 values. - * - * @param s the string to be parsed. - * @return a new <code>BitSet</code> represented by s - */ - public static BitSet parseBitSet(String s) { - try { - return parseBitSet(s.toCharArray()); - } - catch(IllegalArgumentException e) { - throw new IllegalArgumentException("The specified String does not represent a bit set " + "containing only 0 and 1 values: " + s); - } - } - - /** - * Returns a new <code>BitSet</code> initialized to the values represented by - * the specified <code>char</code> array only containing '0' and '1' values. - * - * @param s the char array to be parsed. - * @return a new <code>BitSet</code> represented by s - */ - public static BitSet parseBitSet(char[] s) { - BitSet result = new BitSet(); - for(int i = 0; i < s.length; i++) { - if(s[i] == '1') { - result.set(i); - } - else if(s[i] != '0') { - throw new IllegalArgumentException("The specified String does not represent a bit set " + "containing only 0 and 1 values: " + String.valueOf(s)); - } - } - return result; - } - - /** - * Returns a string that represents the selected bits of the specified - * <code>BitSet</code>, while the first bit starts with 1. The selected bits - * are separated by the specified separator <code>sep</code>. - * - * If <code>sep</code> is ",", the result is suitable as a parameter - * for an IntListParameter. - * - * @param b the bit set to be parsed - * @param sep the separator - * @return a string representing the selected bits of the specified - * <code>BitSet</code> - */ - public static String parseSelectedBits(BitSet b, String sep) { - StringBuffer result = new StringBuffer(); - for(int i = b.nextSetBit(0); i >= 0; i = b.nextSetBit(i + 1)) { - if(result.length() != 0) { - result.append(sep).append(i + 1); - } - else { - result.append((i + 1)); - } - } - - return result.toString(); - } - - /** - * Convert a bit set to a list of integers, representing bits that are set - * - * @param b Bitset - * @param off Offset, set to 0 to start counting at 0, 1 to start counting at - * 1. - * @return List - */ - public static List<Integer> convertBitSetToListInt(BitSet b, int off) { - List<Integer> list = new ArrayList<Integer>(); - for(int i = b.nextSetBit(0); i >= 0; i = b.nextSetBit(i + 1)) { - list.add(i + off); - } - return list; - } - - /** * Creates a new BitSet of fixed cardinality with randomly set bits. * * @param cardinality the cardinality of the BitSet to create @@ -357,9 +112,19 @@ public final class Util { * @return a new BitSet with randomly set bits */ public static BitSet randomBitSet(int cardinality, int capacity, Random random) { + assert (cardinality >= 0) : "Cannot set a negative number of bits!"; + assert (cardinality < capacity) : "Cannot set " + cardinality + " of " + capacity + " bits!"; BitSet bitset = new BitSet(capacity); - while(bitset.cardinality() < cardinality) { - bitset.set(random.nextInt(capacity)); + if(cardinality < capacity >>> 1) { + while(bitset.cardinality() < cardinality) { + bitset.set(random.nextInt(capacity)); + } + } + else { + bitset.flip(0, capacity); + while(bitset.cardinality() > cardinality) { + bitset.clear(random.nextInt(capacity)); + } } return bitset; } @@ -410,7 +175,7 @@ public final class Util { * SparseFloatVector. */ public static SparseFloatVector project(SparseFloatVector v, BitSet selectedAttributes) { - Map<Integer, Float> values = new HashMap<Integer, Float>(selectedAttributes.cardinality(), 1); + TIntFloatHashMap values = new TIntFloatHashMap(selectedAttributes.cardinality(), 1); for(int d = selectedAttributes.nextSetBit(0); d >= 0; d = selectedAttributes.nextSetBit(d + 1)) { if(v.getValue(d + 1) != 0.0f) { values.put(d, v.getValue(d + 1)); @@ -421,124 +186,6 @@ public final class Util { } /** - * Returns the index of the n<sup>th</sup> set bit in the given BitSet. For - * the parameter <code>nthSetBit</code>, following condition is assumed: - * <code>1 ≤ nthSetBit ≤ bitset.cardinality()</code>. Otherwise, i.e., - * if the Bitset contains less than <code>nthSetBit</code> set bits or - * <code>nthSetBit</code> is not a positive number, the method throws an - * IllegalArgumentException. - * - * The worstcase runtime complexity of this method is in <i>O( - * <code>bitset.cardinality()</code>)</i>. - * - * @param bitset the BitSet to derive the index of the n<sup>th</sup> set bit - * in - * @param nthSetBit which set bit to derive the index of - * @return the index of the n<sup>th</sup> set bit in the given BitSet - * @throws IllegalArgumentException if the Bitset contains less than - * <code>nthSetBit</code> set bits or <code>nthSetBit</code> is not a - * positive number - */ - public static int indexOfNthSetBit(BitSet bitset, int nthSetBit) throws IllegalArgumentException { - if(nthSetBit < 1 || nthSetBit > bitset.cardinality()) { - throw new IllegalArgumentException("Parameter nthSetBit out of range: nthSetBit=" + nthSetBit + ", bitset.cardinality=" + bitset.cardinality()); - } - int i = 0; - int index = -1; - for(int d = bitset.nextSetBit(0); d >= 0 && i < nthSetBit; d = bitset.nextSetBit(d + 1)) { - i++; - index = d; - } - return index; - } - - /** - * Provides the intersection of the two specified sets in the given result - * set. - * - * @param <O> object class - * @param s1 the first set - * @param s2 the second set - * @param result the result set - */ - public static <O> void intersection(Set<O> s1, Set<O> s2, Set<O> result) { - for(O object : s1) { - if(s2.contains(object)) { - result.add(object); - } - } - } - - /** - * Converts the specified positive integer value into a bit representation, - * where bit 0 denotes 2<sup>0</sup>, bit 1 denotes 2<sup>1</sup> etc. - * - * @param n the positive integer value to be converted - * @return the specified integer value into a bit representation - */ - public static BitSet int2Bit(int n) { - if(n < 0) { - throw new IllegalArgumentException("Parameter n hast to be greater than or equal to zero!"); - } - - BitSet result = new BitSet(); - int i = 0; - while(n > 0) { - boolean rest = (n % 2 == 1); - if(rest) { - result.set(i); - } - n = n / 2; - i++; - } - return result; - } - - /** - * Joins the specified arrays. - * - * @param array1 the first array - * @param array2 the second array - * @return a new array containing the entries of <code>array1</code> and the - * <code>array2</code>. - */ - public static String[] joinArray(String[] array1, String[] array2) { - String[] newArray = new String[array1.length + array2.length]; - System.arraycopy(array1, 0, newArray, 0, array1.length); - System.arraycopy(array2, 0, newArray, array1.length, array2.length); - return newArray; - } - - /** - * Adds the entries of the specified array to the end of the given list. - * - * @param <O> object class - * @param list the list - * @param array the array containing the objects to be added to the list - */ - public static <O> void addToList(List<O> list, O[] array) { - for(O object : array) { - list.add(object); - } - } - - /** - * Search an (unsorted) array linearly for an object. - * - * @param arr Array to search - * @param ref Object to search for - * @return Index of object or -1 if not found. - */ - public static int arrayFind(String[] arr, Object ref) { - for(int index = 0; index < arr.length; index++) { - if(ref.equals(arr[index])) { - return index; - } - } - return -1; - } - - /** * Mix multiple hashcodes into one. * * @param hash Hashcodes to mix @@ -550,153 +197,40 @@ public final class Util { return 0; } long result = hash[0]; - for (int i = 1; i < hash.length; i++) { + for(int i = 1; i < hash.length; i++) { result = result * prime + hash[i]; } return (int) result; } /** - * This class is a virtual collection based on masking an array list using a - * bit mask. + * Static instance + */ + private static final Comparator<?> FORWARD = new ForwardComparator(); + + /** + * Regular comparator. See {@link java.util.Collections#reverseOrder()} for a + * reverse comparator. * * @author Erich Schubert * - * @apiviz.stereotype decorator - * @apiviz.composedOf java.util.ArrayList - * @apiviz.composedOf java.util.BitSet - * - * @param <T> Object type + * @apiviz.exclude */ - public static class MaskedArrayList<T> extends AbstractCollection<T> implements Collection<T> { - /** - * Data storage - */ - protected ArrayList<T> data; - - /** - * The bitmask used for masking - */ - protected BitSet bits; - - /** - * Flag whether to iterator over set or unset values. - */ - protected boolean inverse = false; - - /** - * Constructor. - * - * @param data Data - * @param bits Bitset to use as mask - * @param inverse Flag to inverse the masking rule - */ - public MaskedArrayList(ArrayList<T> data, BitSet bits, boolean inverse) { - super(); - this.data = data; - this.bits = bits; - this.inverse = inverse; - } - - @Override - public boolean add(T e) { - throw new UnsupportedOperationException(); - } - - @Override - public Iterator<T> iterator() { - if(inverse) { - return new InvItr(); - } - else { - return new Itr(); - } - } - + private static final class ForwardComparator implements Comparator<Comparable<Object>> { @Override - public int size() { - if(inverse) { - return data.size() - bits.cardinality(); - } - else { - return bits.cardinality(); - } + public int compare(Comparable<Object> o1, Comparable<Object> o2) { + return o1.compareTo(o2); } + } - /** - * Iterator over set bits - * - * @author Erich Schubert - * - * @apiviz.exclude - */ - protected class Itr implements Iterator<T> { - /** - * Next position. - */ - private int pos; - - /** - * Constructor - */ - protected Itr() { - this.pos = bits.nextSetBit(0); - } - - @Override - public boolean hasNext() { - return (pos >= 0) && (pos < data.size()); - } - - @Override - public T next() { - T cur = data.get(pos); - pos = bits.nextSetBit(pos + 1); - return cur; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - - /** - * Iterator over unset elements. - * - * @author Erich Schubert - * - * @apiviz.exclude - */ - protected class InvItr implements Iterator<T> { - /** - * Next unset position. - */ - private int pos; - - /** - * Constructor - */ - protected InvItr() { - this.pos = bits.nextClearBit(0); - } - - @Override - public boolean hasNext() { - return (pos >= 0) && (pos < data.size()); - } - - @Override - public T next() { - T cur = data.get(pos); - pos = bits.nextClearBit(pos + 1); - return cur; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } + /** + * Compare two objects, forward. See + * {@link java.util.Collections#reverseOrder()} for a reverse comparator. + * + * @return Forward comparator + */ + @SuppressWarnings("unchecked") + public static final <T> Comparator<T> forwardOrder() { + return (Comparator<T>) FORWARD; } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/AnyMap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/AnyMap.java index 9e1307be..763ce105 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/AnyMap.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/AnyMap.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/HashMapList.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/HashMapList.java index 7c5c950b..26fa4d19 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/HashMapList.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/HashMapList.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/MaskedArrayList.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/MaskedArrayList.java new file mode 100644 index 00000000..c24519d1 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/MaskedArrayList.java @@ -0,0 +1,174 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.AbstractCollection; +import java.util.ArrayList; +import java.util.BitSet; +import java.util.Collection; +import java.util.Iterator; + +/** + * This class is a virtual collection based on masking an array list using a bit + * mask. + * + * @author Erich Schubert + * + * @apiviz.stereotype decorator + * @apiviz.composedOf java.util.ArrayList + * @apiviz.composedOf java.util.BitSet + * + * @param <T> Object type + */ +public class MaskedArrayList<T> extends AbstractCollection<T> implements Collection<T> { + /** + * Data storage + */ + protected ArrayList<T> data; + + /** + * The bitmask used for masking + */ + protected BitSet bits; + + /** + * Flag whether to iterator over set or unset values. + */ + protected boolean inverse = false; + + /** + * Constructor. + * + * @param data Data + * @param bits Bitset to use as mask + * @param inverse Flag to inverse the masking rule + */ + public MaskedArrayList(ArrayList<T> data, BitSet bits, boolean inverse) { + super(); + this.data = data; + this.bits = bits; + this.inverse = inverse; + } + + @Override + public boolean add(T e) { + throw new UnsupportedOperationException(); + } + + @Override + public Iterator<T> iterator() { + if(inverse) { + return new InvItr(); + } + else { + return new Itr(); + } + } + + @Override + public int size() { + if(inverse) { + return data.size() - bits.cardinality(); + } + else { + return bits.cardinality(); + } + } + + /** + * Iterator over set bits + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + protected class Itr implements Iterator<T> { + /** + * Next position. + */ + private int pos; + + /** + * Constructor + */ + protected Itr() { + this.pos = bits.nextSetBit(0); + } + + @Override + public boolean hasNext() { + return (pos >= 0) && (pos < data.size()); + } + + @Override + public T next() { + T cur = data.get(pos); + pos = bits.nextSetBit(pos + 1); + return cur; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + /** + * Iterator over unset elements. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + protected class InvItr implements Iterator<T> { + /** + * Next unset position. + */ + private int pos; + + /** + * Constructor + */ + protected InvItr() { + this.pos = bits.nextClearBit(0); + } + + @Override + public boolean hasNext() { + return (pos >= 0) && (pos < data.size()); + } + + @Override + public T next() { + T cur = data.get(pos); + pos = bits.nextClearBit(pos + 1); + return cur; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/QuickSelect.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/QuickSelect.java new file mode 100644 index 00000000..4498cf07 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/QuickSelect.java @@ -0,0 +1,780 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures; + +import java.util.Comparator; +import java.util.List; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * QuickSelect computes ("selects") the element at a given rank and can be used + * to compute Medians and arbitrary quantiles by computing the appropriate rank. + * + * This algorithm is essentially an incomplete QuickSort that only descends into + * that part of the data that we are interested in, and also attributed to + * Charles Antony Richard Hoare + * + * @author Erich Schubert + */ +public class QuickSelect { + /** + * For small arrays, use a simpler method: + */ + private static final int SMALL = 10; + + /** + * QuickSelect is essentially quicksort, except that we only "sort" that half + * of the array that we are interested in. + * + * Note: the array is <b>modified</b> by this. + * + * @param data Data to process + * @param rank Rank position that we are interested in (integer!) + * @return Value at the given rank + */ + public static double quickSelect(double[] data, int rank) { + quickSelect(data, 0, data.length, rank); + return data[rank]; + } + + /** + * Compute the median of an array efficiently using the QuickSelect method. + * + * Note: the array is <b>modified</b> by this. + * + * @param data Data to process + * @return Median value + */ + public static double median(double[] data) { + return median(data, 0, data.length); + } + + /** + * Compute the median of an array efficiently using the QuickSelect method. + * + * Note: the array is <b>modified</b> by this. + * + * @param data Data to process + * @param begin Begin of valid values + * @param end End of valid values (exclusive!) + * @return Median value + */ + public static double median(double[] data, int begin, int end) { + final int length = end - begin; + assert (length > 0); + // Integer division is "floor" since we are non-negative. + final int left = begin + (length - 1) / 2; + quickSelect(data, begin, end, left); + if(length % 2 == 1) { + return data[left]; + } + else { + quickSelect(data, begin, end, left + 1); + return data[left] + (data[left + 1] - data[left]) / 2; + } + } + + /** + * Compute the median of an array efficiently using the QuickSelect method. + * + * Note: the array is <b>modified</b> by this. + * + * @param data Data to process + * @param quant Quantile to compute + * @return Value at quantile + */ + public static double quantile(double[] data, double quant) { + return quantile(data, 0, data.length, quant); + } + + /** + * Compute the median of an array efficiently using the QuickSelect method. + * + * Note: the array is <b>modified</b> by this. + * + * @param data Data to process + * @param begin Begin of valid values + * @param end End of valid values (exclusive!) + * @param quant Quantile to compute + * @return Value at quantile + */ + public static double quantile(double[] data, int begin, int end, double quant) { + final int length = end - begin; + assert (length > 0) : "Quantile on empty set?"; + // Integer division is "floor" since we are non-negative. + final double dleft = begin + (length - 1) * quant; + final int ileft = (int) Math.floor(dleft); + final double err = dleft - ileft; + + quickSelect(data, begin, end, ileft); + if(err <= Double.MIN_NORMAL) { + return data[ileft]; + } + else { + quickSelect(data, begin, end, ileft + 1); + // Mix: + double mix = data[ileft] + (data[ileft + 1] - data[ileft]) * err; + return mix; + } + } + + /** + * QuickSelect is essentially quicksort, except that we only "sort" that half + * of the array that we are interested in. + * + * @param data Data to process + * @param start Interval start + * @param end Interval end (exclusive) + * @param rank rank position we are interested in (starting at 0) + */ + public static void quickSelect(double[] data, int start, int end, int rank) { + // Optimization for small arrays + // This also ensures a minimum size below + if(start + SMALL > end) { + insertionSort(data, start, end); + return; + } + + // Pick pivot from three candidates: start, middle, end + // Since we compare them, we can also just "bubble sort" them. + final int middle = (start + end) / 2; + if(data[start] > data[middle]) { + swap(data, start, middle); + } + if(data[start] > data[end - 1]) { + swap(data, start, end - 1); + } + if(data[middle] > data[end - 1]) { + swap(data, middle, end - 1); + } + // TODO: use more candidates for larger arrays? + + final double pivot = data[middle]; + // Move middle element out of the way, just before end + // (Since we already know that "end" is bigger) + swap(data, middle, end - 2); + + // Begin partitioning + int i = start + 1, j = end - 3; + // This is classic quicksort stuff + while(true) { + while(data[i] <= pivot && i <= j) { + i++; + } + while(data[j] >= pivot && j >= i) { + j--; + } + if(i >= j) { + break; + } + swap(data, i, j); + } + + // Move pivot (former middle element) back into the appropriate place + swap(data, i, end - 2); + + // In contrast to quicksort, we only need to recurse into the half we are + // interested in. + if(rank < i) { + quickSelect(data, start, i, rank); + } + else if(rank > i) { + quickSelect(data, i + 1, end, rank); + } + } + + /** + * Sort a small array using repetitive insertion sort. + * + * @param data Data to sort + * @param start Interval start + * @param end Interval end + */ + private static void insertionSort(double[] data, int start, int end) { + for(int i = start + 1; i < end; i++) { + for(int j = i; j > start && data[j - 1] > data[j]; j--) { + swap(data, j, j - 1); + } + } + } + + /** + * The usual swap method. + * + * @param data Array + * @param a First index + * @param b Second index + */ + private static final void swap(double[] data, int a, int b) { + double tmp = data[a]; + data[a] = data[b]; + data[b] = tmp; + } + + /** + * QuickSelect is essentially quicksort, except that we only "sort" that half + * of the array that we are interested in. + * + * Note: the array is <b>modified</b> by this. + * + * @param <T> object type + * @param data Data to process + * @param rank Rank position that we are interested in (integer!) + * @return Value at the given rank + */ + public static <T extends Comparable<? super T>> T quickSelect(T[] data, int rank) { + quickSelect(data, 0, data.length, rank); + return data[rank]; + } + + /** + * Compute the median of an array efficiently using the QuickSelect method. + * + * Note: the array is <b>modified</b> by this. + * + * @param data Data to process + * @return Median value + */ + public static <T extends Comparable<? super T>> T median(T[] data) { + return median(data, 0, data.length); + } + + /** + * Compute the median of an array efficiently using the QuickSelect method. + * + * On an odd length, it will return the lower element. + * + * Note: the array is <b>modified</b> by this. + * + * @param <T> object type + * @param data Data to process + * @param begin Begin of valid values + * @param end End of valid values (exclusive!) + * @return Median value + */ + public static <T extends Comparable<? super T>> T median(T[] data, int begin, int end) { + final int length = end - begin; + assert (length > 0); + // Integer division is "floor" since we are non-negative. + final int left = begin + (length - 1) / 2; + quickSelect(data, begin, end, left); + return data[left]; + } + + /** + * Compute the median of an array efficiently using the QuickSelect method. + * + * Note: the array is <b>modified</b> by this. + * + * @param <T> object type + * @param data Data to process + * @param quant Quantile to compute + * @return Value at quantile + */ + public static <T extends Comparable<? super T>> T quantile(T[] data, double quant) { + return quantile(data, 0, data.length, quant); + } + + /** + * Compute the median of an array efficiently using the QuickSelect method. + * + * It will prefer the lower element. + * + * Note: the array is <b>modified</b> by this. + * + * @param <T> object type + * @param data Data to process + * @param begin Begin of valid values + * @param end End of valid values (exclusive!) + * @param quant Quantile to compute + * @return Value at quantile + */ + public static <T extends Comparable<? super T>> T quantile(T[] data, int begin, int end, double quant) { + final int length = end - begin; + assert (length > 0) : "Quantile on empty set?"; + // Integer division is "floor" since we are non-negative. + final double dleft = begin + (length - 1) * quant; + final int ileft = (int) Math.floor(dleft); + + quickSelect(data, begin, end, ileft); + return data[ileft]; + } + + /** + * QuickSelect is essentially quicksort, except that we only "sort" that half + * of the array that we are interested in. + * + * @param <T> object type + * @param data Data to process + * @param start Interval start + * @param end Interval end (exclusive) + * @param rank rank position we are interested in (starting at 0) + */ + public static <T extends Comparable<? super T>> void quickSelect(T[] data, int start, int end, int rank) { + // Optimization for small arrays + // This also ensures a minimum size below + if(start + SMALL > end) { + insertionSort(data, start, end); + return; + } + + // Pick pivot from three candidates: start, middle, end + // Since we compare them, we can also just "bubble sort" them. + final int middle = (start + end) / 2; + if(data[start].compareTo(data[middle]) > 0) { + swap(data, start, middle); + } + if(data[start].compareTo(data[end - 1]) > 0) { + swap(data, start, end - 1); + } + if(data[middle].compareTo(data[end - 1]) > 0) { + swap(data, middle, end - 1); + } + // TODO: use more candidates for larger arrays? + + final T pivot = data[middle]; + // Move middle element out of the way, just before end + // (Since we already know that "end" is bigger) + swap(data, middle, end - 2); + + // Begin partitioning + int i = start + 1, j = end - 3; + // This is classic quicksort stuff + while(true) { + while(data[i].compareTo(pivot) <= 0 && i <= j) { + i++; + } + while(data[j].compareTo(pivot) >= 0 && j >= i) { + j--; + } + if(i >= j) { + break; + } + swap(data, i, j); + } + + // Move pivot (former middle element) back into the appropriate place + swap(data, i, end - 2); + + // In contrast to quicksort, we only need to recurse into the half we are + // interested in. + if(rank < i) { + quickSelect(data, start, i, rank); + } + else if(rank > i) { + quickSelect(data, i + 1, end, rank); + } + } + + /** + * Sort a small array using repetitive insertion sort. + * + * @param <T> object type + * @param data Data to sort + * @param start Interval start + * @param end Interval end + */ + private static <T extends Comparable<? super T>> void insertionSort(T[] data, int start, int end) { + for(int i = start + 1; i < end; i++) { + for(int j = i; j > start && data[j - 1].compareTo(data[j]) > 0; j--) { + swap(data, j, j - 1); + } + } + } + + /** + * The usual swap method. + * + * @param <T> object type + * @param data Array + * @param a First index + * @param b Second index + */ + private static final <T extends Comparable<? super T>> void swap(T[] data, int a, int b) { + T tmp = data[a]; + data[a] = data[b]; + data[b] = tmp; + } + + /** + * QuickSelect is essentially quicksort, except that we only "sort" that half + * of the array that we are interested in. + * + * Note: the array is <b>modified</b> by this. + * + * @param <T> object type + * @param data Data to process + * @param rank Rank position that we are interested in (integer!) + * @return Value at the given rank + */ + public static <T extends Comparable<? super T>> T quickSelect(List<? extends T> data, int rank) { + quickSelect(data, 0, data.size(), rank); + return data.get(rank); + } + + /** + * Compute the median of an array efficiently using the QuickSelect method. + * + * Note: the array is <b>modified</b> by this. + * + * @param <T> object type + * @param data Data to process + * @return Median value + */ + public static <T extends Comparable<? super T>> T median(List<? extends T> data) { + return median(data, 0, data.size()); + } + + /** + * Compute the median of an array efficiently using the QuickSelect method. + * + * On an odd length, it will return the lower element. + * + * Note: the array is <b>modified</b> by this. + * + * @param <T> object type + * @param data Data to process + * @param begin Begin of valid values + * @param end End of valid values (exclusive!) + * @return Median value + */ + public static <T extends Comparable<? super T>> T median(List<? extends T> data, int begin, int end) { + final int length = end - begin; + assert (length > 0); + // Integer division is "floor" since we are non-negative. + final int left = begin + (length - 1) / 2; + quickSelect(data, begin, end, left); + return data.get(left); + } + + /** + * Compute the median of an array efficiently using the QuickSelect method. + * + * Note: the array is <b>modified</b> by this. + * + * @param <T> object type + * @param data Data to process + * @param quant Quantile to compute + * @return Value at quantile + */ + public static <T extends Comparable<? super T>> T quantile(List<? extends T> data, double quant) { + return quantile(data, 0, data.size(), quant); + } + + /** + * Compute the median of an array efficiently using the QuickSelect method. + * + * It will prefer the lower element. + * + * Note: the array is <b>modified</b> by this. + * + * @param <T> object type + * @param data Data to process + * @param begin Begin of valid values + * @param end End of valid values (exclusive!) + * @param quant Quantile to compute + * @return Value at quantile + */ + public static <T extends Comparable<? super T>> T quantile(List<? extends T> data, int begin, int end, double quant) { + final int length = end - begin; + assert (length > 0) : "Quantile on empty set?"; + // Integer division is "floor" since we are non-negative. + final double dleft = begin + (length - 1) * quant; + final int ileft = (int) Math.floor(dleft); + + quickSelect(data, begin, end, ileft); + return data.get(ileft); + } + + /** + * QuickSelect is essentially quicksort, except that we only "sort" that half + * of the array that we are interested in. + * + * @param <T> object type + * @param data Data to process + * @param start Interval start + * @param end Interval end (exclusive) + * @param rank rank position we are interested in (starting at 0) + */ + public static <T extends Comparable<? super T>> void quickSelect(List<? extends T> data, int start, int end, int rank) { + // Optimization for small arrays + // This also ensures a minimum size below + if(start + SMALL > end) { + insertionSort(data, start, end); + return; + } + + // Pick pivot from three candidates: start, middle, end + // Since we compare them, we can also just "bubble sort" them. + final int middle = (start + end) / 2; + if(data.get(start).compareTo(data.get(middle)) > 0) { + swap(data, start, middle); + } + if(data.get(start).compareTo(data.get(end - 1)) > 0) { + swap(data, start, end - 1); + } + if(data.get(middle).compareTo(data.get(end - 1)) > 0) { + swap(data, middle, end - 1); + } + // TODO: use more candidates for larger arrays? + + final T pivot = data.get(middle); + // Move middle element out of the way, just before end + // (Since we already know that "end" is bigger) + swap(data, middle, end - 2); + + // Begin partitioning + int i = start + 1, j = end - 3; + // This is classic quicksort stuff + while(true) { + while(data.get(i).compareTo(pivot) <= 0 && i <= j) { + i++; + } + while(data.get(j).compareTo(pivot) >= 0 && j >= i) { + j--; + } + if(i >= j) { + break; + } + swap(data, i, j); + } + + // Move pivot (former middle element) back into the appropriate place + swap(data, i, end - 2); + + // In contrast to quicksort, we only need to recurse into the half we are + // interested in. + if(rank < i) { + quickSelect(data, start, i, rank); + } + else if(rank > i) { + quickSelect(data, i + 1, end, rank); + } + } + + /** + * Sort a small array using repetitive insertion sort. + * + * @param <T> object type + * @param data Data to sort + * @param start Interval start + * @param end Interval end + */ + private static <T extends Comparable<? super T>> void insertionSort(List<T> data, int start, int end) { + for(int i = start + 1; i < end; i++) { + for(int j = i; j > start && data.get(j - 1).compareTo(data.get(j)) > 0; j--) { + swap(data, j, j - 1); + } + } + } + + /** + * The usual swap method. + * + * @param <T> object type + * @param data Array + * @param a First index + * @param b Second index + */ + private static final <T> void swap(List<T> data, int a, int b) { + data.set(b, data.set(a, data.get(b))); + } + + /** + * QuickSelect is essentially quicksort, except that we only "sort" that half + * of the array that we are interested in. + * + * Note: the array is <b>modified</b> by this. + * + * @param <T> object type + * @param data Data to process + * @param comparator Comparator to use + * @param rank Rank position that we are interested in (integer!) + * @return Value at the given rank + */ + public static <T> T quickSelect(List<? extends T> data, Comparator<? super T> comparator, int rank) { + quickSelect(data, comparator, 0, data.size(), rank); + return data.get(rank); + } + + /** + * Compute the median of an array efficiently using the QuickSelect method. + * + * Note: the array is <b>modified</b> by this. + * + * @param <T> object type + * @param data Data to process + * @param comparator Comparator to use + * @return Median value + */ + public static <T> T median(List<? extends T> data, Comparator<? super T> comparator) { + return median(data, comparator, 0, data.size()); + } + + /** + * Compute the median of an array efficiently using the QuickSelect method. + * + * On an odd length, it will return the lower element. + * + * Note: the array is <b>modified</b> by this. + * + * @param <T> object type + * @param data Data to process + * @param comparator Comparator to use + * @param begin Begin of valid values + * @param end End of valid values (exclusive!) + * @return Median value + */ + public static <T> T median(List<? extends T> data, Comparator<? super T> comparator, int begin, int end) { + final int length = end - begin; + assert (length > 0); + // Integer division is "floor" since we are non-negative. + final int left = begin + (length - 1) / 2; + quickSelect(data, comparator, begin, end, left); + return data.get(left); + } + + /** + * Compute the median of an array efficiently using the QuickSelect method. + * + * Note: the array is <b>modified</b> by this. + * + * @param <T> object type + * @param data Data to process + * @param comparator Comparator to use + * @param quant Quantile to compute + * @return Value at quantile + */ + public static <T> T quantile(List<? extends T> data, Comparator<? super T> comparator, double quant) { + return quantile(data, comparator, 0, data.size(), quant); + } + + /** + * Compute the median of an array efficiently using the QuickSelect method. + * + * It will prefer the lower element. + * + * Note: the array is <b>modified</b> by this. + * + * @param <T> object type + * @param data Data to process + * @param comparator Comparator to use + * @param begin Begin of valid values + * @param end End of valid values (inclusive!) + * @param quant Quantile to compute + * @return Value at quantile + */ + public static <T> T quantile(List<? extends T> data, Comparator<? super T> comparator, int begin, int end, double quant) { + final int length = end - begin; + assert (length > 0) : "Quantile on empty set?"; + // Integer division is "floor" since we are non-negative. + final double dleft = begin + (length - 1) * quant; + final int ileft = (int) Math.floor(dleft); + + quickSelect(data, comparator, begin, end, ileft); + return data.get(ileft); + } + + /** + * QuickSelect is essentially quicksort, except that we only "sort" that half + * of the array that we are interested in. + * + * @param <T> object type + * @param data Data to process + * @param comparator Comparator to use + * @param start Interval start + * @param end Interval end (inclusive) + * @param rank rank position we are interested in (starting at 0) + */ + public static <T> void quickSelect(List<? extends T> data, Comparator<? super T> comparator, int start, int end, int rank) { + // Optimization for small arrays + // This also ensures a minimum size below + if(start + SMALL > end) { + insertionSort(data, comparator, start, end); + return; + } + + // Pick pivot from three candidates: start, middle, end + // Since we compare them, we can also just "bubble sort" them. + final int middle = (start + end) / 2; + if(comparator.compare(data.get(start), data.get(middle)) > 0) { + swap(data, start, middle); + } + if(comparator.compare(data.get(start), data.get(end - 1)) > 0) { + swap(data, start, end - 1); + } + if(comparator.compare(data.get(middle), data.get(end - 1)) > 0) { + swap(data, middle, end - 1); + } + // TODO: use more candidates for larger arrays? + + final T pivot = data.get(middle); + // Move middle element out of the way, just before end + // (Since we already know that "end" is bigger) + swap(data, middle, end - 2); + + // Begin partitioning + int i = start + 1, j = end - 3; + // This is classic quicksort stuff + while(true) { + while(comparator.compare(data.get(i), pivot) <= 0 && i <= j) { + i++; + } + while(comparator.compare(data.get(j), pivot) >= 0 && j >= i) { + j--; + } + if(i >= j) { + break; + } + swap(data, i, j); + } + + // Move pivot (former middle element) back into the appropriate place + swap(data, i, end - 2); + + // In contrast to quicksort, we only need to recurse into the half we are + // interested in. + if(rank < i) { + quickSelect(data, comparator, start, i, rank); + } + else if(rank > i) { + quickSelect(data, comparator, i + 1, end, rank); + } + } + + /** + * Sort a small array using repetitive insertion sort. + * + * @param <T> object type + * @param data Data to sort + * @param start Interval start + * @param end Interval end + */ + private static <T> void insertionSort(List<T> data, Comparator<? super T> comparator, int start, int end) { + for(int i = start + 1; i < end; i++) { + for(int j = i; j > start && comparator.compare(data.get(j - 1), data.get(j)) > 0; j--) { + swap(data, j, j - 1); + } + } + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayAdapter.java new file mode 100644 index 00000000..969d068d --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayAdapter.java @@ -0,0 +1,52 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Adapter for array-like things. For example, arrays and lists. + * + * @author Erich Schubert + * + * @param <T> Item type + * @param <A> Array object type + */ +public interface ArrayAdapter<T, A> { + /** + * Get the size of the array. + * + * @param array Array-like thing + * @return Size + */ + public int size(A array); + + /** + * Get the off'th item from the array. + * + * @param array Array to get from + * @param off Offset + * @return Item at offset off + * @throws IndexOutOfBoundsException for an invalid index. + */ + public T get(A array, int off) throws IndexOutOfBoundsException; +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayDBIDsAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayDBIDsAdapter.java new file mode 100644 index 00000000..6e6e8122 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayDBIDsAdapter.java @@ -0,0 +1,53 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs; +import de.lmu.ifi.dbs.elki.database.ids.DBID; + +/** + * Use a DBID array in a generic array-like context. + * + * @author Erich Schubert + */ +public class ArrayDBIDsAdapter implements ArrayAdapter<DBID, ArrayDBIDs> { + /** + * Constructor. + * + * Protected - use the static instance from {@link ArrayLikeUtil}! + */ + protected ArrayDBIDsAdapter() { + super(); + } + + @Override + public int size(ArrayDBIDs array) { + return array.size(); + } + + @Override + public DBID get(ArrayDBIDs array, int off) throws IndexOutOfBoundsException { + return array.get(off); + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayLikeUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayLikeUtil.java new file mode 100644 index 00000000..2d29f40c --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayLikeUtil.java @@ -0,0 +1,253 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.List; + +import de.lmu.ifi.dbs.elki.data.FeatureVector; +import de.lmu.ifi.dbs.elki.data.NumberVector; + +/** + * Utility class that allows plug-in use of various "array-like" types such as + * lists in APIs that can take any kind of array to safe the cost of + * reorganizing the objects into a real array. + * + * @author Erich Schubert + */ +public final class ArrayLikeUtil { + /** + * Static instance for lists + */ + private static final ListArrayAdapter<Object> LISTADAPTER = new ListArrayAdapter<Object>(); + + /** + * Static instance for lists of numbers + */ + private static final NumberListArrayAdapter<Number> NUMBERLISTADAPTER = new NumberListArrayAdapter<Number>(); + + /** + * Static instance + */ + private final static IdentityArrayAdapter<?> IDENTITYADAPTER = new IdentityArrayAdapter<Object>(); + + /** + * Static instance + */ + private static final FeatureVectorAdapter<?> FEATUREVECTORADAPTER = new FeatureVectorAdapter<Number>(); + + /** + * Use a number vector in the array API. + */ + private static final NumberVectorAdapter<?> NUMBERVECTORADAPTER = new NumberVectorAdapter<Double>(); + + /** + * Use a double array in the array API. + */ + public static final NumberArrayAdapter<Double, double[]> DOUBLEARRAYADAPTER = new DoubleArrayAdapter(); + + /** + * Use a float array in the array API. + */ + public static final NumberArrayAdapter<Float, float[]> FLOATARRAYADAPTER = new FloatArrayAdapter(); + + /** + * Use a Trove double list as array. + */ + public static final TDoubleListAdapter TDOUBLELISTADAPTER = new TDoubleListAdapter(); + + /** + * Use ArrayDBIDs as array. + */ + public static final ArrayDBIDsAdapter ARRAYDBIDADAPTER = new ArrayDBIDsAdapter(); + + /** + * Cast the static instance. + * + * @param dummy Dummy variable, for type inference + * @return Static instance + */ + @SuppressWarnings("unchecked") + public static <T> ArrayAdapter<T, List<? extends T>> listAdapter(List<? extends T> dummy) { + return (ListArrayAdapter<T>) LISTADAPTER; + } + + /** + * Cast the static instance. + * + * @param dummy Dummy variable, for type inference + * @return Static instance + */ + @SuppressWarnings("unchecked") + public static <T extends Number> NumberArrayAdapter<T, List<? extends T>> numberListAdapter(List<? extends T> dummy) { + return (NumberListArrayAdapter<T>) NUMBERLISTADAPTER; + } + + /** + * Get the static instance. + * + * @param dummy Dummy object for type inference + * @return Static instance + */ + @SuppressWarnings("unchecked") + public static <T> IdentityArrayAdapter<T> identityAdapter(T dummy) { + return (IdentityArrayAdapter<T>) IDENTITYADAPTER; + } + + /** + * Get the static instance. + * + * @param prototype Prototype value, for type inference + * @return Instance + */ + @SuppressWarnings("unchecked") + public static <F> FeatureVectorAdapter<F> featureVectorAdapter(FeatureVector<?, F> prototype) { + return (FeatureVectorAdapter<F>) FEATUREVECTORADAPTER; + } + + /** + * Get the static instance. + * + * @param prototype Prototype value, for type inference + * @return Instance + */ + @SuppressWarnings("unchecked") + public static <N extends Number> NumberVectorAdapter<N> numberVectorAdapter(NumberVector<?, N> prototype) { + return (NumberVectorAdapter<N>) NUMBERVECTORADAPTER; + } + + /** + * Get the adapter for double arrays. + * + * @return double array adapter + */ + public static NumberArrayAdapter<Double, double[]> doubleArrayAdapter() { + return DOUBLEARRAYADAPTER; + } + + /** + * Returns the index of the maximum of the given values. If no value is bigger + * than the first, the index of the first entry is returned. + * + * @param <A> array type + * @param array Array to inspect + * @param adapter API adapter class + * @return the index of the maximum in the given values + * @throws IndexOutOfBoundsException if the length of the array is 0. + */ + public static <A> int getIndexOfMaximum(A array, NumberArrayAdapter<?, A> adapter) throws IndexOutOfBoundsException { + final int size = adapter.size(array); + int index = 0; + double max = adapter.getDouble(array, 0); + for(int i = 1; i < size; i++) { + double val = adapter.getDouble(array, i); + if(val > max) { + max = val; + index = i; + } + } + return index; + } + + /** + * Returns the index of the maximum of the given values. If no value is bigger + * than the first, the index of the first entry is returned. + * + * @param array Array to inspect + * @return the index of the maximum in the given values + * @throws IndexOutOfBoundsException if the length of the array is 0. + */ + public static int getIndexOfMaximum(double[] array) throws IndexOutOfBoundsException { + return getIndexOfMaximum(array, DOUBLEARRAYADAPTER); + } + + /** + * Convert a numeric array-like to a <code>double[]</code> + * + * @param array Array-like + * @param adapter Adapter + * @return primitive double array + */ + public static <A> double[] toPrimitiveDoubleArray(A array, NumberArrayAdapter<?, ? super A> adapter) { + double[] ret = new double[adapter.size(array)]; + for(int i = 0; i < ret.length; i++) { + ret[i] = adapter.getDouble(array, i); + } + return ret; + } + + /** + * Convert a list of numbers to <code>double[]</code>. + * + * @param array List of numbers + * @return double array + */ + public static double[] toPrimitiveDoubleArray(List<? extends Number> array) { + return toPrimitiveDoubleArray(array, NUMBERLISTADAPTER); + } + + /** + * Convert a number vector to <code>double[]</code>. + * + * @param obj Object to convert + * @return primitive double array + */ + public static <N extends Number> double[] toPrimitiveDoubleArray(NumberVector<?, N> obj) { + return toPrimitiveDoubleArray(obj, numberVectorAdapter(obj)); + } + + /** + * Convert a numeric array-like to a <code>float[]</code> + * + * @param array Array-like + * @param adapter Adapter + * @return primitive float array + */ + public static <A> float[] toPrimitiveFloatArray(A array, NumberArrayAdapter<?, ? super A> adapter) { + float[] ret = new float[adapter.size(array)]; + for(int i = 0; i < ret.length; i++) { + ret[i] = adapter.getFloat(array, i); + } + return ret; + } + + /** + * Convert a list of numbers to <code>float[]</code>. + * + * @param array List of numbers + * @return float array + */ + public static float[] toPrimitiveFloatArray(List<? extends Number> array) { + return toPrimitiveFloatArray(array, NUMBERLISTADAPTER); + } + + /** + * Convert a number vector to <code>float[]</code>. + * + * @param obj Object to convert + * @return primitive float array + */ + public static <N extends Number> float[] toPrimitiveFloatArray(NumberVector<?, N> obj) { + return toPrimitiveFloatArray(obj, numberVectorAdapter(obj)); + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/DoubleArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/DoubleArrayAdapter.java new file mode 100644 index 00000000..43419103 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/DoubleArrayAdapter.java @@ -0,0 +1,81 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike; +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Use a double array as, well, double array in the ArrayAdapter API. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ +class DoubleArrayAdapter implements NumberArrayAdapter<Double, double[]> { + /** + * Constructor. + * + * Use the static instance from {@link ArrayLikeUtil}! + */ + protected DoubleArrayAdapter() { + super(); + } + + @Override + public int size(double[] array) { + return array.length; + } + + @Override + public Double get(double[] array, int off) throws IndexOutOfBoundsException { + return array[off]; + } + + @Override + public double getDouble(double[] array, int off) throws IndexOutOfBoundsException { + return array[off]; + } + + @Override + public float getFloat(double[] array, int off) throws IndexOutOfBoundsException { + return (float) array[off]; + } + + @Override + public int getInteger(double[] array, int off) throws IndexOutOfBoundsException { + return (int) array[off]; + } + + @Override + public short getShort(double[] array, int off) throws IndexOutOfBoundsException { + return (short) array[off]; + } + + @Override + public long getLong(double[] array, int off) throws IndexOutOfBoundsException { + return (long) array[off]; + } + + @Override + public byte getByte(double[] array, int off) throws IndexOutOfBoundsException { + return (byte) array[off]; + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ExtendedArray.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ExtendedArray.java new file mode 100644 index 00000000..a195360b --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ExtendedArray.java @@ -0,0 +1,96 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Class to extend an array with a single element virtually. + * + * @author Erich Schubert + * + * @param <T> Object type + */ +public class ExtendedArray<T> implements ArrayAdapter<T, ExtendedArray<T>> { + /** + * The array + */ + final Object array; + + /** + * The array adapter + */ + final ArrayAdapter<T, Object> getter; + + /** + * The extra element + */ + final T extra; + + /** + * Our size + */ + final int size; + + /** + * Constructor. + * + * @param array Original array + * @param getter Adapter for array + * @param extra Extra element + */ + protected ExtendedArray(Object array, ArrayAdapter<T, Object> getter, T extra) { + super(); + this.array = array; + this.getter = getter; + this.extra = extra; + this.size = getter.size(array) + 1; + } + + @Override + public int size(ExtendedArray<T> array) { + assert (array == this); + return size; + } + + @Override + public T get(ExtendedArray<T> array, int off) throws IndexOutOfBoundsException { + assert (array == this); + if(off == size - 1) { + return extra; + } + return getter.get(this.array, off); + } + + /** + * Static wrapper that has a nicer generics signature. + * + * @param array Array to extend + * @param getter Getter for array + * @param extra Extra element + * @return Extended array + */ + @SuppressWarnings("unchecked") + public static <T, A> ExtendedArray<T> extend(A array, ArrayAdapter<T, A> getter, T extra) { + return new ExtendedArray<T>(array, (ArrayAdapter<T, Object>) getter, extra); + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/FeatureVectorAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/FeatureVectorAdapter.java new file mode 100644 index 00000000..19c2ec19 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/FeatureVectorAdapter.java @@ -0,0 +1,56 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike; + +import de.lmu.ifi.dbs.elki.data.FeatureVector; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Adapter to use a feature vector as an array of features. + * + * Use the static instance from {@link ArrayLikeUtil}! + * + * @author Erich Schubert + * + * @param <F> Feature type + */ +public class FeatureVectorAdapter<F> implements ArrayAdapter<F, FeatureVector<?, F>> { + /** + * Constructor. + * + * Use the static instance from {@link ArrayLikeUtil}! + */ + protected FeatureVectorAdapter() { + super(); + } + + @Override + public int size(FeatureVector<?, F> array) { + return array.getDimensionality(); + } + + @Override + public F get(FeatureVector<?, F> array, int off) throws IndexOutOfBoundsException { + return array.getValue(off); + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/FloatArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/FloatArrayAdapter.java new file mode 100644 index 00000000..14d42dc5 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/FloatArrayAdapter.java @@ -0,0 +1,82 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Use a double array as, well, double array in the ArrayAdapter API. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ +class FloatArrayAdapter implements NumberArrayAdapter<Float, float[]> { + /** + * Constructor. + * + * Use the static instance from {@link ArrayLikeUtil}! + */ + protected FloatArrayAdapter() { + super(); + } + + @Override + public int size(float[] array) { + return array.length; + } + + @Override + public Float get(float[] array, int off) throws IndexOutOfBoundsException { + return array[off]; + } + + @Override + public double getDouble(float[] array, int off) throws IndexOutOfBoundsException { + return (double) array[off]; + } + + @Override + public float getFloat(float[] array, int off) throws IndexOutOfBoundsException { + return array[off]; + } + + @Override + public int getInteger(float[] array, int off) throws IndexOutOfBoundsException { + return (int) array[off]; + } + + @Override + public short getShort(float[] array, int off) throws IndexOutOfBoundsException { + return (short) array[off]; + } + + @Override + public long getLong(float[] array, int off) throws IndexOutOfBoundsException { + return (long) array[off]; + } + + @Override + public byte getByte(float[] array, int off) throws IndexOutOfBoundsException { + return (byte) array[off]; + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/IdentityArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/IdentityArrayAdapter.java new file mode 100644 index 00000000..0c6e03dd --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/IdentityArrayAdapter.java @@ -0,0 +1,55 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Single-item subset adapter + * + * Use the static instance from {@link ArrayLikeUtil}! + * + * @author Erich Schubert + * + * @param <T> Item type + */ +public class IdentityArrayAdapter<T> implements ArrayAdapter<T, T> { + /** + * Constructor. + * + * Use the static instance from {@link ArrayLikeUtil}! + */ + protected IdentityArrayAdapter() { + super(); + } + + @Override + public int size(T array) { + return 1; + } + + @Override + public T get(T array, int off) throws IndexOutOfBoundsException { + assert (off == 0) : "Invalid get()"; + return array; + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ListArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ListArrayAdapter.java new file mode 100644 index 00000000..37875ab7 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ListArrayAdapter.java @@ -0,0 +1,55 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike; + +import java.util.List; +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Static adapter class to use a {@link java.util.List} in an array API. + * + * Use the static instance from {@link ArrayLikeUtil}! + * + * @author Erich Schubert + * + * @param <T> Data object type. + */ +public class ListArrayAdapter<T> implements ArrayAdapter<T, List<? extends T>> { + /** + * Constructor. + * + * Use the static instance from {@link ArrayLikeUtil}! + */ + protected ListArrayAdapter() { + super(); + } + + @Override + public int size(List<? extends T> array) { + return array.size(); + } + + @Override + public T get(List<? extends T> array, int off) throws IndexOutOfBoundsException { + return array.get(off); + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberArrayAdapter.java new file mode 100644 index 00000000..1dc823b1 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberArrayAdapter.java @@ -0,0 +1,99 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike; +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Adapter for arrays of numbers, to avoid boxing. + * + * @author Erich Schubert + * + * @param <N> Number type + * @param <A> Array type + */ +public interface NumberArrayAdapter<N extends Number, A> extends ArrayAdapter<N, A> { + @Override + public int size(A array); + + @Override + public N get(A array, int off) throws IndexOutOfBoundsException; + + /** + * Get the off'th item from the array as double. + * + * @param array Array to get from + * @param off Offset + * @return Item at offset off + * @throws IndexOutOfBoundsException for an invalid index. + */ + public double getDouble(A array, int off) throws IndexOutOfBoundsException; + + /** + * Get the off'th item from the array as float. + * + * @param array Array to get from + * @param off Offset + * @return Item at offset off + * @throws IndexOutOfBoundsException for an invalid index. + */ + public float getFloat(A array, int off) throws IndexOutOfBoundsException; + + /** + * Get the off'th item from the array as integer. + * + * @param array Array to get from + * @param off Offset + * @return Item at offset off + * @throws IndexOutOfBoundsException for an invalid index. + */ + public int getInteger(A array, int off) throws IndexOutOfBoundsException; + + /** + * Get the off'th item from the array as short. + * + * @param array Array to get from + * @param off Offset + * @return Item at offset off + * @throws IndexOutOfBoundsException for an invalid index. + */ + public short getShort(A array, int off) throws IndexOutOfBoundsException; + + /** + * Get the off'th item from the array as long. + * + * @param array Array to get from + * @param off Offset + * @return Item at offset off + * @throws IndexOutOfBoundsException for an invalid index. + */ + public long getLong(A array, int off) throws IndexOutOfBoundsException; + + /** + * Get the off'th item from the array as byte. + * + * @param array Array to get from + * @param off Offset + * @return Item at offset off + * @throws IndexOutOfBoundsException for an invalid index. + */ + public byte getByte(A array, int off) throws IndexOutOfBoundsException; +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberListArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberListArrayAdapter.java new file mode 100644 index 00000000..89a4e3d6 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberListArrayAdapter.java @@ -0,0 +1,87 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike; + +import java.util.List; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Static adapter class to use a {@link java.util.List} in an array of number + * API. + * + * Use the static instance from {@link ArrayLikeUtil}! + * + * @author Erich Schubert + * + * @param <T> Data object type. + */ +public class NumberListArrayAdapter<T extends Number> implements NumberArrayAdapter<T, List<? extends T>> { + /** + * Constructor. + * + * Use the static instance from {@link ArrayLikeUtil}! + */ + protected NumberListArrayAdapter() { + super(); + } + + @Override + public int size(List<? extends T> array) { + return array.size(); + } + + @Override + public T get(List<? extends T> array, int off) throws IndexOutOfBoundsException { + return array.get(off); + } + + @Override + public double getDouble(List<? extends T> array, int off) throws IndexOutOfBoundsException { + return array.get(off).doubleValue(); + } + + @Override + public float getFloat(List<? extends T> array, int off) throws IndexOutOfBoundsException { + return array.get(off).floatValue(); + } + + @Override + public int getInteger(List<? extends T> array, int off) throws IndexOutOfBoundsException { + return array.get(off).intValue(); + } + + @Override + public short getShort(List<? extends T> array, int off) throws IndexOutOfBoundsException { + return array.get(off).shortValue(); + } + + @Override + public long getLong(List<? extends T> array, int off) throws IndexOutOfBoundsException { + return array.get(off).longValue(); + } + + @Override + public byte getByte(List<? extends T> array, int off) throws IndexOutOfBoundsException { + return array.get(off).byteValue(); + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberVectorAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberVectorAdapter.java new file mode 100644 index 00000000..c75acd64 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberVectorAdapter.java @@ -0,0 +1,86 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike; + +import de.lmu.ifi.dbs.elki.data.NumberVector; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Adapter to use a feature vector as an array of features. + * + * Use the static instance from {@link ArrayLikeUtil}! + * + * @author Erich Schubert + * + * @param <N> Number type + */ +public class NumberVectorAdapter<N extends Number> implements NumberArrayAdapter<N, NumberVector<?, N>> { + /** + * Constructor. + * + * Use the static instance from {@link ArrayLikeUtil}! + */ + protected NumberVectorAdapter() { + super(); + } + + @Override + public int size(NumberVector<?, N> array) { + return array.getDimensionality(); + } + + @Override + public N get(NumberVector<?, N> array, int off) throws IndexOutOfBoundsException { + return array.getValue(off + 1); + } + + @Override + public double getDouble(NumberVector<?, N> array, int off) throws IndexOutOfBoundsException { + return array.doubleValue(off + 1); + } + + @Override + public float getFloat(NumberVector<?, N> array, int off) throws IndexOutOfBoundsException { + return array.floatValue(off + 1); + } + + @Override + public int getInteger(NumberVector<?, N> array, int off) throws IndexOutOfBoundsException { + return array.intValue(off + 1); + } + + @Override + public short getShort(NumberVector<?, N> array, int off) throws IndexOutOfBoundsException { + return array.shortValue(off + 1); + } + + @Override + public long getLong(NumberVector<?, N> array, int off) throws IndexOutOfBoundsException { + return array.longValue(off + 1); + } + + @Override + public byte getByte(NumberVector<?, N> array, int off) throws IndexOutOfBoundsException { + return array.byteValue(off + 1); + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SingleSubsetArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SingleSubsetArrayAdapter.java new file mode 100644 index 00000000..d7483e4d --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SingleSubsetArrayAdapter.java @@ -0,0 +1,67 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Single-item subset adapter + * + * @author Erich Schubert + * + * @param <T> Entry type + * @param <A> Array type + */ +public class SingleSubsetArrayAdapter<T, A> implements ArrayAdapter<T, A> { + /** + * Wrapped adapter + */ + ArrayAdapter<T, ? super A> wrapped; + + /** + * Offset to return + */ + int off; + + /** + * Constructor. + * + * @param wrapped Wrapped adapter + * @param off Offset + */ + public SingleSubsetArrayAdapter(ArrayAdapter<T, ? super A> wrapped, int off) { + super(); + this.wrapped = wrapped; + this.off = off; + } + + @Override + public int size(A array) { + return 1; + } + + @Override + public T get(A array, int off) throws IndexOutOfBoundsException { + assert (off == 0) : "Invalid get()"; + return wrapped.get(array, off); + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SubsetArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SubsetArrayAdapter.java new file mode 100644 index 00000000..b2958358 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SubsetArrayAdapter.java @@ -0,0 +1,65 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike; +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Subset array adapter (allows reordering and projection) + * + * @author Erich Schubert + * + * @param <T> Entry type + * @param <A> Array type + */ +public class SubsetArrayAdapter<T, A> implements ArrayAdapter<T, A> { + /** + * Wrapped adapter + */ + ArrayAdapter<T, ? super A> wrapped; + + /** + * Offsets to return + */ + int[] offs; + + /** + * Constructor. + * + * @param wrapped Wrapped adapter + * @param offs Offsets + */ + public SubsetArrayAdapter(ArrayAdapter<T, ? super A> wrapped, int[] offs) { + super(); + this.wrapped = wrapped; + this.offs = offs; + } + + @Override + public int size(A array) { + return offs.length; + } + + @Override + public T get(A array, int off) throws IndexOutOfBoundsException { + return wrapped.get(array, offs[off]); + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/TDoubleListAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/TDoubleListAdapter.java new file mode 100644 index 00000000..889c64e8 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/TDoubleListAdapter.java @@ -0,0 +1,81 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike; + +import gnu.trove.list.TDoubleList; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +/** + * Adapter for using Trove TDoubleLists as array-like. + * + * @author Erich Schubert + * + * @apiviz.uses TDoubleList + */ +public class TDoubleListAdapter implements NumberArrayAdapter<Double, TDoubleList> { + /** + * Constructor. + */ + protected TDoubleListAdapter() { + super(); + } + + @Override + public int size(TDoubleList array) { + return array.size(); + } + + @Override + public Double get(TDoubleList array, int off) throws IndexOutOfBoundsException { + return array.get(off); + } + + @Override + public double getDouble(TDoubleList array, int off) throws IndexOutOfBoundsException { + return array.get(off); + } + + @Override + public float getFloat(TDoubleList array, int off) throws IndexOutOfBoundsException { + return (float) array.get(off); + } + + @Override + public int getInteger(TDoubleList array, int off) throws IndexOutOfBoundsException { + return (int) array.get(off); + } + + @Override + public short getShort(TDoubleList array, int off) throws IndexOutOfBoundsException { + return (short) array.get(off); + } + + @Override + public long getLong(TDoubleList array, int off) throws IndexOutOfBoundsException { + return (long) array.get(off); + } + + @Override + public byte getByte(TDoubleList array, int off) throws IndexOutOfBoundsException { + return (byte) array.get(off); + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observable.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/package-info.java index 82e56164..55627df4 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observable.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/package-info.java @@ -1,10 +1,11 @@ -package de.lmu.ifi.dbs.elki.utilities.designpattern; - +/** + * <p>Common API for accessing objects that are "array-like", including lists, numerical vectors, database vectors and arrays.</p> + */ /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -22,28 +23,4 @@ package de.lmu.ifi.dbs.elki.utilities.designpattern; You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ - - -/** - * Observable design pattern. - * - * @author Erich Schubert - * - * @apiviz.has Observers - * - * @param <T> the object to observer - */ -public interface Observable<T> { - /** - * Add an observer to the object. - * - * @param o Observer to add - */ - public void addObserver(Observer<? super T> o); - /** - * Remove an observer from the object. - * - * @param o Observer to remove - */ - public void removeObserver(Observer<? super T> o); -}
\ No newline at end of file +package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike;
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoublePriorityObject.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoublePriorityObject.java new file mode 100644 index 00000000..976a4d0c --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoublePriorityObject.java @@ -0,0 +1,127 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures.heap; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.utilities.pairs.PairInterface; + +/** + * Object for a priority queue with integer priority. Can be used in the + * {@link de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap + * UpdatableHeap}, since hashcode and equality use the stored objects only, not + * the priority. + * + * @author Erich Schubert + * + * @param <O> Stored object type. + */ +public class DoublePriorityObject<O> implements PairInterface<Double, O>, Comparable<DoublePriorityObject<?>> { + /** + * Priority. + */ + double priority; + + /** + * Stored object. Private; since changing this will break an + * {@link de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap + * UpdatableHeap}s Hash Map! + */ + private O object; + + /** + * Constructor. + * + * @param priority Priority + * @param object Payload + */ + public DoublePriorityObject(double priority, O object) { + super(); + this.priority = priority; + this.object = object; + } + + /** + * Get the priority. + * + * @return Priority + */ + public double getPriority() { + return priority; + } + + /** + * Get the stored object payload + * + * @return object data + */ + public O getObject() { + return object; + } + + @Override + public Double getFirst() { + return priority; + } + + @Override + public O getSecond() { + return object; + } + + @Override + public int hashCode() { + return ((object == null) ? 0 : object.hashCode()); + } + + @Override + public boolean equals(Object obj) { + if(this == obj) { + return true; + } + if(obj == null) { + return false; + } + if(!(obj instanceof DoublePriorityObject)) { + return false; + } + DoublePriorityObject<?> other = (DoublePriorityObject<?>) obj; + if(object == null) { + return (other.object == null); + } + else { + return object.equals(other.object); + } + } + + @Override + public int compareTo(DoublePriorityObject<?> o) { + return Double.compare(o.priority, this.priority); + } + + @Override + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append(priority).append(":").append(object.toString()); + return buf.toString(); + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/Heap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/Heap.java index 307e3ecc..307a0807 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/Heap.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/Heap.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -27,14 +27,22 @@ import java.io.Serializable; import java.util.AbstractQueue; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Comparator; import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.NoSuchElementException; +import de.lmu.ifi.dbs.elki.math.MathUtil; + /** - * Basic in-memory heap structure. Closely related to a {@link java.util.PriorityQueue}, - * but here we can override methods to obtain e.g. a {@link TopBoundedHeap} + * Basic in-memory heap structure. Closely related to a + * {@link java.util.PriorityQueue}, but here we can override methods to obtain + * e.g. a {@link TopBoundedHeap} + * + * Additionally, this heap is built lazily: if you first add many elements, then + * poll the heap, it will be bulk-loaded in O(n) instead of iteratively built in + * O(n log n). This is implemented via a simple validTo counter. * * @author Erich Schubert * @@ -49,11 +57,8 @@ public class Heap<E> extends AbstractQueue<E> implements Serializable { /** * Heap storage - * - * Note: keep private; all write access should be done through - * {@link #putInQueue} for subclasses to track! */ - private Object[] queue; + protected transient Object[] queue; /** * Current number of objects @@ -61,9 +66,14 @@ public class Heap<E> extends AbstractQueue<E> implements Serializable { protected int size = 0; /** + * Indicate up to where the heap is valid + */ + protected int validSize = 0; + + /** * The comparator or {@code null} */ - private final Comparator<? super E> comparator; + protected final Comparator<Object> comparator; /** * (Structural) modification counter. Used to invalidate iterators. @@ -106,230 +116,288 @@ public class Heap<E> extends AbstractQueue<E> implements Serializable { * @param size initial capacity * @param comparator Comparator */ + @SuppressWarnings("unchecked") public Heap(int size, Comparator<? super E> comparator) { super(); this.size = 0; this.queue = new Object[size]; - this.comparator = comparator; + this.comparator = (Comparator<Object>) comparator; + } + + @Override + public boolean add(E e) { + // Never full - overriding probably slightly faster + return offer(e); } @Override - public synchronized boolean offer(E e) { + public boolean offer(E e) { // resize when needed - considerResize(size + 1); - final int parent = parent(size); - // append element - modCount++; - putInQueue(size, e); - this.size = size + 1; - heapifyUp(parent); + if(size + 1 > queue.length) { + resize(size + 1); + } + // final int pos = size; + this.queue[size] = e; + this.size += 1; + heapifyUp(size - 1, e); + validSize += 1; // We have changed - return true according to {@link Collection#put} + modCount++; return true; } @Override - public synchronized E peek() { + public E peek() { if(size == 0) { return null; } + ensureValid(); return castQueueElement(0); } @Override public E poll() { + ensureValid(); return removeAt(0); } /** + * Repair the heap + */ + protected void ensureValid() { + if(validSize != size) { + if(size > 1) { + // Bottom up heap update. + if(comparator != null) { + // Parent of first invalid + int nextmin = validSize > 0 ? ((validSize - 1) >>> 1) : 0; + int curmin = MathUtil.nextAllOnesInt(nextmin); // Next line + int nextmax = curmin - 1; // End of valid line + int pos = (size - 2) >>> 1; // Parent of last element + // System.err.println(validSize+"<="+size+" iter:"+pos+"->"+curmin+", "+nextmin); + while(pos >= nextmin) { + // System.err.println(validSize+"<="+size+" iter:"+pos+"->"+curmin); + while(pos >= curmin) { + if(!heapifyDownComparator(pos, queue[pos])) { + final int parent = (pos - 1) >>> 1; + if(parent < curmin) { + nextmin = Math.min(nextmin, parent); + nextmax = Math.max(nextmax, parent); + } + } + pos--; + } + curmin = nextmin; + pos = Math.min(pos, nextmax); + nextmax = -1; + } + } + else { + // Parent of first invalid + int nextmin = validSize > 0 ? ((validSize - 1) >>> 1) : 0; + int curmin = MathUtil.nextAllOnesInt(nextmin); // Next line + int nextmax = curmin - 1; // End of valid line + int pos = (size - 2) >>> 1; // Parent of last element + // System.err.println(validSize+"<="+size+" iter:"+pos+"->"+curmin+", "+nextmin); + while(pos >= nextmin) { + // System.err.println(validSize+"<="+size+" iter:"+pos+"->"+curmin); + while(pos >= curmin) { + if(!heapifyDownComparable(pos, queue[pos])) { + final int parent = (pos - 1) >>> 1; + if(parent < curmin) { + nextmin = Math.min(nextmin, parent); + nextmax = Math.max(nextmax, parent); + } + } + pos--; + } + curmin = nextmin; + pos = Math.min(pos, nextmax); + nextmax = -1; + } + } + } + validSize = size; + } + } + + /** * Remove the element at the given position. * * @param pos Element position. */ - protected synchronized E removeAt(int pos) { + protected E removeAt(int pos) { if(pos < 0 || pos >= size) { return null; } + final E ret = castQueueElement(pos); + // Replacement object: + final Object reinsert = queue[size - 1]; + queue[size - 1] = null; + // Keep heap in sync + if(validSize == size) { + size -= 1; + validSize -= 1; + heapifyDown(pos, reinsert); + } + else { + size -= 1; + validSize = Math.min(pos >>> 1, validSize); + queue[pos] = reinsert; + } modCount++; - E ret = castQueueElement(0); - // remove! - putInQueue(pos, queue[size - 1]); - size = size - 1; - // avoid dangling references! - putInQueue(size, null); - heapifyDown(pos); return ret; } /** - * Compute parent index in heap array. - * - * @param pos Element index - * @return Parent index - */ - private int parent(int pos) { - return (pos - 1) / 2; - } - - /** - * Compute left child index in heap array. + * Execute a "Heapify Upwards" aka "SiftUp". Used in insertions. * - * @param pos Element index - * @return left child index + * @param pos insertion position + * @param elem Element to insert */ - private int leftChild(int pos) { - return 2 * pos + 1; + protected void heapifyUp(int pos, E elem) { + assert (pos < size && pos >= 0); + if(comparator != null) { + heapifyUpComparator(pos, elem); + } + else { + heapifyUpComparable(pos, elem); + } } /** - * Compute right child index in heap array. + * Execute a "Heapify Upwards" aka "SiftUp". Used in insertions. * - * @param pos Element index - * @return right child index + * @param pos insertion position + * @param elem Element to insert */ - private int rightChild(int pos) { - return 2 * pos + 2; + @SuppressWarnings("unchecked") + protected void heapifyUpComparable(int pos, Object elem) { + final Comparable<Object> cur = (Comparable<Object>) elem; // queue[pos]; + while(pos > 0) { + final int parent = (pos - 1) >>> 1; + Object par = queue[parent]; + + if(cur.compareTo(par) >= 0) { + break; + } + queue[pos] = par; + pos = parent; + } + queue[pos] = cur; } /** * Execute a "Heapify Upwards" aka "SiftUp". Used in insertions. * * @param pos insertion position + * @param cur Element to insert */ - protected void heapifyUp(int pos) { - if(pos < 0 || pos >= size) { - return; - } - // precondition: both child trees are already sorted. - final int parent = parent(pos); - final int lchild = leftChild(pos); - final int rchild = rightChild(pos); - - int min = pos; - if(lchild < size) { - if(compare(min, lchild) > 0) { - min = lchild; - } - } - if(rchild < size) { - if(compare(min, rchild) > 0) { - min = rchild; + protected void heapifyUpComparator(int pos, Object cur) { + while(pos > 0) { + final int parent = (pos - 1) >>> 1; + Object par = queue[parent]; + + if(comparator.compare(cur, par) >= 0) { + break; } + queue[pos] = par; + pos = parent; } - if(min != pos) { - swap(pos, min); - heapifyUp(parent); - } - } - - /** - * Start a heapify up at the parent of this node, since we've changed a child - * - * @param pos Position to start the modification. - */ - protected void heapifyUpParent(int pos) { - heapifyUp(parent(pos)); + queue[pos] = cur; } /** * Execute a "Heapify Downwards" aka "SiftDown". Used in deletions. * * @param pos re-insertion position + * @param reinsert Object to reinsert + * @return true when the order was changed */ - protected void heapifyDown(int pos) { - if(pos < 0 || pos >= size) { - return; - } - final int lchild = leftChild(pos); - final int rchild = rightChild(pos); - - int min = pos; - if(lchild < size) { - if(compare(min, lchild) > 0) { - min = lchild; - } - } - if(rchild < size) { - if(compare(min, rchild) > 0) { - min = rchild; - } + protected boolean heapifyDown(int pos, Object reinsert) { + assert (pos >= 0); + if(comparator != null) { + return heapifyDownComparator(pos, reinsert); } - if(min != pos) { - // swap with minimal element - swap(pos, min); - // recurse down - heapifyDown(min); + else { + return heapifyDownComparable(pos, reinsert); } } /** - * Put an element into the queue at a given position. This allows subclasses - * to index the queue. - * - * @param index Index - * @param e Element - */ - protected void putInQueue(int index, Object e) { - queue[index] = e; - } - - /** - * Swap two elements in the heap. + * Execute a "Heapify Downwards" aka "SiftDown". Used in deletions. * - * @param a Element - * @param b Element + * @param ipos re-insertion position + * @return true when the order was changed */ - protected void swap(int a, int b) { - Object oa = queue[a]; - Object ob = queue[b]; - putInQueue(a, ob); - putInQueue(b, oa); - modCount++; - } - @SuppressWarnings("unchecked") - protected int compare(int pos1, int pos2) { - if(comparator != null) { - return comparator.compare(castQueueElement(pos1), castQueueElement(pos2)); - } - try { - Comparable<E> c = (Comparable<E>) castQueueElement(pos1); - return c.compareTo(castQueueElement(pos2)); - } - catch(ClassCastException e) { - throw e; - } - } + protected boolean heapifyDownComparable(final int ipos, Object reinsert) { + Comparable<Object> cur = (Comparable<Object>) reinsert; + int pos = ipos; + final int half = size >>> 1; + while(pos < half) { + // Get left child (must exist!) + int cpos = (pos << 1) + 1; + Object child = queue[cpos]; + // Test right child, if present + final int rchild = cpos + 1; + if(rchild < size) { + Object right = queue[rchild]; + if(((Comparable<Object>) child).compareTo(right) > 0) { + cpos = rchild; + child = right; + } + } - @SuppressWarnings("unchecked") - protected int compareExternal(E o1, int pos2) { - if(comparator != null) { - return comparator.compare(o1, castQueueElement(pos2)); - } - try { - Comparable<E> c = (Comparable<E>) o1; - return c.compareTo(castQueueElement(pos2)); - } - catch(ClassCastException e) { - throw e; + if(cur.compareTo(child) <= 0) { + break; + } + queue[pos] = child; + pos = cpos; } + queue[pos] = cur; + return (pos == ipos); } - @SuppressWarnings("unchecked") - protected int compareExternalExternal(E o1, E o2) { - if(comparator != null) { - return comparator.compare(o1, o2); - } - try { - Comparable<E> c = (Comparable<E>) o1; - return c.compareTo(o2); - } - catch(ClassCastException e) { - throw e; + /** + * Execute a "Heapify Downwards" aka "SiftDown". Used in deletions. + * + * @param ipos re-insertion position + * @return true when the order was changed + */ + protected boolean heapifyDownComparator(final int ipos, Object cur) { + int pos = ipos; + final int half = size >>> 1; + while(pos < half) { + int min = pos; + Object best = cur; + + final int lchild = (pos << 1) + 1; + Object left = queue[lchild]; + if(comparator.compare(best, left) > 0) { + min = lchild; + best = left; + } + final int rchild = lchild + 1; + if(rchild < size) { + Object right = queue[rchild]; + if(comparator.compare(best, right) > 0) { + min = rchild; + best = right; + } + } + if(min == pos) { + break; + } + queue[pos] = best; + pos = min; } + queue[pos] = cur; + return (pos == ipos); } @SuppressWarnings("unchecked") - protected E castQueueElement(int n) { + protected final E castQueueElement(int n) { return (E) queue[n]; } @@ -343,46 +411,28 @@ public class Heap<E> extends AbstractQueue<E> implements Serializable { * * @param requiredSize required capacity */ - private void considerResize(int requiredSize) { - if(requiredSize > queue.length) { - // Double until 64, then increase by 50% each time. - int newCapacity = ((queue.length < 64) ? ((queue.length + 1) * 2) : ((queue.length / 2) * 3)); - // overflow? - if(newCapacity < 0) { - newCapacity = Integer.MAX_VALUE; - } - if(requiredSize > newCapacity) { - newCapacity = requiredSize; - } - grow(newCapacity); - } - } - - /** - * Execute the actual resize operation. - * - * @param newsize New size - */ - private void grow(int newsize) { - // check for overflows - if(newsize < 0) { + protected final void resize(int requiredSize) { + // Double until 64, then increase by 50% each time. + int newCapacity = ((queue.length < 64) ? ((queue.length + 1) * 2) : ((queue.length / 2) * 3)); + // overflow? + if(newCapacity < 0) { throw new OutOfMemoryError(); } - if(newsize == queue.length) { - return; + if(requiredSize > newCapacity) { + newCapacity = requiredSize; } - modCount++; - queue = Arrays.copyOf(queue, newsize); + queue = Arrays.copyOf(queue, newCapacity); } @Override public void clear() { - modCount++; // clean up references in the array for memory management for(int i = 0; i < size; i++) { queue[i] = null; } this.size = 0; + this.validSize = -1; + modCount++; } @Override @@ -398,13 +448,26 @@ public class Heap<E> extends AbstractQueue<E> implements Serializable { return false; } - // TODO: bulk add implementation of addAll? - @Override public Iterator<E> iterator() { return new Itr(); } + @Override + public boolean addAll(Collection<? extends E> c) { + final int addsize = c.size(); + if(addsize <= 0) { + return false; + } + if(size + addsize > queue.length) { + resize(size + addsize); + } + for(E elem : c) { + add(elem); + } + return true; + } + /** * Iterator over queue elements. No particular order (i.e. heap order!) * @@ -453,10 +516,10 @@ public class Heap<E> extends AbstractQueue<E> implements Serializable { expectedModCount = modCount; } } - + /** - * Return the heap as a sorted array list, by repeated polling. - * This will empty the heap! + * Return the heap as a sorted array list, by repeated polling. This will + * empty the heap! * * @return new array list */ @@ -467,4 +530,34 @@ public class Heap<E> extends AbstractQueue<E> implements Serializable { } return ret; } + + /** + * Test whether the heap is still valid. + * + * Debug method. + * + * @return {@code null} when the heap is correct + */ + protected String checkHeap() { + ensureValid(); + if(comparator == null) { + for(int i = 1; i < size; i++) { + final int parent = (i - 1) >>> 1; + @SuppressWarnings("unchecked") + Comparable<Object> po = (Comparable<Object>) queue[parent]; + if(po.compareTo(queue[i]) > 0) { + return "@" + parent + ": " + queue[parent] + " < @" + i + ": " + queue[i]; + } + } + } + else { + for(int i = 1; i < size; i++) { + final int parent = (i - 1) >>> 1; + if(comparator.compare(queue[parent], queue[i]) > 0) { + return "@" + parent + ": " + queue[parent] + " < @" + i + ": " + queue[i]; + } + } + } + return null; + } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerPriorityObject.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerPriorityObject.java index 0bfa8a90..9dd941ec 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerPriorityObject.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerPriorityObject.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -27,8 +27,9 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.PairInterface; /** * Object for a priority queue with integer priority. Can be used in the - * {@link de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap UpdatableHeap}, since hashcode and equality use the stored objects - * only, not the priority. + * {@link de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap + * UpdatableHeap}, since hashcode and equality use the stored objects only, not + * the priority. * * @author Erich Schubert * @@ -42,13 +43,14 @@ public class IntegerPriorityObject<O> implements PairInterface<Integer, O>, Comp /** * Stored object. Private; since changing this will break an - * {@link de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap UpdatableHeap}s Hash Map! + * {@link de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap + * UpdatableHeap}s Hash Map! */ private O object; /** * Constructor. - * + * * @param priority Priority * @param object Payload */ @@ -115,4 +117,11 @@ public class IntegerPriorityObject<O> implements PairInterface<Integer, O>, Comp public int compareTo(IntegerPriorityObject<?> o) { return o.priority - this.priority; } + + @Override + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append(priority).append(":").append(object.toString()); + return buf.toString(); + } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNHeap.java index 9f2d29f3..a1706c84 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNHeap.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNHeap.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -87,7 +87,7 @@ public class KNNHeap<D extends Distance<D>> extends TiedTopBoundedHeap<DistanceR * @return KNNList with the heaps contents. */ public KNNList<D> toKNNList() { - return new KNNList<D>(this, maxdist); + return new KNNList<D>(this); } /** diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNList.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNList.java index 02a5264c..b19612f2 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNList.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNList.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,15 +23,15 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import java.util.AbstractList; -import java.util.ArrayList; -import java.util.Collection; +import java.util.AbstractCollection; import java.util.Iterator; import java.util.List; +import java.util.Queue; import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs; -import de.lmu.ifi.dbs.elki.database.ids.DBID; import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; +import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult; +import de.lmu.ifi.dbs.elki.database.query.knn.KNNUtil; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; /** @@ -39,49 +39,60 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; * * @author Erich Schubert * - * @apiviz.composedOf DBIDItr - * @apiviz.composedOf DBIDView - * @apiviz.composedOf DistanceItr - * @apiviz.composedOf DistanceView - * - * @param <D> + * @param <D> Distance type */ -public class KNNList<D extends Distance<D>> extends ArrayList<DistanceResultPair<D>> { - /** - * Serial ID - */ - private static final long serialVersionUID = 1L; - +public class KNNList<D extends Distance<D>> extends AbstractCollection<DistanceResultPair<D>> implements KNNResult<D> { /** * The value of k this was materialized for. */ private final int k; /** - * The maximum distance to return if size() < k + * The actual data array. */ - private final D maxdist; + private final Object[] data; /** - * Constructor, to be called from KNNHeap only! + * Constructor, to be called from KNNHeap only. Use {@link KNNHeap#toKNNList} + * instead! * - * @param heap Calling heap. - * @param maxdist infinite distance to return. + * @param heap Calling heap */ - protected KNNList(KNNHeap<D> heap, D maxdist) { - super(heap.size()); + protected KNNList(KNNHeap<D> heap) { + super(); + this.data = new Object[heap.size()]; this.k = heap.getK(); - this.maxdist = maxdist; + assert(heap.size() >= this.k) : "Heap doesn't contain enough objects!"; // Get sorted data from heap; but in reverse. - int i; - for(i = 0; i < heap.size(); i++) { - super.add(null); + int i = heap.size(); + while(!heap.isEmpty()) { + i--; + assert (i >= 0); + data[i] = heap.poll(); } + assert (data.length == 0 || data[0] != null); + assert (heap.size() == 0); + } + + /** + * Constructor. With a KNNHeap, use {@link KNNHeap#toKNNList} instead! + * + * @param heap Calling heap + * @param k K value + */ + public KNNList(Queue<D> heap, int k) { + super(); + this.data = new Object[heap.size()]; + this.k = k; + assert(heap.size() >= this.k) : "Heap doesn't contain enough objects!"; + // Get sorted data from heap; but in reverse. + int i = heap.size(); while(!heap.isEmpty()) { i--; assert (i >= 0); - super.set(i, heap.poll()); + data[i] = heap.poll(); } + assert (data.length == 0 || data[0] != null); assert (heap.size() == 0); } @@ -99,30 +110,19 @@ public class KNNList<D extends Distance<D>> extends ArrayList<DistanceResultPair * * @return Maximum distance */ + @Override public D getKNNDistance() { - if(size() < getK()) { - return maxdist; - } return get(getK() - 1).getDistance(); } /** - * Get maximum distance in list - */ - public D getMaximumDistance() { - if(isEmpty()) { - return maxdist; - } - return get(size() - 1).getDistance(); - } - - /** * View as ArrayDBIDs * * @return Static DBIDs */ + @Override public ArrayDBIDs asDBIDs() { - return new DBIDView(this); + return KNNUtil.asDBIDs(this); } /** @@ -130,221 +130,73 @@ public class KNNList<D extends Distance<D>> extends ArrayList<DistanceResultPair * * @return List of distances view */ + @Override public List<D> asDistanceList() { - return new DistanceView<D>(this); + return KNNUtil.asDistanceList(this); } /* Make the list unmodifiable! */ @Override - public boolean add(DistanceResultPair<D> e) { - throw new UnsupportedOperationException(); - } - - @Override - public void add(int index, DistanceResultPair<D> element) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean addAll(Collection<? extends DistanceResultPair<D>> c) { - throw new UnsupportedOperationException(); - } - + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append("kNNList["); + Iterator<DistanceResultPair<D>> iter = this.iterator(); + while(iter.hasNext()) { + DistanceResultPair<D> pair = iter.next(); + buf.append(pair.getDistance()).append(":").append(pair.getDBID()); + if(iter.hasNext()) { + buf.append(","); + } + } + buf.append("]"); + return buf.toString(); + } + + @SuppressWarnings("unchecked") @Override - public boolean addAll(int index, Collection<? extends DistanceResultPair<D>> c) { - throw new UnsupportedOperationException(); + public DistanceResultPair<D> get(int index) { + return (DistanceResultPair<D>) data[index]; } @Override - public void clear() { - throw new UnsupportedOperationException(); + public Iterator<DistanceResultPair<D>> iterator() { + return new Itr(); } @Override - public DistanceResultPair<D> remove(int index) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean remove(Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public DistanceResultPair<D> set(int index, DistanceResultPair<D> element) { - throw new UnsupportedOperationException(); - } - - @Override - public void trimToSize() { - throw new UnsupportedOperationException(); + public int size() { + return data.length; } /** - * Proxy iterator for accessing DBIDs. + * Iterator * * @author Erich Schubert - */ - protected static class DBIDItr implements Iterator<DBID> { - /** - * The real iterator. - */ - Iterator<? extends DistanceResultPair<?>> itr; - - /** - * Constructor. - */ - protected DBIDItr(Iterator<? extends DistanceResultPair<?>> itr) { - super(); - this.itr = itr; - } - - @Override - public boolean hasNext() { - return itr.hasNext(); - } - - @Override - public DBID next() { - return itr.next().getDBID(); - } - - @Override - public void remove() { - itr.remove(); - } - } - - /** - * A view on the DBIDs of the result * - * @author Erich Schubert + * @apiviz.exclude */ - protected static class DBIDView extends AbstractList<DBID> implements ArrayDBIDs { + private class Itr implements Iterator<DistanceResultPair<D>> { /** - * The true list. + * Cursor position */ - final List<? extends DistanceResultPair<?>> parent; - - /** - * Constructor. - * - * @param parent Owner - */ - public DBIDView(List<? extends DistanceResultPair<?>> parent) { - super(); - this.parent = parent; - } - - @Override - public DBID get(int i) { - return parent.get(i).getDBID(); - } - - @Override - public Collection<DBID> asCollection() { - return this; - } - - @Override - public Iterator<DBID> iterator() { - return new DBIDItr(parent.iterator()); - } - - @Override - public int size() { - return parent.size(); - } - } - - /** - * Proxy iterator for accessing DBIDs. - * - * @author Erich Schubert - */ - protected static class DistanceItr<D extends Distance<D>> implements Iterator<D> { - /** - * The real iterator. - */ - Iterator<? extends DistanceResultPair<D>> itr; - - /** - * Constructor. - */ - protected DistanceItr(Iterator<? extends DistanceResultPair<D>> itr) { - super(); - this.itr = itr; - } + private int pos = -1; @Override public boolean hasNext() { - return itr.hasNext(); + return pos + 1 < data.length; } + @SuppressWarnings("unchecked") @Override - public D next() { - return itr.next().getDistance(); + public DistanceResultPair<D> next() { + pos++; + return (DistanceResultPair<D>) data[pos]; } @Override public void remove() { - itr.remove(); - } - } - - /** - * A view on the Distances of the result - * - * @author Erich Schubert - */ - protected static class DistanceView<D extends Distance<D>> extends AbstractList<D> implements List<D> { - /** - * The true list. - */ - final List<? extends DistanceResultPair<D>> parent; - - /** - * Constructor. - * - * @param parent Owner - */ - public DistanceView(List<? extends DistanceResultPair<D>> parent) { - super(); - this.parent = parent; + throw new UnsupportedOperationException("kNN results are unmodifiable."); } - - @Override - public D get(int i) { - return parent.get(i).getDistance(); - } - - @Override - public Iterator<D> iterator() { - return new DistanceItr<D>(parent.iterator()); - } - - @Override - public int size() { - return parent.size(); - } - } - - /** - * View as ArrayDBIDs - * - * @return Static DBIDs - */ - public static ArrayDBIDs asDBIDs(List<? extends DistanceResultPair<?>> list) { - return new DBIDView(list); - } - - /** - * View as list of distances - * - * @return List of distances view - */ - public static <D extends Distance<D>> List<D> asDistanceList(List<? extends DistanceResultPair<D>> list) { - return new DistanceView<D>(list); } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TiedTopBoundedHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TiedTopBoundedHeap.java index ba4307b1..c0ce3acf 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TiedTopBoundedHeap.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TiedTopBoundedHeap.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,15 +23,17 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap; along with this program. If not, see <http://www.gnu.org/licenses/>. */ +import java.util.ArrayList; import java.util.Comparator; import java.util.Iterator; -import java.util.LinkedList; +import java.util.List; import de.lmu.ifi.dbs.elki.utilities.iterator.MergedIterator; /** - * A size-limited heap similar to {@link TopBoundedHeap}, discarding elements with - * the highest value. However, this variation keeps a list of tied elements. + * A size-limited heap similar to {@link TopBoundedHeap}, discarding elements + * with the highest value. However, this variation keeps a list of tied + * elements. * * @author Erich Schubert * @@ -46,7 +48,7 @@ public class TiedTopBoundedHeap<E> extends TopBoundedHeap<E> { /** * List to keep ties in. */ - private LinkedList<E> ties = new LinkedList<E>(); + private List<E> ties = new ArrayList<E>(); /** * Constructor with comparator. @@ -90,31 +92,44 @@ public class TiedTopBoundedHeap<E> extends TopBoundedHeap<E> { } @Override - public synchronized E peek() { - if (ties.isEmpty()) { + public E peek() { + if(ties.isEmpty()) { return super.peek(); - } else { - return ties.peek() ; + } + else { + return ties.get(ties.size() - 1); } } @Override public E poll() { - if (ties.isEmpty()) { + if(ties.isEmpty()) { return super.poll(); - } else { - return ties.poll(); + } + else { + return ties.remove(ties.size() - 1); } } @Override protected void handleOverflow(E e) { - if (super.compareExternal(e, 0) == 0) { - if (!ties.isEmpty() && super.compareExternalExternal(e, ties.peek()) < 0) { - ties.clear(); + boolean tied = false; + if(comparator == null) { + @SuppressWarnings("unchecked") + Comparable<Object> c = (Comparable<Object>) e; + if(c.compareTo(queue[0]) == 0) { + tied = true; + } + } + else { + if(comparator.compare(e, queue[0]) == 0) { + tied = true; } + } + if(tied) { ties.add(e); - } else { + } + else { // Also remove old ties. ties.clear(); } diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TiedTopBoundedUpdatableHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TiedTopBoundedUpdatableHeap.java new file mode 100644 index 00000000..4fbc852e --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TiedTopBoundedUpdatableHeap.java @@ -0,0 +1,175 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures.heap; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; +import de.lmu.ifi.dbs.elki.utilities.iterator.MergedIterator; + +/** + * A size-limited heap similar to {@link TopBoundedHeap}, discarding elements + * with the highest value. However, this variation keeps a list of tied + * elements. + * + * @author Erich Schubert + * + * @param <E> Object type + */ +public class TiedTopBoundedUpdatableHeap<E> extends TopBoundedUpdatableHeap<E> { + /** + * Serial version + */ + private static final long serialVersionUID = 1L; + + /** + * List to keep ties in. + */ + private List<E> ties = new ArrayList<E>(); + + /** + * Constructor with comparator. + * + * @param maxsize Maximum size of heap (unless tied) + * @param comparator Comparator + */ + public TiedTopBoundedUpdatableHeap(int maxsize, Comparator<? super E> comparator) { + super(maxsize, comparator); + } + + /** + * Constructor for Comparable objects. + * + * @param maxsize Maximum size of heap (unless tied) + */ + public TiedTopBoundedUpdatableHeap(int maxsize) { + this(maxsize, null); + } + + @Override + public int size() { + return super.size() + ties.size(); + } + + @Override + public void clear() { + super.clear(); + ties.clear(); + } + + @Override + public boolean contains(Object o) { + return ties.contains(o) || super.contains(o); + } + + @SuppressWarnings("unchecked") + @Override + public Iterator<E> iterator() { + return new MergedIterator<E>(ties.iterator(), super.iterator()); + } + + @Override + public boolean offerAt(int pos, E e) { + if(pos == IN_TIES) { + for(Iterator<E> i = ties.iterator(); i.hasNext();) { + E e2 = i.next(); + if(e.equals(e2)) { + if(compare(e, e2) <= 0) { + i.remove(); + index.remove(e2); + } + // while we did not change, this still was "successful". + return true; + } + } + throw new AbortException("Heap corrupt - should not be reached"); + } + // Updated object will be worse than the current ties + if(pos >= 0 && ties.size() > 0 && compare(e, ties.get(0)) < 0) { + removeAt(pos); + index.remove(e); + // assert(checkHeap() == null) : "removeObject broke heap: "+ checkHeap(); + // Move one object back from ties + final E e2 = ties.remove(ties.size() - 1); + // index.remove(e2); + super.offerAt(NO_VALUE, e2); + return true; + } + return super.offerAt(pos, e); + } + + @Override + public E peek() { + if(ties.isEmpty()) { + return super.peek(); + } + else { + return ties.get(ties.size() - 1); + } + } + + @Override + public E poll() { + if(ties.isEmpty()) { + return super.poll(); + } + else { + E e = ties.remove(ties.size() - 1); + index.remove(e); + return e; + } + } + + @Override + protected void handleOverflow(E e) { + boolean tied = false; + if(comparator == null) { + @SuppressWarnings("unchecked") + Comparable<Object> c = (Comparable<Object>) e; + if(c.compareTo(queue[0]) == 0) { + tied = true; + } + } + else { + if(comparator.compare(e, queue[0]) == 0) { + tied = true; + } + } + if(tied) { + ties.add(e); + index.put(e, IN_TIES); + } + else { + index.remove(e); + // Also remove old ties. + for(E e2 : ties) { + index.remove(e2); + } + ties.clear(); + } + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TopBoundedHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TopBoundedHeap.java index cd7280a5..5b61e6f3 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TopBoundedHeap.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TopBoundedHeap.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -26,19 +26,20 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap; import java.util.Comparator; /** - * Heap class that is bounded in size from the top. - * It will keep the bottom {@code k} Elements only. + * Heap class that is bounded in size from the top. It will keep the bottom + * {@code k} Elements only. * * @author Erich Schubert - * - * @param <E> Element type. Should be {@link Comparable} or a {@link Comparator} needs to be given. + * + * @param <E> Element type. Should be {@link Comparable} or a {@link Comparator} + * needs to be given. */ public class TopBoundedHeap<E> extends Heap<E> { /** * Serial version */ private static final long serialVersionUID = 1L; - + /** * Maximum size */ @@ -62,32 +63,40 @@ public class TopBoundedHeap<E> extends Heap<E> { public TopBoundedHeap(int maxsize, Comparator<? super E> comparator) { super(maxsize + 1, comparator); this.maxsize = maxsize; - assert(maxsize > 0); + assert (maxsize > 0); } @Override public boolean offer(E e) { - // NOTE: we deliberately call super methods here! - // to have the handleOverflow method called consistently. - // don't add if we hit maxsize and are worse - if (super.size() >= maxsize) { - if (super.compareExternal(e, 0) < 0) { - // while we did not change, this still was "successful". - return true; + if(super.size() >= maxsize) { + ensureValid(); + if(comparator == null) { + @SuppressWarnings("unchecked") + Comparable<Object> c = (Comparable<Object>) e; + if(c.compareTo(queue[0]) < 0) { + // while we did not change, this still was "successful". + return true; + } + } + else { + if(comparator.compare(e, queue[0]) < 0) { + // while we did not change, this still was "successful". + return true; + } } } boolean result = super.offer(e); // purge unneeded entry(s) - while (super.size() > maxsize) { + while(super.size() > maxsize) { handleOverflow(super.poll()); } return result; } /** - * Handle an overflow in the structure. - * This function can be overridden to get overflow treatment. + * Handle an overflow in the structure. This function can be overridden to get + * overflow treatment. * * @param e Overflowing element. */ @@ -101,4 +110,4 @@ public class TopBoundedHeap<E> extends Heap<E> { public int getMaxSize() { return maxsize; } -} +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TopBoundedUpdatableHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TopBoundedUpdatableHeap.java new file mode 100644 index 00000000..2b22eba2 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TopBoundedUpdatableHeap.java @@ -0,0 +1,122 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures.heap; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.Comparator; + +/** + * Heap class that is bounded in size from the top. It will keep the bottom + * {@code k} Elements only. + * + * @author Erich Schubert + * + * @param <E> Element type. Should be {@link Comparable} or a {@link Comparator} + * needs to be given. + */ +public class TopBoundedUpdatableHeap<E> extends UpdatableHeap<E> { + /** + * Serial version + */ + private static final long serialVersionUID = 1L; + + /** + * Maximum size + */ + protected int maxsize; + + /** + * Constructor with maximum size only. + * + * @param maxsize Maximum size + */ + public TopBoundedUpdatableHeap(int maxsize) { + this(maxsize, null); + } + + /** + * Constructor with maximum size and {@link Comparator}. + * + * @param maxsize Maximum size + * @param comparator Comparator + */ + public TopBoundedUpdatableHeap(int maxsize, Comparator<? super E> comparator) { + super(maxsize + 1, comparator); + this.maxsize = maxsize; + assert (maxsize > 0); + } + + @Override + public boolean offerAt(int pos, E e) { + // don't add if we hit maxsize and are worse + if(pos == NO_VALUE && super.size() >= maxsize) { + ensureValid(); + if(compare(e, queue[0]) < 0) { + // while we did not change, this still was "successful". + return true; + } + // pos = index.get(e); // Should not be needed. + } + boolean result = super.offerAt(pos, e); + // purge unneeded entry(s) + while(super.size() > maxsize) { + handleOverflow(super.poll()); + } + return result; + } + + /** + * Test if the priority of an object is higher. + * + * @param e New object + * @param object Reference object + * @return True when an update is needed + */ + protected int compare(Object e, Object object) { + if(comparator == null) { + @SuppressWarnings("unchecked") + Comparable<Object> c = (Comparable<Object>) e; + return c.compareTo(queue[0]); + } + else { + return comparator.compare(e, queue[0]); + } + } + + /** + * Handle an overflow in the structure. This function can be overridden to get + * overflow treatment. + * + * @param e Overflowing element. + */ + protected void handleOverflow(E e) { + // index.remove(e); // Should not be needed. + } + + /** + * @return the maximum size + */ + public int getMaxSize() { + return maxsize; + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/UpdatableHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/UpdatableHeap.java index 0ccacadc..745d82cc 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/UpdatableHeap.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/UpdatableHeap.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,8 +23,10 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap; along with this program. If not, see <http://www.gnu.org/licenses/>. */ +import gnu.trove.map.TObjectIntMap; +import gnu.trove.map.hash.TObjectIntHashMap; + import java.util.Comparator; -import java.util.HashMap; /** * A heap as used in OPTICS that allows updating entries. @@ -35,6 +37,16 @@ import java.util.HashMap; */ public class UpdatableHeap<O> extends Heap<O> { /** + * Constant for "not in heap" + */ + protected static final int NO_VALUE = Integer.MIN_VALUE; + + /** + * Constant for "in ties list", for tied heaps. + */ + protected static final int IN_TIES = -1; + + /** * Serial version */ private static final long serialVersionUID = 1L; @@ -42,7 +54,7 @@ public class UpdatableHeap<O> extends Heap<O> { /** * Holds the indices in the heap of each element. */ - private HashMap<O, Integer> index = new HashMap<O, Integer>(); + protected final TObjectIntMap<Object> index = new TObjectIntHashMap<Object>(100, 0.5f, NO_VALUE); /** * Simple constructor with default size. @@ -86,60 +98,111 @@ public class UpdatableHeap<O> extends Heap<O> { } @Override - public synchronized boolean offer(O e) { - Integer pos = index.get(e); - if(pos == null) { - // LoggingUtil.logExpensive(Level.INFO, "Inserting: "+e); - // insert - return super.offer(e); + public boolean offer(O e) { + final int pos = index.get(e); + return offerAt(pos, e); + } + + protected boolean offerAt(final int pos, O e) { + if(pos == NO_VALUE) { + // resize when needed + if(size + 1 > queue.length) { + resize(size + 1); + } + // final int pos = size; + this.queue[size] = e; + index.put(e, size); + size += 1; + // We do NOT YET update the heap. This is done lazily. + // We have changed - return true according to {@link Collection#put} + modCount++; + return true; } else { - // update - if(compareExternal(e, pos) < 0) { - // LoggingUtil.logExpensive(Level.INFO, - // "Updating value: "+e+" vs. "+castQueueElement(pos)); - modCount++; - putInQueue(pos, e); - heapifyUpParent(pos); - // We have changed - return true according to {@link Collection#put} - return true; + assert (pos >= 0) : "Unexpected negative position."; + assert (queue[pos].equals(e)); + // Did the value improve? + if(comparator == null) { + @SuppressWarnings("unchecked") + Comparable<Object> c = (Comparable<Object>) e; + if(c.compareTo(queue[pos]) >= 0) { + // Ignore, but return true according to {@link Collection#put} + return true; + } } else { - // LoggingUtil.logExpensive(Level.INFO, - // "Keeping value: "+e+" vs. "+castQueueElement(pos)); - // Ignore, no improvement. Return success anyway. - return true; + if(comparator.compare(e, queue[pos]) >= 0) { + // Ignore, but return true according to {@link Collection#put} + return true; + } } + if(pos >= validSize) { + queue[pos] = e; + // validSize = Math.min(pos, validSize); + } + else { + // ensureValid(); + heapifyUp(pos, e); + } + modCount++; + // We have changed - return true according to {@link Collection#put} + return true; } } @Override - protected void putInQueue(int pos, Object e) { - super.putInQueue(pos, e); - // Keep index up to date - if(e != null) { - O n = castQueueElement(pos); - index.put(n, pos); + protected O removeAt(int pos) { + if(pos < 0 || pos >= size) { + return null; } - } - - @Override - protected synchronized O removeAt(int pos) { - O node = super.removeAt(pos); + final O ret = castQueueElement(pos); + // Replacement object: + final Object reinsert = queue[size - 1]; + queue[size - 1] = null; + // Keep heap in sync? + if(validSize == size) { + size -= 1; + validSize -= 1; + if(comparator != null) { + if(comparator.compare(ret, reinsert) > 0) { + heapifyUpComparator(pos, reinsert); + } + else { + heapifyDownComparator(pos, reinsert); + } + } + else { + @SuppressWarnings("unchecked") + Comparable<Object> comp = (Comparable<Object>) ret; + if(comp.compareTo(reinsert) > 0) { + heapifyUpComparable(pos, reinsert); + } + else { + heapifyDownComparable(pos, reinsert); + } + } + } + else { + size -= 1; + validSize = Math.min(pos >>> 1, validSize); + queue[pos] = reinsert; + index.put(reinsert, pos); + } + modCount++; // Keep index up to date - index.remove(node); - return node; + index.remove(ret); + return ret; } /** * Remove the given object from the queue. * - * @param e Obejct to remove + * @param e Object to remove * @return Existing entry */ public O removeObject(O e) { - Integer pos = index.get(e); - if(pos != null) { + int pos = index.get(e); + if(pos >= 0) { return removeAt(pos); } else { @@ -153,4 +216,116 @@ public class UpdatableHeap<O> extends Heap<O> { index.remove(node); return node; } + + /** + * Execute a "Heapify Upwards" aka "SiftUp". Used in insertions. + * + * @param pos insertion position + * @param elem Element to insert + */ + @SuppressWarnings("unchecked") + protected void heapifyUpComparable(int pos, Object elem) { + final Comparable<Object> cur = (Comparable<Object>) elem; // queue[pos]; + while(pos > 0) { + final int parent = (pos - 1) >>> 1; + Object par = queue[parent]; + + if(cur.compareTo(par) >= 0) { + break; + } + queue[pos] = par; + index.put(par, pos); + pos = parent; + } + queue[pos] = cur; + index.put(cur, pos); + } + + /** + * Execute a "Heapify Upwards" aka "SiftUp". Used in insertions. + * + * @param pos insertion position + * @param cur Element to insert + */ + protected void heapifyUpComparator(int pos, Object cur) { + while(pos > 0) { + final int parent = (pos - 1) >>> 1; + Object par = queue[parent]; + + if(comparator.compare(cur, par) >= 0) { + break; + } + queue[pos] = par; + index.put(par, pos); + pos = parent; + } + queue[pos] = cur; + index.put(cur, pos); + } + + @SuppressWarnings("unchecked") + @Override + protected boolean heapifyDownComparable(final int ipos, Object reinsert) { + Comparable<Object> cur = (Comparable<Object>) reinsert; + int pos = ipos; + final int half = size >>> 1; + while(pos < half) { + // Get left child (must exist!) + int cpos = (pos << 1) + 1; + Object child = queue[cpos]; + // Test right child, if present + final int rchild = cpos + 1; + if(rchild < size) { + Object right = queue[rchild]; + if(((Comparable<Object>) child).compareTo(right) > 0) { + cpos = rchild; + child = right; + } + } + + if(cur.compareTo(child) <= 0) { + break; + } + queue[pos] = child; + index.put(child, pos); + pos = cpos; + } + queue[pos] = cur; + index.put(cur, pos); + return (pos == ipos); + } + + @Override + protected boolean heapifyDownComparator(final int ipos, Object cur) { + int pos = ipos; + final int half = size >>> 1; + while(pos < half) { + int min = pos; + Object best = cur; + + final int lchild = (pos << 1) + 1; + Object left = queue[lchild]; + if(comparator.compare(best, left) > 0) { + min = lchild; + best = left; + } + final int rchild = lchild + 1; + if(rchild < size) { + Object right = queue[rchild]; + if(comparator.compare(best, right) > 0) { + min = rchild; + best = right; + } + } + if(min == pos) { + break; + } + queue[pos] = best; + index.put(best, pos); + pos = min; + } + queue[pos] = cur; + index.put(cur, pos); + return (pos == ipos); + } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/package-info.java index 45259fe7..3f193171 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 +Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchical.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchical.java index 1bd9b430..697ac640 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchical.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchical.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchy.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchy.java index 94a6c708..3a3c4d45 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchy.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchy.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyHashmapList.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyHashmapList.java index 1b2dd0fa..d09e6d94 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyHashmapList.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyHashmapList.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -92,7 +92,7 @@ public class HierarchyHashmapList<O> implements ModifiableHierarchy<O> { @Override public void remove(O parent, O child) { - // Add child to parent. + // Remove child from parent. { List<O> pchi = this.cmap.get(parent); if(pchi != null) { @@ -104,7 +104,7 @@ public class HierarchyHashmapList<O> implements ModifiableHierarchy<O> { } } } - // Add child to parent + // Remove parent from child { List<O> cpar = this.pmap.get(child); if(cpar != null) { diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyReferenceLists.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyReferenceLists.java index c2185dc9..f6c527ab 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyReferenceLists.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyReferenceLists.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/ModifiableHierarchy.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/ModifiableHierarchy.java index 9faaf189..dadc6f66 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/ModifiableHierarchy.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/ModifiableHierarchy.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/package-info.java index 259ab46b..0aba31be 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 +Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/package-info.java index 31a0f5b4..ae8308af 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 +Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observer.java b/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observer.java index 3fab4ca2..6afec037 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observer.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observer.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.designpattern; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observers.java b/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observers.java index fef6b95c..dacae560 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observers.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observers.java @@ -1,10 +1,12 @@ package de.lmu.ifi.dbs.elki.utilities.designpattern; +import java.util.ArrayList; + /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,30 +25,30 @@ package de.lmu.ifi.dbs.elki.utilities.designpattern; along with this program. If not, see <http://www.gnu.org/licenses/>. */ - /** * Class to manage the observers of an instance. * - * Design note: to avoid reference cycles, this object does not keep track of its owner. + * Design note: to avoid reference cycles, this object does not keep track of + * its owner. * * @author Erich Schubert * * @apiviz.stereotype delegate * @apiviz.has Observer */ -public class Observers<T> extends java.util.Vector<Observer<? super T>> { +public class Observers<T> extends ArrayList<Observer<? super T>> { /** * Serial version */ private static final long serialVersionUID = 1L; - + /** * Constructor. */ public Observers() { super(); } - + /** * Add an observer to the object. * @@ -64,14 +66,14 @@ public class Observers<T> extends java.util.Vector<Observer<? super T>> { public void removeObserver(Observer<? super T> o) { super.remove(o); } - + /** * Notify the observers of the changed object. * * @param owner Owner of the Observers list - changed instance */ public void notifyObservers(T owner) { - for (Observer<? super T> observer : this) { + for(Observer<? super T> observer : this) { observer.update(owner); } } diff --git a/src/de/lmu/ifi/dbs/elki/utilities/designpattern/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/designpattern/package-info.java index e01f64e2..563470af 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/designpattern/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/designpattern/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 +Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/documentation/Description.java b/src/de/lmu/ifi/dbs/elki/utilities/documentation/Description.java index cd9231b1..2769ff13 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/documentation/Description.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/documentation/Description.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.documentation; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/documentation/DocumentationUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/documentation/DocumentationUtil.java index 05859325..1bdef265 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/documentation/DocumentationUtil.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/documentation/DocumentationUtil.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.documentation; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/documentation/Reference.java b/src/de/lmu/ifi/dbs/elki/utilities/documentation/Reference.java index 8b685cf3..acb3a0aa 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/documentation/Reference.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/documentation/Reference.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.documentation; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -36,7 +36,7 @@ import java.lang.annotation.Target; */ @Documented @Retention(RetentionPolicy.RUNTIME) -@Target( { ElementType.TYPE }) +@Target( { ElementType.TYPE, ElementType.METHOD }) public @interface Reference { /** * Publication title. diff --git a/src/de/lmu/ifi/dbs/elki/utilities/documentation/Restricted.java b/src/de/lmu/ifi/dbs/elki/utilities/documentation/Restricted.java new file mode 100644 index 00000000..8daa97ab --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/documentation/Restricted.java @@ -0,0 +1,48 @@ +package de.lmu.ifi.dbs.elki.utilities.documentation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Indicator that the given class has distibution restrictions such as + * associated patents, and therefore must not be included in the release. + * + * @author Erich Schubert + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE }) +public @interface Restricted { + /** + * Restriction reason + * + * @return reason why this class must not be published + */ + String value(); +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/documentation/Title.java b/src/de/lmu/ifi/dbs/elki/utilities/documentation/Title.java index fc6199ae..2a390f19 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/documentation/Title.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/documentation/Title.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.documentation; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/documentation/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/documentation/package-info.java index 8a57e545..70f31ace 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/documentation/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/documentation/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 +Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/APIViolationException.java b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/APIViolationException.java index 37fd0c6a..d332f2b0 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/APIViolationException.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/APIViolationException.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.exceptions; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/AbortException.java b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/AbortException.java index 3025e8e7..768cb243 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/AbortException.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/AbortException.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.exceptions; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/ExceptionMessages.java b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/ExceptionMessages.java index e2d5fb55..1b1eed80 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/ExceptionMessages.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/ExceptionMessages.java @@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.utilities.exceptions; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 +Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/ObjectNotFoundException.java b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/ObjectNotFoundException.java index 9bc9d056..c99e5394 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/ObjectNotFoundException.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/ObjectNotFoundException.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.exceptions; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/UnableToComplyException.java b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/UnableToComplyException.java index 539af3dd..024615f8 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/UnableToComplyException.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/UnableToComplyException.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.exceptions; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/package-info.java index eb701643..f9733d18 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 +Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/AbstractFilteredIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/AbstractFilteredIterator.java index 8cb14df3..a56b34db 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/AbstractFilteredIterator.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/AbstractFilteredIterator.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.iterator; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/EmptyIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/EmptyIterator.java index 10fbca1c..98a3539e 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/EmptyIterator.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/EmptyIterator.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.iterator; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableIterator.java index 7a8e0c73..d416faa6 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableIterator.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableIterator.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.iterator; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableIteratorAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableIteratorAdapter.java index 3976319b..4a8cb512 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableIteratorAdapter.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableIteratorAdapter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.iterator; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableUtil.java index fa748248..8e4afd80 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableUtil.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableUtil.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.iterator; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/MergedIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/MergedIterator.java index 2676a4fb..9208ab14 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/MergedIterator.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/MergedIterator.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.iterator; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -34,15 +34,15 @@ import java.util.Iterator; * * @apiviz.stereotype adapter * @apiviz.uses Iterator oneway - * + * * @param <E> Entry type */ -public class MergedIterator<E> implements Iterator<E> { +public class MergedIterator<E> implements IterableIterator<E> { /** * All the iterators we process */ final Iterator<Iterator<E>> iterators; - + /** * The iterator we are currently processing */ @@ -52,7 +52,7 @@ public class MergedIterator<E> implements Iterator<E> { * The last iterator we returned an object for, for remove() */ Iterator<E> last = null; - + /** * Main constructor. * @@ -83,20 +83,22 @@ public class MergedIterator<E> implements Iterator<E> { @Override public boolean hasNext() { - while((current != null && current.hasNext()) || iterators.hasNext()) { - // Next element in current iterator? - if (current != null && current.hasNext()) { + do { + if(current != null && current.hasNext()) { return true; } + if(!iterators.hasNext()) { + return false; + } // advance master iterator and retry current = iterators.next(); } - return false; + while(true); } @Override public E next() { - while (!current.hasNext()) { + while(!current.hasNext()) { current = iterators.next(); } last = current; @@ -105,9 +107,14 @@ public class MergedIterator<E> implements Iterator<E> { @Override public void remove() { - if (last == null) { + if(last == null) { throw new RuntimeException("Iterator.remove() called without next()"); } last.remove(); } + + @Override + public Iterator<E> iterator() { + return this; + } } diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/OneItemIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/OneItemIterator.java index d67503af..a81dcc18 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/OneItemIterator.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/OneItemIterator.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.iterator; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/ReverseListIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/ReverseListIterator.java index 52cab893..c207e44c 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/ReverseListIterator.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/ReverseListIterator.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.iterator; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/TypeFilterIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/TypeFilterIterator.java index 9bf2ecfc..cd687542 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/TypeFilterIterator.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/TypeFilterIterator.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.iterator; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -33,7 +33,7 @@ import java.util.Iterator; * @param <IN> Input datatype * @param <OUT> Output datatype */ -public class TypeFilterIterator<IN, OUT extends IN> extends AbstractFilteredIterator<IN, OUT> { +public class TypeFilterIterator<IN, OUT extends IN> extends AbstractFilteredIterator<IN, OUT> implements IterableIterator<OUT> { /** * Class restriction */ @@ -83,4 +83,9 @@ public class TypeFilterIterator<IN, OUT extends IN> extends AbstractFilteredIter return null; } } -} + + @Override + public Iterator<OUT> iterator() { + return this; + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableIterator.java index 271ba495..03c1119c 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableIterator.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableIterator.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.iterator; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableListIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableListIterator.java index 0123216d..7b9c9d79 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableListIterator.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableListIterator.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.iterator; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/package-info.java index 52359156..9a889d1d 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 +Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/AbstractParameterizer.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/AbstractParameterizer.java index 9f1a3d49..32543ace 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/AbstractParameterizer.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/AbstractParameterizer.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/InternalParameterizationErrors.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/InternalParameterizationErrors.java index 987497ff..4bec9193 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/InternalParameterizationErrors.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/InternalParameterizationErrors.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/NoParameterValueException.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/NoParameterValueException.java index 00fbac6b..2965f207 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/NoParameterValueException.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/NoParameterValueException.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/OptionID.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/OptionID.java index 8202f9d3..0d685e2b 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/OptionID.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/OptionID.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/OptionUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/OptionUtil.java index f4ad3e48..2aa68611 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/OptionUtil.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/OptionUtil.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/ParameterException.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/ParameterException.java index fabe9c7d..0235b4a9 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/ParameterException.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/ParameterException.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/Parameterizable.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/Parameterizable.java index 044c119c..4149658a 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/Parameterizable.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/Parameterizable.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/Parameterizer.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/Parameterizer.java index b434ea4e..aa5c74bd 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/Parameterizer.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/Parameterizer.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/UnspecifiedParameterException.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/UnspecifiedParameterException.java index 16828b3f..8e294ddb 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/UnspecifiedParameterException.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/UnspecifiedParameterException.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/UnusedParameterException.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/UnusedParameterException.java index 05943069..0914c0f1 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/UnusedParameterException.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/UnusedParameterException.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/WrongParameterValueException.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/WrongParameterValueException.java index 0f9c6260..219b32cd 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/WrongParameterValueException.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/WrongParameterValueException.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AbstractNumberConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AbstractNumberConstraint.java index 6b49faea..f622aba5 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AbstractNumberConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AbstractNumberConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AllOrNoneMustBeSetGlobalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AllOrNoneMustBeSetGlobalConstraint.java index 59a91613..42209d87 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AllOrNoneMustBeSetGlobalConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AllOrNoneMustBeSetGlobalConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualSizeGlobalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualSizeGlobalConstraint.java index 0e04906b..22d1ceb2 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualSizeGlobalConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualSizeGlobalConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualStringConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualStringConstraint.java index 342ffd00..ad567fa1 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualStringConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualStringConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalListSizeConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalListSizeConstraint.java index 8f510dc9..b30a45d9 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalListSizeConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalListSizeConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalParameterConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalParameterConstraint.java index 404da18f..b59c9493 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalParameterConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalParameterConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalVectorListElementSizeConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalVectorListElementSizeConstraint.java index fe4b6520..740d9545 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalVectorListElementSizeConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalVectorListElementSizeConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GreaterConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GreaterConstraint.java index 1f894094..22cc50f9 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GreaterConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GreaterConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GreaterEqualConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GreaterEqualConstraint.java index 7a1d2f7a..26145620 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GreaterEqualConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GreaterEqualConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/IntervalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/IntervalConstraint.java index 8a9f1bcf..f9e93a5b 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/IntervalConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/IntervalConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -41,7 +41,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.WrongParameterValueException public class IntervalConstraint implements ParameterConstraint<Number> { /** * Available interval boundary types types: - * {@link IntervalConstraint.IntervalBoundary#OPEN} denotes an opend interval, + * {@link IntervalConstraint.IntervalBoundary#OPEN} denotes an open interval, * i.e. less than (or greater than) comparison * {@link IntervalConstraint.IntervalBoundary#CLOSE} denotes a closed * interval, i.e. an equal to or less than (or equal to or greater than) @@ -66,7 +66,9 @@ public class IntervalConstraint implements ParameterConstraint<Number> { private final Number lowConstraintValue; /** - * The interval boundary for the low constraint value (@see IntervalBoundary) + * The interval boundary for the low constraint value. + * + * @see IntervalBoundary */ private final IntervalBoundary lowBoundary; @@ -76,7 +78,9 @@ public class IntervalConstraint implements ParameterConstraint<Number> { private final Number highConstraintValue; /** - * The interval boundary for the high constraint value (@see IntervalBoundary) + * The interval boundary for the high constraint value. + * + * @see IntervalBoundary */ private final IntervalBoundary highBoundary; @@ -88,12 +92,11 @@ public class IntervalConstraint implements ParameterConstraint<Number> { * than (or equal to, if specified) than the specified high constraint value. * * @param lowConstraintValue the low constraint value (left interval boundary) - * @param lowBoundary the interval boundary for the low constraint value (@see - * IntervalBoundary) + * @param lowBoundary the interval boundary for the low constraint value (see {@link IntervalBoundary}) * @param highConstraintValue the high constraint value (right interval * boundary) * @param highBoundary the interval boundary for the high constraint value - * (@see IntervalBoundary) + * (see {@link IntervalBoundary}) */ public IntervalConstraint(Number lowConstraintValue, IntervalBoundary lowBoundary, Number highConstraintValue, IntervalBoundary highBoundary) { if(lowConstraintValue.doubleValue() >= highConstraintValue.doubleValue()) { diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessConstraint.java index a7c7cebd..0994425e 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessEqualConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessEqualConstraint.java index 9c180c02..712630e8 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessEqualConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessEqualConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessEqualGlobalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessEqualGlobalConstraint.java index 358248cf..9855b96d 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessEqualGlobalConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessEqualGlobalConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessGlobalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessGlobalConstraint.java index 6ea46b09..e475e92f 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessGlobalConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessGlobalConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListGreaterEqualConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListGreaterEqualConstraint.java index fa56d021..0f33b9b2 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListGreaterEqualConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListGreaterEqualConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListSizeConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListSizeConstraint.java index 5c6a5156..f2ef2069 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListSizeConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListSizeConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/NoDuplicateValueGlobalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/NoDuplicateValueGlobalConstraint.java index 7ddd3d3b..04472fa5 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/NoDuplicateValueGlobalConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/NoDuplicateValueGlobalConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OneMustBeSetGlobalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OneMustBeSetGlobalConstraint.java index 7473b6bd..1c8c6b94 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OneMustBeSetGlobalConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OneMustBeSetGlobalConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OnlyOneIsAllowedToBeSetGlobalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OnlyOneIsAllowedToBeSetGlobalConstraint.java index 8f677669..74a1955b 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OnlyOneIsAllowedToBeSetGlobalConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OnlyOneIsAllowedToBeSetGlobalConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterConstraint.java index ea57c0ea..ff66ec05 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterFlagGlobalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterFlagGlobalConstraint.java index 4c5b9262..befc0788 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterFlagGlobalConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterFlagGlobalConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/StringLengthConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/StringLengthConstraint.java index ac8c48b3..84d8fa6d 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/StringLengthConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/StringLengthConstraint.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/package-info.java index 59d6534d..4b8c163a 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 +Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/package-info.java index c3196511..2756327e 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/package-info.java @@ -2,7 +2,7 @@ * <p><b>Parameter handling and option descriptions.</b></p> * * <ol> - * <li><b>Option ID</b>: Any parameter <em>must</em> have a {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID OptionID}.<br /> + * <li><b>Option ID</b>: Any parameter <em>must</em> have an {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID OptionID}.<br /> * These are Singleton objects to uniquely identify the option. They should be "public static". <br /> * The OptionID specifies the parameter name and a generic description. * <p /> @@ -253,7 +253,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 +Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/AbstractParameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/AbstractParameterization.java index a333bffd..156dca1d 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/AbstractParameterization.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/AbstractParameterization.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -173,7 +173,7 @@ public abstract class AbstractParameterization implements Parameterization { } catch(Exception e) { logger.exception(e); - reportError(new InternalParameterizationErrors("Error instantiating internal class.", e)); + reportError(new InternalParameterizationErrors("Error instantiating internal class: "+c.getName(), e)); return null; } } @@ -185,7 +185,7 @@ public abstract class AbstractParameterization implements Parameterization { } catch(Exception e) { logger.exception(e); - reportError(new InternalParameterizationErrors("Error instantiating internal class.", e)); + reportError(new InternalParameterizationErrors("Error instantiating internal class: "+c.getName(), e)); return null; } } diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ChainedParameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ChainedParameterization.java index 33aab341..f62b8128 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ChainedParameterization.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ChainedParameterization.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/EmptyParameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/EmptyParameterization.java index 05a85b49..1fbd26b6 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/EmptyParameterization.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/EmptyParameterization.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ListParameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ListParameterization.java index 8e751fe7..937bb966 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ListParameterization.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ListParameterization.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/MergedParameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/MergedParameterization.java index 7a9ce476..8bba1c2a 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/MergedParameterization.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/MergedParameterization.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -174,7 +174,7 @@ public class MergedParameterization implements Parameterization { return ClassGenericsUtil.tryInstantiate(r, c, this); } catch(Exception e) { - reportError(new InternalParameterizationErrors("Error instantiating internal class.", e)); + reportError(new InternalParameterizationErrors("Error instantiating internal class: "+c.getName(), e)); return null; } } @@ -185,7 +185,7 @@ public class MergedParameterization implements Parameterization { return ClassGenericsUtil.tryInstantiate(c, c, this); } catch(Exception e) { - reportError(new InternalParameterizationErrors("Error instantiating internal class.", e)); + reportError(new InternalParameterizationErrors("Error instantiating internal class: "+c.getName(), e)); return null; } } diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/Parameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/Parameterization.java index be7c422e..f03463f8 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/Parameterization.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/Parameterization.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/SerializedParameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/SerializedParameterization.java index a4eeda1a..73abbca0 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/SerializedParameterization.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/SerializedParameterization.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/TrackParameters.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/TrackParameters.java index 0399a5c7..157efa32 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/TrackParameters.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/TrackParameters.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -205,7 +205,7 @@ public class TrackParameters implements Parameterization { return ClassGenericsUtil.tryInstantiate(r, c, this); } catch(Exception e) { - reportError(new InternalParameterizationErrors("Error instantiating internal class.", e)); + reportError(new InternalParameterizationErrors("Error instantiating internal class: "+c.getName(), e)); return null; } } @@ -216,7 +216,7 @@ public class TrackParameters implements Parameterization { return ClassGenericsUtil.tryInstantiate(c, c, this); } catch(Exception e) { - reportError(new InternalParameterizationErrors("Error instantiating internal class.", e)); + reportError(new InternalParameterizationErrors("Error instantiating internal class: "+c.getName(), e)); return null; } } diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/UnParameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/UnParameterization.java index 5fc930db..3a25ddd4 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/UnParameterization.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/UnParameterization.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -91,7 +91,7 @@ public class UnParameterization implements Parameterization { return ClassGenericsUtil.tryInstantiate(r, c, this); } catch(Exception e) { - reportError(new InternalParameterizationErrors("Error instantiating internal class.", e)); + reportError(new InternalParameterizationErrors("Error instantiating internal class: "+c.getName(), e)); return null; } } @@ -102,7 +102,7 @@ public class UnParameterization implements Parameterization { return ClassGenericsUtil.tryInstantiate(c, c, this); } catch(Exception e) { - reportError(new InternalParameterizationErrors("Error instantiating internal class.", e)); + reportError(new InternalParameterizationErrors("Error instantiating internal class: "+c.getName(), e)); return null; } } diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/package-info.java index 174c52b4..41856ad7 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/package-info.java @@ -8,7 +8,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 +Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ClassListParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ClassListParameter.java index 2ec3fb91..85851e5b 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ClassListParameter.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ClassListParameter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -26,13 +26,9 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; import java.util.ArrayList; import java.util.List; -import de.lmu.ifi.dbs.elki.properties.IterateKnownImplementations; -import de.lmu.ifi.dbs.elki.properties.Properties; import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil; import de.lmu.ifi.dbs.elki.utilities.FormatUtil; import de.lmu.ifi.dbs.elki.utilities.InspectionUtil; -import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator; -import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil; import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; import de.lmu.ifi.dbs.elki.utilities.optionhandling.ParameterException; import de.lmu.ifi.dbs.elki.utilities.optionhandling.UnspecifiedParameterException; @@ -46,14 +42,18 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz * @author Steffi Wanka * @author Erich Schubert * - * @apiviz.uses Properties - * @apiviz.uses IterateKnownImplementations + * @apiviz.uses InspectionUtil * * @param <C> Class type */ // TODO: Add missing constructors. (ObjectListParameter also!) public class ClassListParameter<C> extends ListParameter<Class<? extends C>> { /** + * Class loader + */ + protected static final ClassLoader loader = ClassLoader.getSystemClassLoader(); + + /** * The restriction class for the list of class names. */ protected Class<C> restrictionClass; @@ -145,11 +145,11 @@ public class ClassListParameter<C> extends ListParameter<Class<? extends C>> { try { Class<?> c; try { - c = Class.forName(cl); + c = loader.loadClass(cl); } catch(ClassNotFoundException e) { // try in package of restriction class - c = Class.forName(restrictionClass.getPackage().getName() + "." + cl); + c = loader.loadClass(restrictionClass.getPackage().getName() + "." + cl); } // Redundant check, also in validate(), but not expensive. if(!restrictionClass.isAssignableFrom(c)) { @@ -192,27 +192,10 @@ public class ClassListParameter<C> extends ListParameter<Class<? extends C>> { /** * Get an iterator over all known implementations of the class restriction. * - * @return {@link java.lang.Iterable Iterable} and {@link java.util.Iterator - * Iterator} object - */ - public IterableIterator<Class<?>> getKnownImplementations() { - if(InspectionUtil.NONSTATIC_CLASSPATH) { - return IterableUtil.fromIterable(InspectionUtil.cachedFindAllImplementations(getRestrictionClass())); - } - return new IterateKnownImplementations(getRestrictionClass()); - } - - /** - * Returns the class names allowed according to the restriction class of this - * parameter. - * - * @return class names allowed according to the restriction class defined. + * @return List object */ - public String[] getRestrictionClasses() { - if(restrictionClass != null) { - return Properties.ELKI_PROPERTIES.getProperty(restrictionClass.getName()); - } - return new String[] {}; + public List<Class<?>> getKnownImplementations() { + return InspectionUtil.cachedFindAllImplementations(getRestrictionClass()); } /** @@ -277,8 +260,8 @@ public class ClassListParameter<C> extends ListParameter<Class<? extends C>> { info.append(restrictionClass.getName()); info.append(FormatUtil.NEWLINE); - IterableIterator<Class<?>> known = getKnownImplementations(); - if(known.hasNext()) { + List<Class<?>> known = getKnownImplementations(); + if(!known.isEmpty()) { info.append("Known classes (default package " + prefix + "):"); info.append(FormatUtil.NEWLINE); for(Class<?> c : known) { diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ClassParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ClassParameter.java index 36abc0f7..6b056c03 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ClassParameter.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ClassParameter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,15 +24,12 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; */ import java.lang.reflect.InvocationTargetException; +import java.util.List; import de.lmu.ifi.dbs.elki.logging.LoggingUtil; -import de.lmu.ifi.dbs.elki.properties.IterateKnownImplementations; -import de.lmu.ifi.dbs.elki.properties.Properties; import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil; import de.lmu.ifi.dbs.elki.utilities.FormatUtil; import de.lmu.ifi.dbs.elki.utilities.InspectionUtil; -import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator; -import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil; import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; import de.lmu.ifi.dbs.elki.utilities.optionhandling.ParameterException; import de.lmu.ifi.dbs.elki.utilities.optionhandling.UnspecifiedParameterException; @@ -46,14 +43,21 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz * @author Steffi Wanka * @author Erich Schubert * - * @apiviz.uses Properties - * @apiviz.uses IterateKnownImplementations + * @apiviz.uses InspectionUtil * * @param <C> Class type */ // TODO: add additional constructors with parameter constraints. // TODO: turn restrictionClass into a constraint? public class ClassParameter<C> extends Parameter<Class<?>, Class<? extends C>> { + /** + * Class loader. + */ + protected static final ClassLoader loader = ClassLoader.getSystemClassLoader(); + + /** + * Factory class postfix. + */ public static final String FACTORY_POSTFIX = "$Factory"; /** @@ -133,26 +137,26 @@ public class ClassParameter<C> extends Parameter<Class<?>, Class<? extends C>> { try { // Try exact class factory first. try { - return (Class<? extends C>) Class.forName(value + FACTORY_POSTFIX); + return (Class<? extends C>) loader.loadClass(value + FACTORY_POSTFIX); } catch(ClassNotFoundException e) { // Ignore, retry } try { - return (Class<? extends C>) Class.forName(value); + return (Class<? extends C>) loader.loadClass(value); } catch(ClassNotFoundException e) { // Ignore, retry } // Try factory for guessed name next try { - return (Class<? extends C>) Class.forName(restrictionClass.getPackage().getName() + "." + value + FACTORY_POSTFIX); + return (Class<? extends C>) loader.loadClass(restrictionClass.getPackage().getName() + "." + value + FACTORY_POSTFIX); } catch(ClassNotFoundException e) { // Ignore, retry } // Last try: guessed name prefix only - return (Class<? extends C>) Class.forName(restrictionClass.getPackage().getName() + "." + value); + return (Class<? extends C>) loader.loadClass(restrictionClass.getPackage().getName() + "." + value); } catch(ClassNotFoundException e) { throw new WrongParameterValueException(this, value, "Given class \"" + value + "\" not found.", e); @@ -269,27 +273,10 @@ public class ClassParameter<C> extends Parameter<Class<?>, Class<? extends C>> { /** * Get an iterator over all known implementations of the class restriction. * - * @return {@link java.lang.Iterable Iterable} and {@link java.util.Iterator - * Iterator} object - */ - public IterableIterator<Class<?>> getKnownImplementations() { - if(InspectionUtil.NONSTATIC_CLASSPATH) { - return IterableUtil.fromIterable(InspectionUtil.cachedFindAllImplementations(getRestrictionClass())); - } - return new IterateKnownImplementations(getRestrictionClass()); - } - - /** - * Returns the class names allowed according to the restriction class of this - * class parameter. - * - * @return class names allowed according to the restriction class defined. + * @return List object */ - public String[] getRestrictionClasses() { - if(restrictionClass != null) { - return Properties.ELKI_PROPERTIES.getProperty(restrictionClass.getName()); - } - return new String[] {}; + public List<Class<?>> getKnownImplementations() { + return InspectionUtil.cachedFindAllImplementations(getRestrictionClass()); } /** @@ -310,8 +297,8 @@ public class ClassParameter<C> extends Parameter<Class<?>, Class<? extends C>> { info.append(restrictionClass.getName()); info.append(FormatUtil.NEWLINE); - IterableIterator<Class<?>> known = getKnownImplementations(); - if(known.hasNext()) { + List<Class<?>> known = getKnownImplementations(); + if(!known.isEmpty()) { info.append("Known classes (default package " + restrictionClass.getPackage().getName() + "):"); info.append(FormatUtil.NEWLINE); for(Class<?> c : known) { diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DistanceParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DistanceParameter.java index a47f6d53..bb9dc60c 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DistanceParameter.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DistanceParameter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DoubleListParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DoubleListParameter.java index 2e255f2f..07b10b83 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DoubleListParameter.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DoubleListParameter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DoubleParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DoubleParameter.java index aad0a2ee..9ebb61ee 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DoubleParameter.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DoubleParameter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileListParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileListParameter.java index ec716a63..1b72df80 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileListParameter.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileListParameter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileParameter.java index 7c642fe8..1e04c7ae 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileParameter.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileParameter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/Flag.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/Flag.java index fd383020..e2ce63c2 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/Flag.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/Flag.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/IntListParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/IntListParameter.java index 32675d22..d7b5d570 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/IntListParameter.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/IntListParameter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/IntParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/IntParameter.java index a1b22519..4e494fda 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/IntParameter.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/IntParameter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ListParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ListParameter.java index 0cc35d62..ad0ded5c 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ListParameter.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ListParameter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/LongParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/LongParameter.java index d03d77f1..6f1a7beb 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/LongParameter.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/LongParameter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/NumberParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/NumberParameter.java index 87384e4f..3a1ab946 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/NumberParameter.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/NumberParameter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ObjectListParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ObjectListParameter.java index f5eb2838..cfd74d9a 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ObjectListParameter.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ObjectListParameter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ObjectParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ObjectParameter.java index ffc668c2..0a1a6b27 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ObjectParameter.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ObjectParameter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/Parameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/Parameter.java index 9c555359..8502bbec 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/Parameter.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/Parameter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -468,8 +468,8 @@ public abstract class Parameter<S, T extends S> { /** * Returns the value of the option. * - * You should use either {Parameterization#grab} or {@link #isDefined} to test - * if getValue() will return a well-defined value. + * You should use either {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization#grab} + * or {@link #isDefined} to test if getValue() will return a well-defined value. * * @return the option's value. */ diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/PatternParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/PatternParameter.java index b988f9cb..1f54c5d2 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/PatternParameter.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/PatternParameter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -61,7 +61,7 @@ public class PatternParameter extends Parameter<Pattern, Pattern> { * @param defaultValue the default value of the parameter */ public PatternParameter(OptionID optionID, List<ParameterConstraint<Pattern>> constraint, String defaultValue) { - super(optionID, constraint, Pattern.compile(defaultValue)); + super(optionID, constraint, Pattern.compile(defaultValue, Pattern.CASE_INSENSITIVE)); } /** @@ -108,7 +108,7 @@ public class PatternParameter extends Parameter<Pattern, Pattern> { * @param defaultValue the default value of the parameter */ public PatternParameter(OptionID optionID, ParameterConstraint<Pattern> constraint, String defaultValue) { - super(optionID, constraint, Pattern.compile(defaultValue)); + super(optionID, constraint, Pattern.compile(defaultValue, Pattern.CASE_INSENSITIVE)); } /** @@ -151,7 +151,7 @@ public class PatternParameter extends Parameter<Pattern, Pattern> { * @param defaultValue the default value of the parameter */ public PatternParameter(OptionID optionID, String defaultValue) { - super(optionID, Pattern.compile(defaultValue)); + super(optionID, Pattern.compile(defaultValue, Pattern.CASE_INSENSITIVE)); } /** @@ -173,13 +173,11 @@ public class PatternParameter extends Parameter<Pattern, Pattern> { super(optionID); } - /** {@inheritDoc} */ @Override public String getValueAsString() { return getValue().toString(); } - /** {@inheritDoc} */ @Override protected Pattern parseValue(Object obj) throws ParameterException { if(obj == null) { @@ -190,7 +188,7 @@ public class PatternParameter extends Parameter<Pattern, Pattern> { } if(obj instanceof String) { try { - return Pattern.compile((String) obj); + return Pattern.compile((String) obj, Pattern.CASE_INSENSITIVE); } catch(PatternSyntaxException e) { throw new WrongParameterValueException("Given pattern \"" + obj + "\" for parameter \"" + getName() + "\" is no valid regular expression!"); diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/StringParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/StringParameter.java index 43a19217..ea1c5a2c 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/StringParameter.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/StringParameter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/VectorListParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/VectorListParameter.java index 9fb9c6f1..0e6612b6 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/VectorListParameter.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/VectorListParameter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/package-info.java index e13d29ee..5fcaa0c0 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/package-info.java @@ -8,7 +8,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 +Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/package-info.java index 09d0398e..a1bbc579 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/package-info.java @@ -48,7 +48,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 +Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/CPair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/CPair.java index ce7b5ded..dabc623e 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/CPair.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/CPair.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/CTriple.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/CTriple.java index 28802e3e..5a4b8cbd 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/CTriple.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/CTriple.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleDoublePair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleDoublePair.java index 410f3f36..c24ee8f3 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleDoublePair.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleDoublePair.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleIntPair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleIntPair.java index 98aba136..7bd22095 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleIntPair.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleIntPair.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleObjPair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleObjPair.java index 970926bc..aa4d4b36 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleObjPair.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleObjPair.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/FCPair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/FCPair.java index 00636784..6724ddfb 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/FCPair.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/FCPair.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/IntDoublePair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/IntDoublePair.java index 2806731c..d0f356f8 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/IntDoublePair.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/IntDoublePair.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/IntIntPair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/IntIntPair.java index 62b57709..96108239 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/IntIntPair.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/IntIntPair.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -154,6 +154,11 @@ public class IntIntPair implements Comparable<IntIntPair>, PairInterface<Integer this.second = second; } + @Override + public String toString() { + return "(" + first + ", " + second + ")"; + } + /** * Comparator to compare by second component only */ diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/Pair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/Pair.java index f034bd97..f682e06f 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/Pair.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/Pair.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/PairInterface.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/PairInterface.java index 8e45ce2d..5ea33971 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/PairInterface.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/PairInterface.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/PairUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/PairUtil.java index 69e8ef3c..21917332 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/PairUtil.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/PairUtil.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/SCPair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/SCPair.java index a2880a8f..585c7a57 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/SCPair.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/SCPair.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/Triple.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/Triple.java index 34c8713a..2f75ec5a 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/Triple.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/Triple.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/package-info.java index cda785b3..2fdf3770 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/package-info.java @@ -37,7 +37,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 +Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/AxisBasedReferencePoints.java b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/AxisBasedReferencePoints.java index 5fd4d6b4..3ec38f58 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/AxisBasedReferencePoints.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/AxisBasedReferencePoints.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.referencepoints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -94,11 +94,11 @@ public class AxisBasedReferencePoints<V extends NumberVector<V, ?>> implements R for(int d = 0; d < dim; d++) { vec[d] = mean[d] - delta[d]; } - result.add(factory.newInstance(vec)); + result.add(factory.newNumberVector(vec)); for(int d = 0; d < dim; d++) { vec[d] = mean[d] + delta[d]; } - result.add(factory.newInstance(vec)); + result.add(factory.newNumberVector(vec)); // Plus axis end points: for(int i = 0; i < dim; i++) { @@ -110,7 +110,7 @@ public class AxisBasedReferencePoints<V extends NumberVector<V, ?>> implements R vec[d] = mean[d] + delta[d]; } } - result.add(factory.newInstance(vec)); + result.add(factory.newNumberVector(vec)); } return result; diff --git a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/FullDatabaseReferencePoints.java b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/FullDatabaseReferencePoints.java index 62cb4c03..d427e35a 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/FullDatabaseReferencePoints.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/FullDatabaseReferencePoints.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.referencepoints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/GridBasedReferencePoints.java b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/GridBasedReferencePoints.java index 142f9708..09d36cd8 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/GridBasedReferencePoints.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/GridBasedReferencePoints.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.referencepoints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -117,13 +117,13 @@ public class GridBasedReferencePoints<V extends NumberVector<V, ?>> implements R acc = acc / (gridres + 1); vec[d] = mean[d] + (coord - halfgrid) * delta[d] * gridscale; } - V newp = factory.newInstance(vec); + V newp = factory.newNumberVector(vec); // logger.debug("New reference point: " + FormatUtil.format(vec)); result.add(newp); } } else { - result.add(factory.newInstance(mean)); + result.add(factory.newNumberVector(mean)); // logger.debug("New reference point: " + FormatUtil.format(mean)); } diff --git a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/RandomGeneratedReferencePoints.java b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/RandomGeneratedReferencePoints.java index ed7d74f6..6a56bfcd 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/RandomGeneratedReferencePoints.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/RandomGeneratedReferencePoints.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.referencepoints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -107,7 +107,7 @@ public class RandomGeneratedReferencePoints<V extends NumberVector<V, ?>> implem for(int d = 0; d < dim; d++) { vec[d] = mean[d] + (Math.random() - 0.5) * scale * delta[d]; } - V newp = factory.newInstance(vec); + V newp = factory.newNumberVector(vec); // logger.debug("New reference point: " + FormatUtil.format(vec)); result.add(newp); } diff --git a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/RandomSampleReferencePoints.java b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/RandomSampleReferencePoints.java index 43c5f233..48125019 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/RandomSampleReferencePoints.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/RandomSampleReferencePoints.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.referencepoints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/ReferencePointsHeuristic.java b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/ReferencePointsHeuristic.java index a7b64cc6..70114a32 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/ReferencePointsHeuristic.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/ReferencePointsHeuristic.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.referencepoints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/StarBasedReferencePoints.java b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/StarBasedReferencePoints.java index 9970bf9c..819fc29e 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/StarBasedReferencePoints.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/StarBasedReferencePoints.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.referencepoints; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -118,7 +118,7 @@ public class StarBasedReferencePoints<V extends NumberVector<V, ?>> implements R ArrayList<V> result = new ArrayList<V>(2 * dim + 1); if(!nocenter) { - result.add(factory.newInstance(centroid)); + result.add(factory.newNumberVector(centroid)); } // Plus axis end points through centroid double[] vec = new double[dim]; @@ -129,9 +129,9 @@ public class StarBasedReferencePoints<V extends NumberVector<V, ?>> implements R } } vec[i] = min[i]; - result.add(factory.newInstance(vec)); + result.add(factory.newNumberVector(vec)); vec[i] = max[i]; - result.add(factory.newInstance(vec)); + result.add(factory.newNumberVector(vec)); } return result; diff --git a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/package-info.java index 7c8ce99f..a8ce0bc5 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/package-info.java @@ -7,7 +7,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 +Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/ClipScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/ClipScaling.java index d2f53ac2..97a43f37 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/ClipScaling.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/ClipScaling.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/GammaScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/GammaScaling.java index 3aa539af..719a72c3 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/GammaScaling.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/GammaScaling.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/IdentityScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/IdentityScaling.java index 239d51fe..a2202b92 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/IdentityScaling.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/IdentityScaling.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/LinearScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/LinearScaling.java index c4ea9e1d..87f42835 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/LinearScaling.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/LinearScaling.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/MinusLogScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/MinusLogScaling.java index a3c31169..b5007ad1 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/MinusLogScaling.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/MinusLogScaling.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/ScalingFunction.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/ScalingFunction.java index 3aab82ec..6bd0527f 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/ScalingFunction.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/ScalingFunction.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/StaticScalingFunction.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/StaticScalingFunction.java index 197f4e6c..228f5f1a 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/StaticScalingFunction.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/StaticScalingFunction.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/HeDESNormalizationOutlierScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/HeDESNormalizationOutlierScaling.java index cf880a3f..e7e6ee90 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/HeDESNormalizationOutlierScaling.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/HeDESNormalizationOutlierScaling.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogGammaScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogGammaScaling.java index 4b7c7797..1485204c 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogGammaScaling.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogGammaScaling.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -25,8 +25,8 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier; import de.lmu.ifi.dbs.elki.database.ids.DBID; import de.lmu.ifi.dbs.elki.math.DoubleMinMax; -import de.lmu.ifi.dbs.elki.math.MathUtil; import de.lmu.ifi.dbs.elki.math.MeanVariance; +import de.lmu.ifi.dbs.elki.math.statistics.distribution.GammaDistribution; import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult; import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; @@ -37,7 +37,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; * * @author Erich Schubert */ -@Reference(authors = "H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title = "Interpreting and Unifying Outlier Scores", booktitle = "Proc. 11th SIAM International Conference on Data Mining (SDM), Mesa, AZ, 2011", url = "http://www.dbs.ifi.lmu.de/~zimek/publications/SDM2011/SDM11-outlier-preprint.pdf") +@Reference(authors = "H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title = "Interpreting and Unifying Outlier Scores", booktitle = "Proc. 11th SIAM International Conference on Data Mining (SDM), Mesa, AZ, 2011", url = "http://siam.omnibooksonline.com/2011datamining/data/papers/018.pdf") public class MinusLogGammaScaling extends OutlierGammaScaling { /** * Maximum value seen @@ -88,7 +88,7 @@ public class MinusLogGammaScaling extends OutlierGammaScaling { final double var = mv.getSampleVariance(); k = (mean * mean) / var; theta = var / mean; - atmean = MathUtil.regularizedGammaP(k, mean / theta); + atmean = GammaDistribution.regularizedGammaP(k, mean / theta); // logger.warning("Mean:"+mean+" Var:"+var+" Theta: "+theta+" k: "+k+" valatmean"+atmean); } diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogStandardDeviationScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogStandardDeviationScaling.java index 552de806..477fbdd2 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogStandardDeviationScaling.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogStandardDeviationScaling.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -26,6 +26,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier; import de.lmu.ifi.dbs.elki.database.ids.DBID; import de.lmu.ifi.dbs.elki.math.MathUtil; import de.lmu.ifi.dbs.elki.math.MeanVariance; +import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution; import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult; import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; @@ -40,7 +41,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; * * @author Erich Schubert */ -@Reference(authors="H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title="Interpreting and Unifying Outlier Scores", booktitle="Proc. 11th SIAM International Conference on Data Mining (SDM), Mesa, AZ, 2011", url="http://www.dbs.ifi.lmu.de/~zimek/publications/SDM2011/SDM11-outlier-preprint.pdf") +@Reference(authors="H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title="Interpreting and Unifying Outlier Scores", booktitle="Proc. 11th SIAM International Conference on Data Mining (SDM), Mesa, AZ, 2011", url="http://siam.omnibooksonline.com/2011datamining/data/papers/018.pdf") public class MinusLogStandardDeviationScaling extends StandardDeviationScaling { /** * Constructor. @@ -59,7 +60,7 @@ public class MinusLogStandardDeviationScaling extends StandardDeviationScaling { if(mlogv < mean || Double.isNaN(mlogv)) { return 0.0; } - return Math.max(0.0, MathUtil.erf((mlogv - mean) / factor)); + return Math.max(0.0, NormalDistribution.erf((mlogv - mean) / factor)); } @Override diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MixtureModelOutlierScalingFunction.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MixtureModelOutlierScalingFunction.java index 527429c5..26abb453 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MixtureModelOutlierScalingFunction.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MixtureModelOutlierScalingFunction.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MultiplicativeInverseScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MultiplicativeInverseScaling.java index 3e98f49e..9602b9b6 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MultiplicativeInverseScaling.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MultiplicativeInverseScaling.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -39,7 +39,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; * * @author Erich Schubert */ -@Reference(authors="H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title="Interpreting and Unifying Outlier Scores", booktitle="Proc. 11th SIAM International Conference on Data Mining (SDM), Mesa, AZ, 2011", url="http://www.dbs.ifi.lmu.de/~zimek/publications/SDM2011/SDM11-outlier-preprint.pdf") +@Reference(authors="H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title="Interpreting and Unifying Outlier Scores", booktitle="Proc. 11th SIAM International Conference on Data Mining (SDM), Mesa, AZ, 2011", url="http://siam.omnibooksonline.com/2011datamining/data/papers/018.pdf") public class MultiplicativeInverseScaling implements OutlierScalingFunction { /** * Constructor, adhering to diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierGammaScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierGammaScaling.java index 25864872..a3eecdb0 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierGammaScaling.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierGammaScaling.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,8 +24,8 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier; */ import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.math.MathUtil; import de.lmu.ifi.dbs.elki.math.MeanVariance; +import de.lmu.ifi.dbs.elki.math.statistics.distribution.GammaDistribution; import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult; import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta; import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; @@ -40,7 +40,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag; * * @author Erich Schubert */ -@Reference(authors = "H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title = "Interpreting and Unifying Outlier Scores", booktitle = "Proc. 11th SIAM International Conference on Data Mining (SDM), Mesa, AZ, 2011", url = "http://www.dbs.ifi.lmu.de/~zimek/publications/SDM2011/SDM11-outlier-preprint.pdf") +@Reference(authors = "H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title = "Interpreting and Unifying Outlier Scores", booktitle = "Proc. 11th SIAM International Conference on Data Mining (SDM), Mesa, AZ, 2011", url = "http://siam.omnibooksonline.com/2011datamining/data/papers/018.pdf") public class OutlierGammaScaling implements OutlierScalingFunction { /** * Normalization flag. @@ -93,7 +93,7 @@ public class OutlierGammaScaling implements OutlierScalingFunction { if(Double.isNaN(value) || Double.isInfinite(value)) { return 1.0; } - return Math.max(0, (MathUtil.regularizedGammaP(k, value / theta) - atmean) / (1 - atmean)); + return Math.max(0, (GammaDistribution.regularizedGammaP(k, value / theta) - atmean) / (1 - atmean)); } @Override @@ -111,7 +111,7 @@ public class OutlierGammaScaling implements OutlierScalingFunction { final double var = mv.getSampleVariance(); k = (mean * mean) / var; theta = var / mean; - atmean = MathUtil.regularizedGammaP(k, mean / theta); + atmean = GammaDistribution.regularizedGammaP(k, mean / theta); // logger.warning("Mean:"+mean+" Var:"+var+" Theta: "+theta+" k: "+k+" valatmean"+atmean); } diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierLinearScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierLinearScaling.java index 9d55048b..8f215ec3 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierLinearScaling.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierLinearScaling.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierMinusLogScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierMinusLogScaling.java index f1138cdf..0839f231 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierMinusLogScaling.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierMinusLogScaling.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -38,7 +38,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; * * @author Erich Schubert */ -@Reference(authors = "H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title = "Interpreting and Unifying Outlier Scores", booktitle = "Proc. 11th SIAM International Conference on Data Mining (SDM), Mesa, AZ, 2011", url = "http://www.dbs.ifi.lmu.de/~zimek/publications/SDM2011/SDM11-outlier-preprint.pdf") +@Reference(authors = "H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title = "Interpreting and Unifying Outlier Scores", booktitle = "Proc. 11th SIAM International Conference on Data Mining (SDM), Mesa, AZ, 2011", url = "http://siam.omnibooksonline.com/2011datamining/data/papers/018.pdf") public class OutlierMinusLogScaling implements OutlierScalingFunction { /** * Maximum value seen, set by {@link #prepare} diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierScalingFunction.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierScalingFunction.java index 2aa821fe..ac774745 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierScalingFunction.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierScalingFunction.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierSqrtScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierSqrtScaling.java index 8ccdc8dd..d39fed97 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierSqrtScaling.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierSqrtScaling.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/RankingPseudoOutlierScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/RankingPseudoOutlierScaling.java index d6ef7f5f..47eda6aa 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/RankingPseudoOutlierScaling.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/RankingPseudoOutlierScaling.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SigmoidOutlierScalingFunction.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SigmoidOutlierScalingFunction.java index 7363f4f9..31e78ec8 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SigmoidOutlierScalingFunction.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SigmoidOutlierScalingFunction.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SqrtStandardDeviationScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SqrtStandardDeviationScaling.java index 2c733332..24f9e855 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SqrtStandardDeviationScaling.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SqrtStandardDeviationScaling.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -27,6 +27,7 @@ import de.lmu.ifi.dbs.elki.database.ids.DBID; import de.lmu.ifi.dbs.elki.math.DoubleMinMax; import de.lmu.ifi.dbs.elki.math.MathUtil; import de.lmu.ifi.dbs.elki.math.MeanVariance; +import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution; import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult; import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; @@ -48,7 +49,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter; * * @author Erich Schubert */ -@Reference(authors = "H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title = "Interpreting and Unifying Outlier Scores", booktitle = "Proc. 11th SIAM International Conference on Data Mining (SDM), Mesa, AZ, 2011", url = "http://www.dbs.ifi.lmu.de/~zimek/publications/SDM2011/SDM11-outlier-preprint.pdf") +@Reference(authors = "H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title = "Interpreting and Unifying Outlier Scores", booktitle = "Proc. 11th SIAM International Conference on Data Mining (SDM), Mesa, AZ, 2011", url = "http://siam.omnibooksonline.com/2011datamining/data/papers/018.pdf") public class SqrtStandardDeviationScaling implements OutlierScalingFunction { /** * Parameter to specify the fixed minimum to use. @@ -118,7 +119,7 @@ public class SqrtStandardDeviationScaling implements OutlierScalingFunction { if(value <= mean) { return 0; } - return Math.max(0, MathUtil.erf((value - mean) / factor)); + return Math.max(0, NormalDistribution.erf((value - mean) / factor)); } @Override diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/StandardDeviationScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/StandardDeviationScaling.java index 10db8e56..6ef5c006 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/StandardDeviationScaling.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/StandardDeviationScaling.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -26,6 +26,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier; import de.lmu.ifi.dbs.elki.database.ids.DBID; import de.lmu.ifi.dbs.elki.math.MathUtil; import de.lmu.ifi.dbs.elki.math.MeanVariance; +import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution; import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult; import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; @@ -44,7 +45,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter; * * @author Erich Schubert */ -@Reference(authors="H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title="Interpreting and Unifying Outlier Scores", booktitle="Proc. 11th SIAM International Conference on Data Mining (SDM), Mesa, AZ, 2011", url="http://www.dbs.ifi.lmu.de/~zimek/publications/SDM2011/SDM11-outlier-preprint.pdf") +@Reference(authors="H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title="Interpreting and Unifying Outlier Scores", booktitle="Proc. 11th SIAM International Conference on Data Mining (SDM), Mesa, AZ, 2011", url="http://siam.omnibooksonline.com/2011datamining/data/papers/018.pdf") public class StandardDeviationScaling implements OutlierScalingFunction { /** * Parameter to specify a fixed mean to use. @@ -107,7 +108,7 @@ public class StandardDeviationScaling implements OutlierScalingFunction { if(value <= mean) { return 0; } - return Math.max(0, MathUtil.erf((value - mean) / factor)); + return Math.max(0, NormalDistribution.erf((value - mean) / factor)); } @Override diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/TopKOutlierScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/TopKOutlierScaling.java index 5d32dfb5..8044fce9 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/TopKOutlierScaling.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/TopKOutlierScaling.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/package-info.java index 3015661c..c2adba6b 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 +Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/package-info.java index 4f781fc3..430f1bf7 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 +Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/xml/DOMCloner.java b/src/de/lmu/ifi/dbs/elki/utilities/xml/DOMCloner.java new file mode 100644 index 00000000..dc3b48a8 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/xml/DOMCloner.java @@ -0,0 +1,108 @@ +package de.lmu.ifi.dbs.elki.utilities.xml; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +import org.w3c.dom.Attr; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; + +/** + * Class for cloning XML document, with filter capabilites + * + * @author Erich Schubert + */ +public class DOMCloner { + /** + * Deep-clone a document. + * + * @param domImpl DOM implementation to use + * @param document Original document + * @return Cloned document + */ + public Document cloneDocument(DOMImplementation domImpl, Document document) { + Element root = document.getDocumentElement(); + // New document + Document result = domImpl.createDocument(root.getNamespaceURI(), root.getNodeName(), null); + Element rroot = result.getDocumentElement(); + // Cloning the document element is a bit tricky. + // This is adopted from DomUtilities#deepCloneDocument + boolean before = true; + for(Node n = document.getFirstChild(); n != null; n = n.getNextSibling()) { + if(n == root) { + before = false; + copyAttributes(result, root, rroot); + for(Node c = root.getFirstChild(); c != null; c = c.getNextSibling()) { + final Node cl = cloneNode(result, c); + if(cl != null) { + rroot.appendChild(cl); + } + } + } + else { + if(n.getNodeType() != Node.DOCUMENT_TYPE_NODE) { + final Node cl = cloneNode(result, n); + if(cl != null) { + if(before) { + result.insertBefore(cl, rroot); + } + else { + result.appendChild(cl); + } + } + } + } + } + return result; + } + + /** + * Clone an existing node. + * + * @param doc Document + * @param eold Existing node + * @return Cloned node + */ + public Node cloneNode(Document doc, Node eold) { + return doc.importNode(eold, true); + } + + /** + * Copy the attributes from an existing node to a new node. + * + * @param doc Target document + * @param eold Existing node + * @param enew Target node + */ + public void copyAttributes(Document doc, Element eold, Element enew) { + if(eold.hasAttributes()) { + NamedNodeMap attr = eold.getAttributes(); + int len = attr.getLength(); + for(int i = 0; i < len; i++) { + enew.setAttributeNode((Attr) doc.importNode(attr.item(i), true)); + } + } + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/xml/HTMLUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/xml/HTMLUtil.java index 8ad2ae27..7e433525 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/xml/HTMLUtil.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/xml/HTMLUtil.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.xml; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/xml/XMLNodeIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/xml/XMLNodeIterator.java index 320f7478..e0602790 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/xml/XMLNodeIterator.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/xml/XMLNodeIterator.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.xml; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/xml/XMLNodeListIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/xml/XMLNodeListIterator.java index 762e9fe6..8157d4ba 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/xml/XMLNodeListIterator.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/xml/XMLNodeListIterator.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.xml; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/utilities/xml/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/xml/package-info.java index 45d800b5..9b961687 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/xml/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/xml/package-info.java @@ -6,7 +6,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 +Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team |