saberian | 7b5b77b | 2012-06-04 11:19:43 -0700 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright (C) 2012 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package android.bordeaux.services; |
| 18 | |
| 19 | import android.os.IBinder; |
| 20 | import android.util.Log; |
| 21 | import java.util.HashMap; |
| 22 | import java.util.ArrayList; |
| 23 | import java.util.Map; |
| 24 | import java.util.HashSet; |
| 25 | import java.util.Iterator; |
| 26 | import java.io.Serializable; |
| 27 | import java.io.*; |
| 28 | import java.lang.Boolean; |
| 29 | import android.bordeaux.services.FeatureAssembly; |
| 30 | import android.bordeaux.learning.predictorHist; |
| 31 | |
| 32 | /** |
| 33 | * This is interface to implement Prediction based on histogram that |
| 34 | * uses predictor_histogram from learnerning section |
| 35 | */ |
| 36 | public class Predictor extends IPredictor.Stub |
| 37 | implements IBordeauxLearner { |
| 38 | private ModelChangeCallback modelChangeCallback = null; |
| 39 | private final String TAG = "Predictor"; |
| 40 | private final String SET_EXPIRE_TIME = "SetExpireTime"; |
| 41 | private final String USE_HISTORY = "Use History"; |
| 42 | private final String SET_FEATURE = "Set Feature"; |
| 43 | private long mExpireTime = 3 * 60; |
| 44 | private long mLastSampleTime = 0; |
| 45 | private boolean mUseHistoryFlag = false; |
| 46 | private final String NEW_START = "New Start"; |
| 47 | |
| 48 | static public class Model implements Serializable { |
| 49 | public HashMap<String, Integer> countHistogram = new HashMap<String, Integer>(); |
| 50 | public HashSet<String> usedFeatures = new HashSet<String>(); |
| 51 | public int sampleCounts; |
| 52 | public boolean useHistoryFlag; |
| 53 | public long expireTime; |
| 54 | public long lastSampleTime; |
| 55 | } |
| 56 | |
| 57 | private predictorHist mPredictorHist = new predictorHist(); |
| 58 | private String mLastSample = NEW_START; |
| 59 | public FeatureAssembly mFeatureAssembly = new FeatureAssembly(); |
| 60 | |
| 61 | /** |
| 62 | * Reset the Predictor |
| 63 | */ |
| 64 | public void ResetPredictor(){ |
| 65 | printModel(getPredictionModel()); |
| 66 | mPredictorHist.ResetPredictorHist(); |
| 67 | mUseHistoryFlag = false; |
| 68 | mLastSampleTime = 0; |
| 69 | mLastSample = NEW_START; |
| 70 | mFeatureAssembly = new FeatureAssembly(); |
| 71 | printModel(getPredictionModel()); |
| 72 | if (modelChangeCallback != null) { |
| 73 | modelChangeCallback.modelChanged(this); |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | /** |
| 78 | * Augment input string with buildin features such as time, location |
| 79 | */ |
| 80 | private String buildDataPoint(String sampleName) { |
| 81 | String fs = mFeatureAssembly.augmentFeatureInputString(sampleName); |
| 82 | if (mUseHistoryFlag) { |
| 83 | if (((System.currentTimeMillis()- mLastSampleTime)/1000) > mExpireTime) { |
| 84 | mLastSample = NEW_START; |
| 85 | } |
| 86 | fs = fs + "+" + mLastSample; |
| 87 | } |
| 88 | return fs; |
| 89 | } |
| 90 | |
| 91 | /** |
| 92 | * Input is a sampleName e.g.action name. This input is then augmented with requested build-in |
| 93 | * features such as time and location to create sampleFeatures. The sampleFeatures is then |
| 94 | * pushed to the histogram |
| 95 | */ |
| 96 | public void pushNewSample(String sampleName) { |
| 97 | String sampleFeatures = buildDataPoint(sampleName); |
| 98 | mLastSample = sampleName; |
| 99 | mLastSampleTime = System.currentTimeMillis(); |
| 100 | mPredictorHist.pushSample(sampleFeatures); |
| 101 | if (modelChangeCallback != null) { |
| 102 | modelChangeCallback.modelChanged(this); |
| 103 | } |
| 104 | //printModel(getPredictionModel()); |
| 105 | } |
| 106 | |
| 107 | /** |
| 108 | * return probabilty of an exmple using the histogram |
| 109 | */ |
| 110 | public float getSampleProbability(String sampleName) { |
| 111 | String sampleFeatures = buildDataPoint(sampleName); |
| 112 | return mPredictorHist.getProbability(sampleFeatures); |
| 113 | } |
| 114 | |
| 115 | /** |
| 116 | * Set parameters for 1) using History in probability estimations e.g. consider the last event |
| 117 | * and 2) featureAssembly e.g. time and location. |
| 118 | */ |
| 119 | public boolean setPredictorParameter(String s, String f) { |
| 120 | boolean res = false; |
| 121 | if (s.equals(USE_HISTORY)) { |
| 122 | if (f.equals("true")){ |
| 123 | mUseHistoryFlag = true; |
| 124 | res = true; |
| 125 | } |
| 126 | else if (f.equals("false")) { |
| 127 | mUseHistoryFlag = false; |
| 128 | res = true; |
| 129 | } |
| 130 | } else if (s.equals(SET_EXPIRE_TIME)) { |
| 131 | mExpireTime = Long.valueOf(f); |
| 132 | res = true; |
| 133 | } else if (s.equals(SET_FEATURE)) { |
| 134 | res = mFeatureAssembly.registerFeature(f); |
| 135 | } |
| 136 | if (!res) |
| 137 | Log.e(TAG,"Setting parameter " + s + " with " + f + " is not valid"); |
| 138 | return res; |
| 139 | } |
| 140 | |
| 141 | public Model getPredictionModel() { |
| 142 | Model m = new Model(); |
| 143 | m.countHistogram.putAll(mPredictorHist.getHist()); |
| 144 | m.sampleCounts = mPredictorHist.getHistCounts(); |
| 145 | m.expireTime = mExpireTime; |
| 146 | m.usedFeatures = (HashSet) mFeatureAssembly.getUsedFeatures(); |
| 147 | m.useHistoryFlag = mUseHistoryFlag; |
| 148 | m.lastSampleTime = mLastSampleTime; |
| 149 | return m; |
| 150 | } |
| 151 | |
| 152 | public boolean loadModel(Model m) { |
| 153 | //Log.i(TAG,"on loadModel"); |
| 154 | //printModel(m); |
| 155 | mPredictorHist = new predictorHist(); |
| 156 | mPredictorHist.set(m.countHistogram); |
| 157 | mExpireTime = m.expireTime; |
| 158 | mUseHistoryFlag = m.useHistoryFlag; |
| 159 | mLastSampleTime = m.lastSampleTime; |
| 160 | mFeatureAssembly = new FeatureAssembly(); |
| 161 | boolean res = false; |
| 162 | Iterator itr = m.usedFeatures.iterator(); |
| 163 | while(itr.hasNext()) { |
| 164 | res = res & mFeatureAssembly.registerFeature((String) itr.next()); |
| 165 | } |
| 166 | return res; |
| 167 | } |
| 168 | |
| 169 | public void printModel(Model m) { |
| 170 | Log.i(TAG,"histogram is : " + m.countHistogram.toString()); |
| 171 | Log.i(TAG,"number of counts in histogram is : " + m.sampleCounts); |
| 172 | Log.i(TAG,"ExpireTime time is : " + m.expireTime); |
| 173 | Log.i(TAG,"useHistoryFlag is : " + m.useHistoryFlag); |
| 174 | Log.i(TAG,"used features are : " + m.usedFeatures.toString()); |
| 175 | } |
| 176 | |
| 177 | // Beginning of the IBordeauxLearner Interface implementation |
| 178 | public byte [] getModel() { |
| 179 | Model model = getPredictionModel(); |
| 180 | //Log.i(TAG,"on getModel"); |
| 181 | printModel(model); |
| 182 | try { |
| 183 | ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); |
| 184 | ObjectOutputStream objStream = new ObjectOutputStream(byteStream); |
| 185 | objStream.writeObject(model); |
| 186 | byte[] bytes = byteStream.toByteArray(); |
| 187 | //Log.i(TAG, "getModel: " + bytes); |
| 188 | return bytes; |
| 189 | } catch (IOException e) { |
| 190 | throw new RuntimeException("Can't get model"); |
| 191 | } |
| 192 | } |
| 193 | |
| 194 | public boolean setModel(final byte [] modelData) { |
| 195 | //Log.i(TAG,"on setModel"); |
| 196 | try { |
| 197 | ByteArrayInputStream input = new ByteArrayInputStream(modelData); |
| 198 | ObjectInputStream objStream = new ObjectInputStream(input); |
| 199 | Model model = (Model) objStream.readObject(); |
| 200 | boolean res = loadModel(model); |
| 201 | //Log.i(TAG, "LoadModel: " + modelData); |
| 202 | return res; |
| 203 | } catch (IOException e) { |
| 204 | throw new RuntimeException("Can't load model"); |
| 205 | } catch (ClassNotFoundException e) { |
| 206 | throw new RuntimeException("Learning class not found"); |
| 207 | } |
| 208 | } |
| 209 | |
| 210 | public IBinder getBinder() { |
| 211 | return this; |
| 212 | } |
| 213 | |
| 214 | public void setModelChangeCallback(ModelChangeCallback callback) { |
| 215 | modelChangeCallback = callback; |
| 216 | } |
| 217 | // End of IBordeauxLearner Interface implemenation |
| 218 | } |