/* * Copyright 2004-2010 Information & Software Engineering Group (188/1) * Institute of Software Technology and Interactive Systems * Vienna University of Technology, Austria * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.ifs.tuwien.ac.at/dm/somtoolbox/license.html * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package at.tuwien.ifs.somtoolbox.layers; import java.io.Serializable; import java.math.BigDecimal; /** * A simple class representing a unit label. This class holds the name, the value and the quantization error of a label. * It also provides static methods for sorting an array of labels according to on of the three properties mentioned * before. * * @author Michael Dittenbach * @version $Id: Label.java 3587 2010-05-21 10:35:33Z mayer $ */ public class Label implements Serializable { private static final long serialVersionUID = 1L; public static final int SORT_ASC = 0; private static final int SORT_BYMEAN = 1; private static final int SORT_BYNAME = 2; private static final int SORT_BYQE = 0; public static final int SORT_DESC = 1; /** * Internal method for the quick sort algorithm. * * @param a an array of labels to be sorted. * @param type the sorting criterion ({@link #SORT_BYMEAN}, {@link #SORT_BYNAME} or {@link #SORT_BYQE}). * @param order the order of sorting, either ascending ({@link #SORT_ASC}) or descending ({@link #SORT_DESC}). */ private static void qsort(Label a[], int type, int order) { // type=0 -> qe, type=1 -> value, type=2 -> name qsort(a, 0, a.length - 1, type); if (order == SORT_DESC) { reverse(a); } } /** * Internal method for the quick sort algorithm. * * @param a an array of labels to be sorted. * @param lo0 the lower boundary. * @param hi0 the upper boundary. * @param type the sorting criterion ({@link #SORT_BYMEAN}, {@link #SORT_BYNAME} or {@link #SORT_BYQE}). */ private static void qsort(Label a[], int lo0, int hi0, int type) { int lo = lo0; int hi = hi0; Label mid; if (hi0 > lo0) { mid = a[(lo0 + hi0) / 2]; while (lo <= hi) { if (type == 0) { while (lo < hi0 && a[lo].getQe() < mid.getQe()) { ++lo; } while (hi > lo0 && a[hi].getQe() > mid.getQe()) { --hi; } } else if (type == 1) { while (lo < hi0 && a[lo].getValue() < mid.getValue()) { ++lo; } while (hi > lo0 && a[hi].getValue() > mid.getValue()) { --hi; } } else if (type == 2) { while (lo < hi0 && a[lo].getName().compareTo(mid.getName()) < 0) { ++lo; } while (hi > lo0 && a[hi].getName().compareTo(mid.getName()) > 0) { --hi; } } if (lo <= hi) { swap(a, lo, hi); ++lo; --hi; } } if (lo0 < hi) { qsort(a, lo0, hi, type); } if (lo < hi0) { qsort(a, lo, hi0, type); } } } /** * Convenience method for the reversal of an array of labels. * * @param a the array of labels to be reversed. */ private static void reverse(Label a[]) { reverse(a, 0, a.length - 1); } /** * Internal method for reversal of a part of an array of labels. * * @param a the array of labels to be reversed. * @param start the lower boundary. * @param end the upper boundary. */ private static void reverse(Label a[], int start, int end) { if (end - start > 1) { Label t = null; for (int r = start; r < (end - start) / 2; r++) { t = a[end - start - r]; a[end - start - r] = a[r]; a[r] = t; } } } /** * Convenience method for sorting an array of labels by their values. * * @param labels an array of labels to be sorted. * @param order the sorting order, either ascending ({@link #SORT_ASC}) or descending ({@link #SORT_DESC}). */ public static void sortByValue(Label[] labels, int order) { qsort(labels, SORT_BYMEAN, order); } /** * Convenience method for sorting an array of labels by their values and quantization errors (in case of equal * value). The sorting order is specified separately for both criteria by arguments <code>order1</code> and * <code>order2</code>. * * @param labels an array of labels to be sorted. * @param order1 the sorting order for the primary criterion, either ascending ({@link #SORT_ASC}) or descending ( * {@link #SORT_DESC}). * @param order2 the sorting order for the secondary criterion, either ascending ({@link #SORT_ASC}) or descending ( * {@link #SORT_DESC}). */ public static void sortByValueQe(Label[] labels, int order1, int order2) { sortByValue(labels, order1); int i1 = 0; int i2 = 0; while (i1 < labels.length) { double val = labels[i1].getValue(); while (i2 < labels.length && labels[i2].getValue() == val) { i2++; } qsort(labels, i1, (i2 - 1), SORT_BYQE); if (order2 == SORT_DESC) { reverse(labels, i1, (i2 - 1)); } i1 = i2; } } /** * Convenience method for sorting an array of labels by their names. * * @param labels an array of labels to be sorted. * @param order the sorting order, either ascending ({@link #SORT_ASC}) or descending ({@link #SORT_DESC}). */ public static void sortByName(Label[] labels, int order) { qsort(labels, SORT_BYNAME, order); } /** * Convenience method for sorting an array of labels by their quantization errors. * * @param labels an array of labels to be sorted. * @param order the sorting order, either ascending ({@link #SORT_ASC}) or descending ({@link #SORT_DESC}). */ public static void sortByQe(Label[] labels, int order) { qsort(labels, SORT_BYQE, order); } /** * Convenience method for sorting an array of labels by their quantization errors and values (in case of equal * quantization errors). The sorting order is determined separately for both criteria by arguments * <code>order1</code> and <code>order2</code>. * * @param labels an array of labels to be sorted. * @param order1 the sorting order for the primary criterion, either ascending ({@link #SORT_ASC}) or descending ( * {@link #SORT_DESC}). * @param order2 the sorting order for the secondary criterion, either ascending ({@link #SORT_ASC}) or descending ( * {@link #SORT_DESC}). */ public static void sortByQeValue(Label[] labels, int order1, int order2) { sortByQe(labels, order1); int i1 = 0; int i2 = 0; while (i1 < labels.length) { double val = labels[i1].getQe(); while (i2 < labels.length && labels[i2].getQe() == val) { i2++; } qsort(labels, i1, (i2 - 1), SORT_BYMEAN); if (order2 == SORT_DESC) { reverse(labels, i1, (i2 - 1)); } i1 = i2; } } /** * Internal method for the quick sort algorithm for swapping two elements (labels) of an array. * * @param a an array of labels. * @param i index of first element to be swapped with second. * @param j index of second element to be swapped with first. */ private static void swap(Label a[], int i, int j) { Label T; T = a[i]; a[i] = a[j]; a[j] = T; } private String name; private double qe; private double value; private String bestContext; /** * Constructs a label object with the given arguments. * * @param name the name of the label. * @param value the label value. * @param qe the quantization error of the label. */ public Label(String name, double value, double qe) { this.name = name; this.value = value; this.qe = qe; } public Label(String name, double value) { this.name = name; this.value = value; } public Label(String name) { this.name = name; } public Label(String name, String BestContext) { this.name = name; this.bestContext = BestContext; } /** * Returns the name of the label. * * @return the name of the label. */ public String getName() { return name; } /** * Returns the quantization error of this label. * * @return the quantization error of this label. */ public double getQe() { return qe; } public String getBestContext() { return bestContext; } /** * Returns the value of this label. * * @return the value of this label. */ public double getValue() { return value; } public String getNameAndScaledValue(int scale) { double formattedValue = new BigDecimal(getValue()).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue(); return getName() + "[" + formattedValue + "]"; } }