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 }