001 package org.maltparser.ml.lib;
002
003 import java.io.Serializable;
004
005
006 import org.maltparser.core.helper.HashMap;
007
008 /**
009 * The purpose of the feature map is to map MaltParser's column based features together with the symbol code from the symbol table to
010 * unique indices suitable for liblinear and libsvm. A feature column position are combined together with the symbol code in a
011 * 64-bit key (Long), where 16 bits are reserved for the position and 48 bits are reserved for the symbol code.
012 *
013 * @author Johan Hall
014 *
015 */
016 public class FeatureMap implements Serializable {
017 private static final long serialVersionUID = 7526471155622776147L;
018 private final HashMap<Long,Integer> map;
019 private int featureCounter;
020
021 /**
022 * Creates a feature map and sets the feature counter to 1
023 */
024 public FeatureMap() {
025 map = new HashMap<Long, Integer>();
026 this.featureCounter = 1;
027 }
028
029 /**
030 * Adds a mapping from a combination of the position in the column-based feature vector and the symbol code to
031 * an index value suitable for liblinear and libsvm.
032 *
033 * @param featurePosition a position in the column-based feature vector
034 * @param code a symbol code
035 * @return the index value
036 */
037 public int addIndex(int featurePosition, int code) {
038 final long key = ((((long)featurePosition) << 48) | (long)code);
039 Integer index = map.get(key);
040 if (index == null) {
041 index = featureCounter++;
042 map.put(key, index);
043 }
044 return index.intValue();
045 }
046
047 /**
048 * Return
049 *
050 * @param featurePosition the position in the column-based feature vector
051 * @param code the symbol code suitable for liblinear and libsvm
052 * @return the index value if it exists, otherwise -1
053 */
054 public int getIndex(int featurePosition, int code) {
055 final long key = ((((long)featurePosition) << 48) | (long)code);
056 final Integer index = map.get(key);
057 return (index == null)?-1:index;
058 }
059
060
061 public int addIndex(int featurePosition, int code1, int code2) {
062 final long key = ((((long)featurePosition) << 48) | (((long)code1) << 24) | (long)code2);
063 Integer index = map.get(key);
064 if (index == null) {
065 index = featureCounter++;
066 map.put(key, index);
067 }
068 return index.intValue();
069 }
070
071 public int setIndex(long key, int index) {
072 return map.put(key, index);
073 }
074
075 public int decrementIndex(Long key) {
076 Integer index = map.get(key);
077 if (index != null) {
078 map.put(key, index - 1);
079 }
080 return (index != null)?index - 1 : -1;
081 }
082
083 public void decrementfeatureCounter() {
084 featureCounter--;
085 }
086
087 public Integer removeIndex(long key) {
088 return map.remove(key);
089 }
090
091 public int getIndex(int featurePosition, int code1, int code2) {
092 final long key = ((((long)featurePosition) << 48) | (((long)code1) << 24) | (long)code2);
093 final Integer index = map.get(key);
094 return (index == null)?-1:index;
095 }
096
097 /**
098 * @return the size of the map
099 */
100 public int size() {
101 return map.size();
102 }
103
104
105 public Long[] reverseMap() {
106 Long[] reverseMap = new Long[map.size() +1];
107
108 for (Long key : map.keySet()) {
109 reverseMap[map.get(key)] = key;
110
111 }
112 return reverseMap;
113 }
114
115
116
117 public void setFeatureCounter(int featureCounter) {
118 this.featureCounter = featureCounter;
119 }
120
121 /**
122 * @return the current value of the feature counter.
123 */
124 public int getFeatureCounter() {
125 return featureCounter;
126 }
127 }