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