1 /* 2 * This file is part of ELKI: 3 * Environment for Developing KDD-Applications Supported by Index-Structures 4 * 5 * Copyright (C) 2018 6 * ELKI Development Team 7 * 8 * This program is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Affero General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Affero General Public License for more details. 17 * 18 * You should have received a copy of the GNU Affero General Public License 19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 20 */ 21 package de.lmu.ifi.dbs.elki.data.type; 22 23 import de.lmu.ifi.dbs.elki.data.FeatureVector; 24 import de.lmu.ifi.dbs.elki.utilities.io.ByteBufferSerializer; 25 26 /** 27 * Construct a type information for vector spaces with variable dimensionality. 28 * 29 * @author Erich Schubert 30 * @since 0.4.0 31 * 32 * @has - - - FeatureVector 33 * 34 * @param <V> Vector type 35 */ 36 public class VectorTypeInformation<V extends FeatureVector<?>> extends SimpleTypeInformation<V> { 37 /** 38 * Object factory for producing new instances. 39 */ 40 private final FeatureVector.Factory<V, ?> factory; 41 42 /** 43 * Constructor for a type request without dimensionality constraints. 44 * 45 * @param cls Class constraint 46 * @param <V> vector type 47 */ typeRequest(Class<? super V> cls)48 public static <V extends FeatureVector<?>> VectorTypeInformation<V> typeRequest(Class<? super V> cls) { 49 return new VectorTypeInformation<>(cls, -1, Integer.MAX_VALUE); 50 } 51 52 /** 53 * Constructor for a type request with dimensionality constraints. 54 * 55 * @param cls Class constraint 56 * @param mindim Minimum dimensionality 57 * @param maxdim Maximum dimensionality 58 * @param <V> vector type 59 */ typeRequest(Class<? super V> cls, int mindim, int maxdim)60 public static <V extends FeatureVector<?>> VectorTypeInformation<V> typeRequest(Class<? super V> cls, int mindim, int maxdim) { 61 return new VectorTypeInformation<>(cls, mindim, maxdim); 62 } 63 64 /** 65 * Minimum dimensionality. 66 */ 67 protected final int mindim; 68 69 /** 70 * Maximum dimensionality. 71 */ 72 protected final int maxdim; 73 74 /** 75 * Constructor for a type request. 76 * 77 * @param cls base class 78 * @param mindim Minimum dimensionality 79 * @param maxdim Maximum dimensionality 80 */ VectorTypeInformation(Class<? super V> cls, int mindim, int maxdim)81 public VectorTypeInformation(Class<? super V> cls, int mindim, int maxdim) { 82 super(cls); 83 this.factory = null; 84 assert (mindim <= maxdim); 85 this.mindim = mindim; 86 this.maxdim = maxdim; 87 } 88 89 /** 90 * Constructor for an actual type. 91 * 92 * @param factory Vector factory 93 * @param serializer Serializer 94 * @param mindim Minimum dimensionality 95 * @param maxdim Maximum dimensionality 96 */ VectorTypeInformation(FeatureVector.Factory<V, ?> factory, ByteBufferSerializer<? super V> serializer, int mindim, int maxdim)97 public VectorTypeInformation(FeatureVector.Factory<V, ?> factory, ByteBufferSerializer<? super V> serializer, int mindim, int maxdim) { 98 super(factory.getRestrictionClass(), serializer); 99 this.factory = factory; 100 assert (mindim <= maxdim); 101 this.mindim = mindim; 102 this.maxdim = maxdim; 103 } 104 105 @Override isAssignableFromType(TypeInformation type)106 public boolean isAssignableFromType(TypeInformation type) { 107 // This validates the base type V 108 // Other type must also be a vector type 109 if(!super.isAssignableFromType(type) || !(type instanceof VectorTypeInformation)) { 110 return false; 111 } 112 VectorTypeInformation<?> othertype = (VectorTypeInformation<?>) type; 113 assert (othertype.mindim <= othertype.maxdim); 114 // the other must not have a lower minimum dimensionality 115 if(this.mindim > othertype.mindim) { 116 return false; 117 } 118 // ... or a higher maximum dimensionality. 119 return othertype.maxdim <= this.maxdim; 120 } 121 122 @Override isAssignableFrom(Object other)123 public boolean isAssignableFrom(Object other) { 124 // Validate that we can assign 125 if(!super.isAssignableFrom(other)) { 126 return false; 127 } 128 // Get the object dimensionality 129 final int odim = cast(other).getDimensionality(); 130 return odim >= mindim && odim <= maxdim; 131 } 132 133 /** 134 * Get the object type factory. 135 * 136 * @return the factory 137 */ getFactory()138 public FeatureVector.Factory<V, ?> getFactory() { 139 if(factory == null) { 140 throw new UnsupportedOperationException("Requesting factory for a type request!"); 141 } 142 return factory; 143 } 144 145 /** 146 * Get the minimum dimensionality of the occurring vectors. 147 * 148 * @return dimensionality 149 */ mindim()150 public int mindim() { 151 if(mindim < 0) { 152 throw new UnsupportedOperationException("Requesting dimensionality for a request without defined dimensionality!"); 153 } 154 return mindim; 155 } 156 157 /** 158 * Get the maximum dimensionality of the occurring vectors. 159 * 160 * @return dimensionality 161 */ maxdim()162 public int maxdim() { 163 if(maxdim == Integer.MAX_VALUE) { 164 throw new UnsupportedOperationException("Requesting dimensionality for a request without defined dimensionality!"); 165 } 166 return maxdim; 167 } 168 169 /** 170 * Get the multiplicity of the vector. 171 * 172 * @return Multiplicity {@code 1} (except for subclasses) 173 */ getMultiplicity()174 public int getMultiplicity() { 175 return 1; 176 } 177 178 @Override toString()179 public String toString() { 180 StringBuilder buf = new StringBuilder(1000).append(super.toString()).append(",variable"); 181 if(mindim >= 0) { 182 buf.append(",mindim=").append(mindim); 183 } 184 if(maxdim < Integer.MAX_VALUE) { 185 buf.append(",maxdim=").append(maxdim); 186 } 187 return buf.toString(); 188 } 189 } 190