001package org.maltparser.ml.lib; 002 003import java.io.Serializable; 004 005 006import 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 */ 016public 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 Integer index = map.get(((((long)featurePosition) << 48) | (long)code)); 056 return (index == null)?-1:index; 057 } 058 059 060 public int addIndex(int featurePosition, int code1, int code2) { 061 final long key = ((((long)featurePosition) << 48) | (((long)code1) << 24) | (long)code2); 062 Integer index = map.get(key); 063 if (index == null) { 064 index = featureCounter++; 065 map.put(key, index); 066 } 067 return index.intValue(); 068 } 069 070 public int setIndex(long key, int index) { 071 return map.put(key, index); 072 } 073 074 public int decrementIndex(Long key) { 075 Integer index = map.get(key); 076 if (index != null) { 077 map.put(key, index - 1); 078 } 079 return (index != null)?index - 1 : -1; 080 } 081 082 public void decrementfeatureCounter() { 083 featureCounter--; 084 } 085 086 public Integer removeIndex(long key) { 087 return map.remove(key); 088 } 089 090 public int getIndex(int featurePosition, int code1, int code2) { 091 final Integer index = map.get(((((long)featurePosition) << 48) | (((long)code1) << 24) | (long)code2)); 092 return (index == null)?-1:index; 093 } 094 095 /** 096 * @return the size of the map 097 */ 098 public int size() { 099 return map.size(); 100 } 101 102 103 public Long[] reverseMap() { 104 Long[] reverseMap = new Long[map.size() +1]; 105 106 for (Long key : map.keySet()) { 107 reverseMap[map.get(key)] = key; 108 } 109 return reverseMap; 110 } 111 112 113 114 public void setFeatureCounter(int featureCounter) { 115 this.featureCounter = featureCounter; 116 } 117 118 /** 119 * @return the current value of the feature counter. 120 */ 121 public int getFeatureCounter() { 122 return featureCounter; 123 } 124}