    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    }