From e40bdc75c869050a62c36532606d8a1bc6fd2b7b Mon Sep 17 00:00:00 2001 From: Jean-Luc Brouillet Date: Fri, 28 Apr 2017 16:26:19 -0700 Subject: Remove unused project named "bordeaux". The code has not been touched since 2012 and is not referred anywhere else. It was for on-device machine learning. whua@, who worked on it, say it's fine to remove. Test: mj checkbuild. Got no errors. Change-Id: Ic8d94379cb92c2b229546af6d98c08007f7a0f37 --- Android.mk | 18 - bordeaux/Android.mk | 18 - bordeaux/learning/Android.mk | 50 --- bordeaux/learning/multiclass_pa/Android.mk | 33 -- .../android/bordeaux/learning/MulticlassPA.java | 68 --- .../multiclass_pa/jni/jni_multiclass_pa.cpp | 116 ------ .../learning/multiclass_pa/jni/jni_multiclass_pa.h | 59 --- .../multiclass_pa/native/multiclass_pa.cpp | 250 ----------- .../learning/multiclass_pa/native/multiclass_pa.h | 117 ------ bordeaux/learning/multiclass_pa/native/util.cpp | 52 --- bordeaux/learning/multiclass_pa/native/util.h | 33 -- bordeaux/learning/predictor_histogram/Android.mk | 16 - .../bordeaux/learning/HistogramPredictor.java | 384 ----------------- .../learning/stochastic_linear_ranker/Android.mk | 34 -- .../bordeaux/learning/StochasticLinearRanker.java | 193 --------- .../jni/jni_stochastic_linear_ranker.cpp | 461 --------------------- .../jni/jni_stochastic_linear_ranker.h | 182 -------- .../stochastic_linear_ranker/native/common_defs.h | 46 -- .../native/learning_rate_controller-inl.h | 127 ------ .../native/sparse_weight_vector.cpp | 398 ------------------ .../native/sparse_weight_vector.h | 204 --------- .../native/stochastic_linear_ranker.cpp | 139 ------- .../native/stochastic_linear_ranker.h | 244 ----------- bordeaux/service/Android.mk | 79 ---- bordeaux/service/AndroidManifest.xml | 23 - bordeaux/service/res/drawable-hdpi/ic_bordeaux.png | Bin 3774 -> 0 bytes bordeaux/service/res/drawable-mdpi/ic_bordeaux.png | Bin 2911 -> 0 bytes .../service/res/drawable-xhdpi/ic_bordeaux.png | Bin 3904 -> 0 bytes .../res/layout/lava_messenger_service_binding.xml | 69 --- .../service/res/layout/lava_service_binding.xml | 59 --- .../service/res/layout/lava_service_controller.xml | 42 -- bordeaux/service/res/values/strings.xml | 59 --- .../src/android/bordeaux/services/Aggregator.java | 28 -- .../bordeaux/services/AggregatorManager.java | 160 ------- .../bordeaux/services/AggregatorRecordStorage.java | 120 ------ .../bordeaux/services/AggregatorStorage.java | 57 --- .../src/android/bordeaux/services/BaseCluster.java | 213 ---------- .../services/BordeauxAggregatorManager.java | 148 ------- .../bordeaux/services/BordeauxClassifier.java | 103 ----- .../bordeaux/services/BordeauxManagerService.java | 152 ------- .../bordeaux/services/BordeauxPredictor.java | 117 ------ .../android/bordeaux/services/BordeauxRanker.java | 139 ------- .../android/bordeaux/services/BordeauxService.java | 197 --------- .../bordeaux/services/BordeauxSessionManager.java | 206 --------- .../bordeaux/services/BordeauxSessionStorage.java | 152 ------- .../android/bordeaux/services/ClusterManager.java | 338 --------------- .../android/bordeaux/services/FeatureAssembly.java | 112 ----- .../bordeaux/services/IAggregatorManager.aidl | 38 -- .../bordeaux/services/IBordeauxLearner.java | 37 -- .../bordeaux/services/IBordeauxService.aidl | 51 --- .../services/IBordeauxServiceCallback.aidl | 29 -- .../bordeaux/services/ILearning_MulticlassPA.aidl | 29 -- .../services/ILearning_StochasticLinearRanker.aidl | 34 -- .../src/android/bordeaux/services/IPredictor.aidl | 26 -- .../src/android/bordeaux/services/IntFloat.aidl | 3 - .../src/android/bordeaux/services/IntFloat.java | 40 -- .../bordeaux/services/Learning_MulticlassPA.java | 89 ---- .../services/Learning_StochasticLinearRanker.java | 146 ------- .../android/bordeaux/services/LocationCluster.java | 149 ------- .../bordeaux/services/LocationStatsAggregator.java | 239 ----------- .../bordeaux/services/MotionStatsAggregator.java | 39 -- .../src/android/bordeaux/services/Predictor.java | 174 -------- .../services/StochasticLinearRankerWithPrior.java | 211 ---------- .../src/android/bordeaux/services/StringFloat.aidl | 3 - .../src/android/bordeaux/services/StringFloat.java | 46 -- .../android/bordeaux/services/StringString.aidl | 3 - .../android/bordeaux/services/StringString.java | 41 -- .../bordeaux/services/TimeStatsAggregator.java | 199 --------- 68 files changed, 7441 deletions(-) delete mode 100644 Android.mk delete mode 100644 bordeaux/Android.mk delete mode 100644 bordeaux/learning/Android.mk delete mode 100644 bordeaux/learning/multiclass_pa/Android.mk delete mode 100644 bordeaux/learning/multiclass_pa/java/android/bordeaux/learning/MulticlassPA.java delete mode 100644 bordeaux/learning/multiclass_pa/jni/jni_multiclass_pa.cpp delete mode 100644 bordeaux/learning/multiclass_pa/jni/jni_multiclass_pa.h delete mode 100644 bordeaux/learning/multiclass_pa/native/multiclass_pa.cpp delete mode 100644 bordeaux/learning/multiclass_pa/native/multiclass_pa.h delete mode 100644 bordeaux/learning/multiclass_pa/native/util.cpp delete mode 100644 bordeaux/learning/multiclass_pa/native/util.h delete mode 100644 bordeaux/learning/predictor_histogram/Android.mk delete mode 100644 bordeaux/learning/predictor_histogram/java/android/bordeaux/learning/HistogramPredictor.java delete mode 100644 bordeaux/learning/stochastic_linear_ranker/Android.mk delete mode 100644 bordeaux/learning/stochastic_linear_ranker/java/android/bordeaux/learning/StochasticLinearRanker.java delete mode 100644 bordeaux/learning/stochastic_linear_ranker/jni/jni_stochastic_linear_ranker.cpp delete mode 100644 bordeaux/learning/stochastic_linear_ranker/jni/jni_stochastic_linear_ranker.h delete mode 100644 bordeaux/learning/stochastic_linear_ranker/native/common_defs.h delete mode 100644 bordeaux/learning/stochastic_linear_ranker/native/learning_rate_controller-inl.h delete mode 100644 bordeaux/learning/stochastic_linear_ranker/native/sparse_weight_vector.cpp delete mode 100644 bordeaux/learning/stochastic_linear_ranker/native/sparse_weight_vector.h delete mode 100644 bordeaux/learning/stochastic_linear_ranker/native/stochastic_linear_ranker.cpp delete mode 100644 bordeaux/learning/stochastic_linear_ranker/native/stochastic_linear_ranker.h delete mode 100644 bordeaux/service/Android.mk delete mode 100644 bordeaux/service/AndroidManifest.xml delete mode 100644 bordeaux/service/res/drawable-hdpi/ic_bordeaux.png delete mode 100644 bordeaux/service/res/drawable-mdpi/ic_bordeaux.png delete mode 100644 bordeaux/service/res/drawable-xhdpi/ic_bordeaux.png delete mode 100644 bordeaux/service/res/layout/lava_messenger_service_binding.xml delete mode 100644 bordeaux/service/res/layout/lava_service_binding.xml delete mode 100644 bordeaux/service/res/layout/lava_service_controller.xml delete mode 100644 bordeaux/service/res/values/strings.xml delete mode 100644 bordeaux/service/src/android/bordeaux/services/Aggregator.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/AggregatorManager.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/AggregatorRecordStorage.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/AggregatorStorage.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/BaseCluster.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/BordeauxAggregatorManager.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/BordeauxClassifier.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/BordeauxManagerService.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/BordeauxPredictor.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/BordeauxRanker.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/BordeauxService.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/BordeauxSessionManager.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/BordeauxSessionStorage.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/ClusterManager.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/FeatureAssembly.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/IAggregatorManager.aidl delete mode 100644 bordeaux/service/src/android/bordeaux/services/IBordeauxLearner.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/IBordeauxService.aidl delete mode 100644 bordeaux/service/src/android/bordeaux/services/IBordeauxServiceCallback.aidl delete mode 100644 bordeaux/service/src/android/bordeaux/services/ILearning_MulticlassPA.aidl delete mode 100644 bordeaux/service/src/android/bordeaux/services/ILearning_StochasticLinearRanker.aidl delete mode 100644 bordeaux/service/src/android/bordeaux/services/IPredictor.aidl delete mode 100644 bordeaux/service/src/android/bordeaux/services/IntFloat.aidl delete mode 100644 bordeaux/service/src/android/bordeaux/services/IntFloat.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/Learning_MulticlassPA.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/Learning_StochasticLinearRanker.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/LocationCluster.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/LocationStatsAggregator.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/MotionStatsAggregator.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/Predictor.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/StochasticLinearRankerWithPrior.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/StringFloat.aidl delete mode 100644 bordeaux/service/src/android/bordeaux/services/StringFloat.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/StringString.aidl delete mode 100644 bordeaux/service/src/android/bordeaux/services/StringString.java delete mode 100644 bordeaux/service/src/android/bordeaux/services/TimeStatsAggregator.java diff --git a/Android.mk b/Android.mk deleted file mode 100644 index 0918da517..000000000 --- a/Android.mk +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (C) 2012 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -TOP_LOCAL_PATH:= $(call my-dir) - -include $(call all-subdir-makefiles) diff --git a/bordeaux/Android.mk b/bordeaux/Android.mk deleted file mode 100644 index 0918da517..000000000 --- a/bordeaux/Android.mk +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (C) 2012 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -TOP_LOCAL_PATH:= $(call my-dir) - -include $(call all-subdir-makefiles) diff --git a/bordeaux/learning/Android.mk b/bordeaux/learning/Android.mk deleted file mode 100644 index 562a81def..000000000 --- a/bordeaux/learning/Android.mk +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright (C) 2011 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LEARNING_LOCAL_PATH:= $(call my-dir) -include $(call all-subdir-makefiles) - -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := samples tests - -LOCAL_MODULE := libbordeaux - -LOCAL_WHOLE_STATIC_LIBRARIES := libmulticlass_pa libstochastic_linear -LOCAL_SHARED_LIBRARIES := libcutils liblog - - -LOCAL_C_INCLUDES += $(LOCAL_PATH)/../native - -include $(BUILD_SHARED_LIBRARY) - -## -# Build java lib -## -LOCAL_PATH:= $(LEARNING_LOCAL_PATH) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := samples tests - -LOCAL_SRC_FILES := $(call all-java-files-under, multiclass_pa stochastic_linear_ranker ) \ - $(call all-java-files-under, predictor_histogram) - -LOCAL_MODULE := bordeaux_learners - -LOCAL_PROGUARD_ENABLED := disabled - -LOCAL_JNI_SHARED_LIBRARIES := libbordeaux - -include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/bordeaux/learning/multiclass_pa/Android.mk b/bordeaux/learning/multiclass_pa/Android.mk deleted file mode 100644 index c69f69158..000000000 --- a/bordeaux/learning/multiclass_pa/Android.mk +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (C) 2011 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_PATH := $(call my-dir) - -## -# Build native code -## -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := samples tests - -LOCAL_MODULE := libmulticlass_pa - -LOCAL_SRC_FILES := native/multiclass_pa.cpp \ - jni/jni_multiclass_pa.cpp - - -LOCAL_C_INCLUDES += $(LOCAL_PATH)/../native - -include $(BUILD_STATIC_LIBRARY) diff --git a/bordeaux/learning/multiclass_pa/java/android/bordeaux/learning/MulticlassPA.java b/bordeaux/learning/multiclass_pa/java/android/bordeaux/learning/MulticlassPA.java deleted file mode 100644 index 8a868e1cc..000000000 --- a/bordeaux/learning/multiclass_pa/java/android/bordeaux/learning/MulticlassPA.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package android.bordeaux.learning; - -/** - * Wrapper for multiclass passive aggressive classifier. - * version 1 supports indexed sparse feature only. - */ -public class MulticlassPA { - - public MulticlassPA(int numClasses, int numDimensions, float aggressiveness) { - nativeClassifier = initNativeClassifier(numClasses, numDimensions, - aggressiveness); - } - - /** - * Train on one example - */ - public boolean sparseTrainOneExample(int[] index_array, - float[] float_array, - int target) { - return nativeSparseTrainOneExample( - index_array, float_array, target, nativeClassifier); - } - - /** - * Train on one example - */ - public int sparseGetClass(int[] index_array, float[] float_array) { - return nativeSparseGetClass(index_array, float_array, nativeClassifier); - } - - static { - System.loadLibrary("bordeaux"); - } - - private long nativeClassifier; - - /* - * Initialize native classifier - */ - private native long initNativeClassifier(int num_classes, int num_dims, float aggressiveness); - - private native void deleteNativeClassifier(long classPtr); - - private native boolean nativeSparseTrainOneExample(int[] index_array, - float[] float_array, - int target, long classPtr); - - private native int nativeSparseGetClass(int[] index_array, - float[] float_array, - long classPtr); -} diff --git a/bordeaux/learning/multiclass_pa/jni/jni_multiclass_pa.cpp b/bordeaux/learning/multiclass_pa/jni/jni_multiclass_pa.cpp deleted file mode 100644 index 3825586ed..000000000 --- a/bordeaux/learning/multiclass_pa/jni/jni_multiclass_pa.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "jni/jni_multiclass_pa.h" -#include "native/multiclass_pa.h" - -#include - -using learningfw::MulticlassPA; -using std::vector; -using std::pair; - -void CreateIndexValuePairs(const int* indices, const float* values, - const int length, vector >* pairs) { - pairs->clear(); - - for (int i = 0; i < length; ++i) { - pair new_pair(indices[i], values[i]); - pairs->push_back(new_pair); - } -} - -jlong Java_android_bordeaux_learning_MulticlassPA_initNativeClassifier(JNIEnv* /* env */, - jobject /* thiz */, - jint num_classes, - jint num_dims, - jfloat aggressiveness) { - MulticlassPA* classifier = new MulticlassPA(num_classes, - num_dims, - aggressiveness); - return ((jlong) classifier); -} - - -jboolean Java_android_bordeaux_learning_MulticlassPA_deleteNativeClassifier(JNIEnv* /* env */, - jobject /* thiz */, - jlong paPtr) { - MulticlassPA* classifier = (MulticlassPA*) paPtr; - delete classifier; - return JNI_TRUE; -} - -jboolean Java_android_bordeaux_learning_MulticlassPA_nativeSparseTrainOneExample(JNIEnv* env, - jobject /* thiz */, - jintArray index_array, - jfloatArray value_array, - jint target, - jlong paPtr) { - MulticlassPA* classifier = (MulticlassPA*) paPtr; - - if (classifier && index_array && value_array) { - - jfloat* values = env->GetFloatArrayElements(value_array, NULL); - jint* indices = env->GetIntArrayElements(index_array, NULL); - const int value_len = env->GetArrayLength(value_array); - const int index_len = env->GetArrayLength(index_array); - - if (values && indices && value_len == index_len) { - vector > inputs; - - CreateIndexValuePairs(indices, values, value_len, &inputs); - classifier->SparseTrainOneExample(inputs, target); - env->ReleaseIntArrayElements(index_array, indices, JNI_ABORT); - env->ReleaseFloatArrayElements(value_array, values, JNI_ABORT); - - return JNI_TRUE; - } - env->ReleaseIntArrayElements(index_array, indices, JNI_ABORT); - env->ReleaseFloatArrayElements(value_array, values, JNI_ABORT); - } - - return JNI_FALSE; -} - - -jint Java_android_bordeaux_learning_MulticlassPA_nativeSparseGetClass(JNIEnv* env, - jobject /* thiz */, - jintArray index_array, - jfloatArray value_array, - jlong paPtr) { - - MulticlassPA* classifier = (MulticlassPA*) paPtr; - - if (classifier && index_array && value_array) { - - jfloat* values = env->GetFloatArrayElements(value_array, NULL); - jint* indices = env->GetIntArrayElements(index_array, NULL); - const int value_len = env->GetArrayLength(value_array); - const int index_len = env->GetArrayLength(index_array); - - if (values && indices && value_len == index_len) { - vector > inputs; - CreateIndexValuePairs(indices, values, value_len, &inputs); - env->ReleaseIntArrayElements(index_array, indices, JNI_ABORT); - env->ReleaseFloatArrayElements(value_array, values, JNI_ABORT); - return classifier->SparseGetClass(inputs); - } - env->ReleaseIntArrayElements(index_array, indices, JNI_ABORT); - env->ReleaseFloatArrayElements(value_array, values, JNI_ABORT); - } - - return -1; -} diff --git a/bordeaux/learning/multiclass_pa/jni/jni_multiclass_pa.h b/bordeaux/learning/multiclass_pa/jni/jni_multiclass_pa.h deleted file mode 100644 index dd0f43d5c..000000000 --- a/bordeaux/learning/multiclass_pa/jni/jni_multiclass_pa.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LEARNINGFW_JNI_MULTICLASS_PA_H -#define LEARNINGFW_JNI_MULTICLASS_PA_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -JNIEXPORT jlong JNICALL -Java_android_bordeaux_learning_MulticlassPA_initNativeClassifier(JNIEnv* env, - jobject thiz, - jint num_classes, - jint num_dims, - jfloat aggressiveness); - - -JNIEXPORT jboolean JNICALL -Java_android_bordeaux_learning_MulticlassPA_deleteNativeClassifier(JNIEnv* env, - jobject thiz, - jlong paPtr); - -JNIEXPORT jboolean JNICALL -Java_android_bordeaux_learning_MulticlassPA_nativeSparseTrainOneExample(JNIEnv* env, - jobject thiz, - jintArray index_array, - jfloatArray value_array, - jint target, - jlong paPtr); - -JNIEXPORT jint JNICALL -Java_android_bordeaux_learning_MulticlassPA_nativeSparseGetClass(JNIEnv* env, - jobject thiz, - jintArray index_array, - jfloatArray value_array, - jlong paPtr); - - -#ifdef __cplusplus -} -#endif - -#endif /* ANDROID_LEARNINGFW_JNI_MULTICLASS_PA_H */ diff --git a/bordeaux/learning/multiclass_pa/native/multiclass_pa.cpp b/bordeaux/learning/multiclass_pa/native/multiclass_pa.cpp deleted file mode 100644 index 9ee12b035..000000000 --- a/bordeaux/learning/multiclass_pa/native/multiclass_pa.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// This file contains the MulticlassPA class which implements a simple -// linear multi-class classifier based on the multi-prototype version of -// passive aggressive. - -#include "native/multiclass_pa.h" - -#include - -using std::vector; -using std::pair; - -namespace learningfw { - -float RandFloat() { - return static_cast(rand()) / RAND_MAX; -} - -MulticlassPA::MulticlassPA(int num_classes, - int num_dimensions, - float aggressiveness) - : num_classes_(num_classes), - num_dimensions_(num_dimensions), - aggressiveness_(aggressiveness) { - InitializeParameters(); -} - -MulticlassPA::~MulticlassPA() { -} - -void MulticlassPA::InitializeParameters() { - parameters_.resize(num_classes_); - for (int i = 0; i < num_classes_; ++i) { - parameters_[i].resize(num_dimensions_); - for (int j = 0; j < num_dimensions_; ++j) { - parameters_[i][j] = 0.0; - } - } -} - -int MulticlassPA::PickAClassExcept(int target) { - int picked; - do { - picked = static_cast(RandFloat() * num_classes_); - // picked = static_cast(random_.RandFloat() * num_classes_); - } while (target == picked); - return picked; -} - -int MulticlassPA::PickAnExample(int num_examples) { - return static_cast(RandFloat() * num_examples); -} - -float MulticlassPA::Score(const vector& inputs, - const vector& parameters) const { - // CHECK_EQ(inputs.size(), parameters.size()); - float result = 0.0; - for (int i = 0; i < static_cast(inputs.size()); ++i) { - result += inputs[i] * parameters[i]; - } - return result; -} - -float MulticlassPA::SparseScore(const vector >& inputs, - const vector& parameters) const { - float result = 0.0; - for (int i = 0; i < static_cast(inputs.size()); ++i) { - //DCHECK_GE(inputs[i].first, 0); - //DCHECK_LT(inputs[i].first, parameters.size()); - result += inputs[i].second * parameters[inputs[i].first]; - } - return result; -} - -float MulticlassPA::L2NormSquare(const vector& inputs) const { - float norm = 0; - for (int i = 0; i < static_cast(inputs.size()); ++i) { - norm += inputs[i] * inputs[i]; - } - return norm; -} - -float MulticlassPA::SparseL2NormSquare( - const vector >& inputs) const { - float norm = 0; - for (int i = 0; i < static_cast(inputs.size()); ++i) { - norm += inputs[i].second * inputs[i].second; - } - return norm; -} - -float MulticlassPA::TrainOneExample(const vector& inputs, int target) { - //CHECK_GE(target, 0); - //CHECK_LT(target, num_classes_); - float target_class_score = Score(inputs, parameters_[target]); - // VLOG(1) << "target class " << target << " score " << target_class_score; - int other_class = PickAClassExcept(target); - float other_class_score = Score(inputs, parameters_[other_class]); - // VLOG(1) << "other class " << other_class << " score " << other_class_score; - float loss = 1.0 - target_class_score + other_class_score; - if (loss > 0.0) { - // Compute the learning rate according to PA-I. - float twice_norm_square = L2NormSquare(inputs) * 2.0; - if (twice_norm_square == 0.0) { - twice_norm_square = kEpsilon; - } - float rate = loss / twice_norm_square; - if (rate > aggressiveness_) { - rate = aggressiveness_; - } - // VLOG(1) << "loss = " << loss << " rate = " << rate; - // Modify the parameter vectors of the correct and wrong classes - for (int i = 0; i < static_cast(inputs.size()); ++i) { - // First modify the parameter value of the correct class - parameters_[target][i] += rate * inputs[i]; - // Then modify the parameter value of the wrong class - parameters_[other_class][i] -= rate * inputs[i]; - } - return loss; - } - return 0.0; -} - -float MulticlassPA::SparseTrainOneExample( - const vector >& inputs, int target) { - // CHECK_GE(target, 0); - // CHECK_LT(target, num_classes_); - float target_class_score = SparseScore(inputs, parameters_[target]); - // VLOG(1) << "target class " << target << " score " << target_class_score; - int other_class = PickAClassExcept(target); - float other_class_score = SparseScore(inputs, parameters_[other_class]); - // VLOG(1) << "other class " << other_class << " score " << other_class_score; - float loss = 1.0 - target_class_score + other_class_score; - if (loss > 0.0) { - // Compute the learning rate according to PA-I. - float twice_norm_square = SparseL2NormSquare(inputs) * 2.0; - if (twice_norm_square == 0.0) { - twice_norm_square = kEpsilon; - } - float rate = loss / twice_norm_square; - if (rate > aggressiveness_) { - rate = aggressiveness_; - } - // VLOG(1) << "loss = " << loss << " rate = " << rate; - // Modify the parameter vectors of the correct and wrong classes - for (int i = 0; i < static_cast(inputs.size()); ++i) { - // First modify the parameter value of the correct class - parameters_[target][inputs[i].first] += rate * inputs[i].second; - // Then modify the parameter value of the wrong class - parameters_[other_class][inputs[i].first] -= rate * inputs[i].second; - } - return loss; - } - return 0.0; -} - -float MulticlassPA::Train(const vector, int> >& data, - int num_iterations) { - int num_examples = data.size(); - float total_loss = 0.0; - for (int t = 0; t < num_iterations; ++t) { - int index = PickAnExample(num_examples); - float loss_t = TrainOneExample(data[index].first, data[index].second); - total_loss += loss_t; - } - return total_loss / static_cast(num_iterations); -} - -float MulticlassPA::SparseTrain( - const vector >, int> >& data, - int num_iterations) { - int num_examples = data.size(); - float total_loss = 0.0; - for (int t = 0; t < num_iterations; ++t) { - int index = PickAnExample(num_examples); - float loss_t = SparseTrainOneExample(data[index].first, data[index].second); - total_loss += loss_t; - } - return total_loss / static_cast(num_iterations); -} - -int MulticlassPA::GetClass(const vector& inputs) { - int best_class = -1; - float best_score = -10000.0; - // float best_score = -MathLimits::kMax; - for (int i = 0; i < num_classes_; ++i) { - float score_i = Score(inputs, parameters_[i]); - if (score_i > best_score) { - best_score = score_i; - best_class = i; - } - } - return best_class; -} - -int MulticlassPA::SparseGetClass(const vector >& inputs) { - int best_class = -1; - float best_score = -10000.0; - //float best_score = -MathLimits::kMax; - for (int i = 0; i < num_classes_; ++i) { - float score_i = SparseScore(inputs, parameters_[i]); - if (score_i > best_score) { - best_score = score_i; - best_class = i; - } - } - return best_class; -} - -float MulticlassPA::Test(const vector, int> >& data) { - int num_examples = data.size(); - float total_error = 0.0; - for (int t = 0; t < num_examples; ++t) { - int best_class = GetClass(data[t].first); - if (best_class != data[t].second) { - ++total_error; - } - } - return total_error / num_examples; -} - -float MulticlassPA::SparseTest( - const vector >, int> >& data) { - int num_examples = data.size(); - float total_error = 0.0; - for (int t = 0; t < num_examples; ++t) { - int best_class = SparseGetClass(data[t].first); - if (best_class != data[t].second) { - ++total_error; - } - } - return total_error / num_examples; -} -} // namespace learningfw diff --git a/bordeaux/learning/multiclass_pa/native/multiclass_pa.h b/bordeaux/learning/multiclass_pa/native/multiclass_pa.h deleted file mode 100644 index c4d99440a..000000000 --- a/bordeaux/learning/multiclass_pa/native/multiclass_pa.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// This file contains the MulticlassPA class which implements a simple -// linear multi-class classifier based on the multi-prototype version of -// passive aggressive. - -#ifndef LEARNINGFW_MULTICLASS_PA_H_ -#define LEARNINGFW_MULTICLASS_PA_H_ - -#include -#include - -const float kEpsilon = 1.0e-4; - -namespace learningfw { - -class MulticlassPA { - public: - MulticlassPA(int num_classes, - int num_dimensions, - float aggressiveness); - virtual ~MulticlassPA(); - - // Initialize all parameters to 0.0. - void InitializeParameters(); - - // Returns a random class that is different from the target class. - int PickAClassExcept(int target); - - // Returns a random example. - int PickAnExample(int num_examples); - - // Computes the score of a given input vector for a given parameter - // vector, by computing the dot product between the two. - float Score(const std::vector& inputs, - const std::vector& parameters) const; - float SparseScore(const std::vector >& inputs, - const std::vector& parameters) const; - - // Returns the square of the L2 norm. - float L2NormSquare(const std::vector& inputs) const; - float SparseL2NormSquare(const std::vector >& inputs) const; - - // Verify if the given example is correctly classified with margin with - // respect to a random class. If not, then modifies the corresponding - // parameters using passive-aggressive. - virtual float TrainOneExample(const std::vector& inputs, int target); - virtual float SparseTrainOneExample( - const std::vector >& inputs, int target); - - // Iteratively train the model for num_iterations on the given dataset. - float Train(const std::vector, int> >& data, - int num_iterations); - float SparseTrain( - const std::vector >, int> >& data, - int num_iterations); - - // Returns the best class for a given input vector. - virtual int GetClass(const std::vector& inputs); - virtual int SparseGetClass(const std::vector >& inputs); - - // Computes the test error of a given test set on the current model. - float Test(const std::vector, int> >& data); - float SparseTest( - const std::vector >, int> >& data); - - // A few accessors used by the sub-classes. - inline float aggressiveness() const { - return aggressiveness_; - } - - inline std::vector >& parameters() { - return parameters_; - } - - inline std::vector >* mutable_parameters() { - return ¶meters_; - } - - inline int num_classes() const { - return num_classes_; - } - - inline int num_dimensions() const { - return num_dimensions_; - } - - private: - // Keeps the current parameter vector. - std::vector > parameters_; - - // The number of classes of the problem. - int num_classes_; - - // The number of dimensions of the input vectors. - int num_dimensions_; - - // Controls how "aggressive" training should be. - float aggressiveness_; - -}; -} // namespace learningfw -#endif // LEARNINGFW_MULTICLASS_PA_H_ diff --git a/bordeaux/learning/multiclass_pa/native/util.cpp b/bordeaux/learning/multiclass_pa/native/util.cpp deleted file mode 100644 index fc92fe49a..000000000 --- a/bordeaux/learning/multiclass_pa/native/util.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// This file contains a few utilities for MulticlassPA - -#include "learning/multiclass_pa/util.h" - -#include - -#include "learning/multiclass_pa/multiclass_pa.h" -#include "learning/multiclass_pa/multiclass_pa_max.h" -#include "learning/multiclass_pa/multiclass_pa_opt.h" -#include "learning/multiclass_pa/multiclass_warp.h" -#include "strings/strutil.h" - -namespace learning_multiclass_pa { - -MulticlassPA* CreateMulticlassPA(const string& version, - int32 num_classes, - int32 num_dimensions, - float aggressiveness) { - MulticlassPA* machine = NULL; - if (StringCaseEqual(version, "max")) { - machine = reinterpret_cast( - new MulticlassPAMax(num_classes, num_dimensions, aggressiveness)); - } else if (StringCaseEqual(version, "opt")) { - machine = reinterpret_cast( - new MulticlassPAOpt(num_classes, num_dimensions, aggressiveness)); - } else if (StringCaseEqual(version, "random")) { - machine = new MulticlassPA(num_classes, num_dimensions, aggressiveness); - } else if (StringCaseEqual(version, "warp")) { - machine = reinterpret_cast( - new MulticlassWarp(num_classes, num_dimensions, aggressiveness)); - } else { - LOG(ERROR) << "Machine type (" << version << ") unknown"; - } - return machine; -} -} // namespace learning_multiclass_pa diff --git a/bordeaux/learning/multiclass_pa/native/util.h b/bordeaux/learning/multiclass_pa/native/util.h deleted file mode 100644 index a3aa4b571..000000000 --- a/bordeaux/learning/multiclass_pa/native/util.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// This file contains some utilities for MulticlassPA - -#ifndef LEARNING_MULTICLASS_PA_UTIL_H_ -#define LEARNING_MULTICLASS_PA_UTIL_H_ - -#include - -#include "learning/multiclass_pa/multiclass_pa.h" - -namespace learning_multiclass_pa { - -MulticlassPA* CreateMulticlassPA(const string& version, - int32 num_classes, - int32 num_dimensions, - float aggressiveness); -} // namespace learning_multiclass_pa -#endif // LEARNING_MULTICLASS_PA_UTIL_H_ diff --git a/bordeaux/learning/predictor_histogram/Android.mk b/bordeaux/learning/predictor_histogram/Android.mk deleted file mode 100644 index 1c352f1cb..000000000 --- a/bordeaux/learning/predictor_histogram/Android.mk +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (C) 2011 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_PATH := $(call my-dir) diff --git a/bordeaux/learning/predictor_histogram/java/android/bordeaux/learning/HistogramPredictor.java b/bordeaux/learning/predictor_histogram/java/android/bordeaux/learning/HistogramPredictor.java deleted file mode 100644 index e63f40dd9..000000000 --- a/bordeaux/learning/predictor_histogram/java/android/bordeaux/learning/HistogramPredictor.java +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.learning; - -import android.util.Log; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ConcurrentHashMap; -/** - * A histogram based predictor which records co-occurrences of applations with a speficic - * feature, for example, location, * time of day, etc. The histogram is kept in a two level - * hash table. The first level key is the feature value and the second level key is the app - * id. - */ -// TODOS: -// 1. Use forgetting factor to downweight istances propotional to the time -// 2. Different features could have different weights on prediction scores. -// 3. Add function to remove sampleid (i.e. remove apps that are uninstalled). - - -public class HistogramPredictor { - final static String TAG = "HistogramPredictor"; - - private HashMap mPredictor = - new HashMap(); - - private HashMap mClassCounts = new HashMap(); - private HashSet mBlacklist = new HashSet(); - - private static final int MINIMAL_FEATURE_VALUE_COUNTS = 5; - private static final int MINIMAL_APP_APPEARANCE_COUNTS = 5; - - // This parameter ranges from 0 to 1 which determines the effect of app prior. - // When it is set to 0, app prior means completely neglected. When it is set to 1 - // the predictor is a standard naive bayes model. - private static final int PRIOR_K_VALUE = 1; - - private static final String[] APP_BLACKLIST = { - "com.android.contacts", - "com.android.chrome", - "com.android.providers.downloads.ui", - "com.android.settings", - "com.android.vending", - "com.android.mms", - "com.google.android.gm", - "com.google.android.gallery3d", - "com.google.android.apps.googlevoice", - }; - - public HistogramPredictor(String[] blackList) { - for (String appName : blackList) { - mBlacklist.add(appName); - } - } - - /* - * This class keeps the histogram counts for each feature and provide the - * joint probabilities of . - */ - private class HistogramCounter { - private HashMap > mCounter = - new HashMap >(); - - public HistogramCounter() { - mCounter.clear(); - } - - public void setCounter(HashMap > counter) { - resetCounter(); - mCounter.putAll(counter); - } - - public void resetCounter() { - mCounter.clear(); - } - - public void addSample(String className, String featureValue) { - HashMap classCounts; - - if (!mCounter.containsKey(featureValue)) { - classCounts = new HashMap(); - mCounter.put(featureValue, classCounts); - } else { - classCounts = mCounter.get(featureValue); - } - int count = (classCounts.containsKey(className)) ? - classCounts.get(className) + 1 : 1; - classCounts.put(className, count); - } - - public HashMap getClassScores(String featureValue) { - HashMap classScores = new HashMap(); - - if (mCounter.containsKey(featureValue)) { - int totalCount = 0; - for(Map.Entry entry : - mCounter.get(featureValue).entrySet()) { - String app = entry.getKey(); - int count = entry.getValue(); - - // For apps with counts less than or equal to one, we treated - // those as having count one. Hence their score, i.e. log(count) - // would be zero. classScroes stores only apps with non-zero scores. - // Note that totalCount also neglect app with single occurrence. - if (count > 1) { - double score = Math.log((double) count); - classScores.put(app, score); - totalCount += count; - } - } - if (totalCount < MINIMAL_FEATURE_VALUE_COUNTS) { - classScores.clear(); - } - } - return classScores; - } - - public byte[] getModel() { - try { - ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); - ObjectOutputStream objStream = new ObjectOutputStream(byteStream); - synchronized(mCounter) { - objStream.writeObject(mCounter); - } - byte[] bytes = byteStream.toByteArray(); - return bytes; - } catch (IOException e) { - throw new RuntimeException("Can't get model"); - } - } - - public boolean setModel(final byte[] modelData) { - mCounter.clear(); - HashMap > model; - - try { - ByteArrayInputStream input = new ByteArrayInputStream(modelData); - ObjectInputStream objStream = new ObjectInputStream(input); - model = (HashMap >) objStream.readObject(); - } catch (IOException e) { - throw new RuntimeException("Can't load model"); - } catch (ClassNotFoundException e) { - throw new RuntimeException("Learning class not found"); - } - - synchronized(mCounter) { - mCounter.putAll(model); - } - - return true; - } - - - public HashMap > getCounter() { - return mCounter; - } - - public String toString() { - String result = ""; - for (Map.Entry > entry : - mCounter.entrySet()) { - result += "{ " + entry.getKey() + " : " + - entry.getValue().toString() + " }"; - } - return result; - } - } - - /* - * Given a map of feature name -value pairs returns topK mostly likely apps to - * be launched with corresponding likelihoods. If topK is set zero, it will return - * the whole list. - */ - public List > findTopClasses(Map features, int topK) { - // Most sophisticated function in this class - HashMap appScores = new HashMap(); - int validFeatureCount = 0; - - // compute all app scores - for (Map.Entry entry : mPredictor.entrySet()) { - String featureName = entry.getKey(); - HistogramCounter counter = entry.getValue(); - - if (features.containsKey(featureName)) { - String featureValue = features.get(featureName); - HashMap scoreMap = counter.getClassScores(featureValue); - - if (scoreMap.isEmpty()) { - continue; - } - validFeatureCount++; - - for (Map.Entry item : scoreMap.entrySet()) { - String appName = item.getKey(); - double appScore = item.getValue(); - if (appScores.containsKey(appName)) { - appScore += appScores.get(appName); - } - appScores.put(appName, appScore); - } - } - } - - HashMap appCandidates = new HashMap(); - for (Map.Entry entry : appScores.entrySet()) { - String appName = entry.getKey(); - if (mBlacklist.contains(appName)) { - Log.i(TAG, appName + " is in blacklist"); - continue; - } - if (!mClassCounts.containsKey(appName)) { - throw new RuntimeException("class count error!"); - } - int appCount = mClassCounts.get(appName); - if (appCount < MINIMAL_APP_APPEARANCE_COUNTS) { - Log.i(TAG, appName + " doesn't have enough counts"); - continue; - } - - double appScore = entry.getValue(); - double appPrior = Math.log((double) appCount); - appCandidates.put(appName, - appScore - appPrior * (validFeatureCount - PRIOR_K_VALUE)); - } - - // sort app scores - List > appList = - new ArrayList >(appCandidates.size()); - appList.addAll(appCandidates.entrySet()); - Collections.sort(appList, new Comparator >() { - public int compare(Map.Entry o1, - Map.Entry o2) { - return o2.getValue().compareTo(o1.getValue()); - } - }); - - if (topK == 0) { - topK = appList.size(); - } - return appList.subList(0, Math.min(topK, appList.size())); - } - - /* - * Add a new observation of given sample id and features to the histograms - */ - public void addSample(String sampleId, Map features) { - for (Map.Entry entry : features.entrySet()) { - String featureName = entry.getKey(); - String featureValue = entry.getValue(); - - useFeature(featureName); - HistogramCounter counter = mPredictor.get(featureName); - counter.addSample(sampleId, featureValue); - } - - int sampleCount = (mClassCounts.containsKey(sampleId)) ? - mClassCounts.get(sampleId) + 1 : 1; - mClassCounts.put(sampleId, sampleCount); - } - - /* - * reset predictor to a empty model - */ - public void resetPredictor() { - // TODO: not sure this step would reduce memory waste - for (HistogramCounter counter : mPredictor.values()) { - counter.resetCounter(); - } - mPredictor.clear(); - mClassCounts.clear(); - } - - /* - * convert the prediction model into a byte array - */ - public byte[] getModel() { - // TODO: convert model to a more memory efficient data structure. - HashMap > > model = - new HashMap > >(); - for(Map.Entry entry : mPredictor.entrySet()) { - model.put(entry.getKey(), entry.getValue().getCounter()); - } - - try { - ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); - ObjectOutputStream objStream = new ObjectOutputStream(byteStream); - objStream.writeObject(model); - byte[] bytes = byteStream.toByteArray(); - return bytes; - } catch (IOException e) { - throw new RuntimeException("Can't get model"); - } - } - - /* - * set the prediction model from a model data in the format of byte array - */ - public boolean setModel(final byte[] modelData) { - HashMap > > model; - - try { - ByteArrayInputStream input = new ByteArrayInputStream(modelData); - ObjectInputStream objStream = new ObjectInputStream(input); - model = (HashMap > >) - objStream.readObject(); - } catch (IOException e) { - throw new RuntimeException("Can't load model"); - } catch (ClassNotFoundException e) { - throw new RuntimeException("Learning class not found"); - } - - resetPredictor(); - for (Map.Entry > > entry : - model.entrySet()) { - useFeature(entry.getKey()); - mPredictor.get(entry.getKey()).setCounter(entry.getValue()); - } - - // TODO: this is a temporary fix for now - loadClassCounter(); - - return true; - } - - private void loadClassCounter() { - String TIME_OF_WEEK = "Time of Week"; - - if (!mPredictor.containsKey(TIME_OF_WEEK)) { - throw new RuntimeException("Precition model error: missing Time of Week!"); - } - - HashMap > counter = - mPredictor.get(TIME_OF_WEEK).getCounter(); - - mClassCounts.clear(); - for (HashMap map : counter.values()) { - for (Map.Entry entry : map.entrySet()) { - int classCount = entry.getValue(); - String className = entry.getKey(); - // mTotalClassCount += classCount; - - if (mClassCounts.containsKey(className)) { - classCount += mClassCounts.get(className); - } - mClassCounts.put(className, classCount); - } - } - Log.i(TAG, "class counts: " + mClassCounts); - } - - private void useFeature(String featureName) { - if (!mPredictor.containsKey(featureName)) { - mPredictor.put(featureName, new HistogramCounter()); - } - } -} diff --git a/bordeaux/learning/stochastic_linear_ranker/Android.mk b/bordeaux/learning/stochastic_linear_ranker/Android.mk deleted file mode 100644 index 62f0fd3a0..000000000 --- a/bordeaux/learning/stochastic_linear_ranker/Android.mk +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (C) 2011 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_PATH := $(call my-dir) - -## -# Build native code -## -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := samples tests - -LOCAL_MODULE := libstochastic_linear - -LOCAL_SRC_FILES := native/stochastic_linear_ranker.cpp \ - native/sparse_weight_vector.cpp \ - jni/jni_stochastic_linear_ranker.cpp - - -LOCAL_C_INCLUDES += $(LOCAL_PATH)/../native - -include $(BUILD_STATIC_LIBRARY) diff --git a/bordeaux/learning/stochastic_linear_ranker/java/android/bordeaux/learning/StochasticLinearRanker.java b/bordeaux/learning/stochastic_linear_ranker/java/android/bordeaux/learning/StochasticLinearRanker.java deleted file mode 100644 index 59f32a955..000000000 --- a/bordeaux/learning/stochastic_linear_ranker/java/android/bordeaux/learning/StochasticLinearRanker.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package android.bordeaux.learning; - -import android.util.Log; - -import java.io.Serializable; -import java.util.List; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -/** - * Stochastic Linear Ranker, learns how to rank a sample. The learned rank score - * can be used to compare samples. - * This java class wraps the native StochasticLinearRanker class. - * To update the ranker, call updateClassifier with two samples, with the first - * one having higher rank than the second one. - * To get the rank score of the sample call scoreSample. - * TODO: adding more interfaces for changing the learning parameters - */ -public class StochasticLinearRanker { - String TAG = "StochasticLinearRanker"; - public static int VAR_NUM = 14; - static public class Model implements Serializable { - public HashMap weights = new HashMap(); - public float weightNormalizer = 1; - public HashMap parameters = new HashMap(); - } - - /** - * Initializing a ranker - */ - public StochasticLinearRanker() { - mNativeClassifier = initNativeClassifier(); - } - - /** - * Reset the ranker - */ - public void resetRanker(){ - deleteNativeClassifier(mNativeClassifier); - mNativeClassifier = initNativeClassifier(); - } - - /** - * Train the ranker with a pair of samples. A sample, a pair of arrays of - * keys and values. The first sample should have higher rank than the second - * one. - */ - public boolean updateClassifier(String[] keys_positive, - float[] values_positive, - String[] keys_negative, - float[] values_negative) { - return nativeUpdateClassifier(keys_positive, values_positive, - keys_negative, values_negative, - mNativeClassifier); - } - - /** - * Get the rank score of the sample, a sample is a list of key, value pairs. - */ - public float scoreSample(String[] keys, float[] values) { - return nativeScoreSample(keys, values, mNativeClassifier); - } - - /** - * Get the current model and parameters of ranker - */ - public Model getUModel(){ - Model slrModel = new Model(); - int len = nativeGetLengthClassifier(mNativeClassifier); - String[] wKeys = new String[len]; - float[] wValues = new float[len]; - float wNormalizer = 1; - nativeGetWeightClassifier(wKeys, wValues, wNormalizer, mNativeClassifier); - slrModel.weightNormalizer = wNormalizer; - for (int i=0; i< wKeys.length ; i++) - slrModel.weights.put(wKeys[i], wValues[i]); - - String[] paramKeys = new String[VAR_NUM]; - String[] paramValues = new String[VAR_NUM]; - nativeGetParameterClassifier(paramKeys, paramValues, mNativeClassifier); - for (int i=0; i< paramKeys.length ; i++) - slrModel.parameters.put(paramKeys[i], paramValues[i]); - return slrModel; - } - - /** - * load the given model and parameters to the ranker - */ - public boolean loadModel(Model model) { - String[] wKeys = new String[model.weights.size()]; - float[] wValues = new float[model.weights.size()]; - int i = 0 ; - for (Map.Entry e : model.weights.entrySet()){ - wKeys[i] = e.getKey(); - wValues[i] = e.getValue(); - i++; - } - boolean res = setModelWeights(wKeys, wValues, model.weightNormalizer); - if (!res) - return false; - - for (Map.Entry e : model.parameters.entrySet()){ - res = setModelParameter(e.getKey(), e.getValue()); - if (!res) - return false; - } - return res; - } - - public boolean setModelWeights(String[] keys, float [] values, float normalizer){ - return nativeSetWeightClassifier(keys, values, normalizer, mNativeClassifier); - } - - public boolean setModelParameter(String key, String value){ - boolean res = nativeSetParameterClassifier(key, value, mNativeClassifier); - return res; - } - - /** - * Print a model for debugging - */ - public void print(Model model){ - String Sw = ""; - String Sp = ""; - for (Map.Entry e : model.weights.entrySet()) - Sw = Sw + "<" + e.getKey() + "," + e.getValue() + "> "; - for (Map.Entry e : model.parameters.entrySet()) - Sp = Sp + "<" + e.getKey() + "," + e.getValue() + "> "; - Log.i(TAG, "Weights are " + Sw); - Log.i(TAG, "Normalizer is " + model.weightNormalizer); - Log.i(TAG, "Parameters are " + Sp); - } - - @Override - protected void finalize() throws Throwable { - deleteNativeClassifier(mNativeClassifier); - } - - static { - System.loadLibrary("bordeaux"); - } - - private long mNativeClassifier; - - /* - * The following methods are the java stubs for the jni implementations. - */ - private native long initNativeClassifier(); - - private native void deleteNativeClassifier(long classifierPtr); - - private native boolean nativeUpdateClassifier( - String[] keys_positive, - float[] values_positive, - String[] keys_negative, - float[] values_negative, - long classifierPtr); - - private native float nativeScoreSample(String[] keys, float[] values, long classifierPtr); - - private native void nativeGetWeightClassifier(String [] keys, float[] values, float normalizer, - long classifierPtr); - - private native void nativeGetParameterClassifier(String [] keys, String[] values, - long classifierPtr); - - private native int nativeGetLengthClassifier(long classifierPtr); - - private native boolean nativeSetWeightClassifier(String [] keys, float[] values, - float normalizer, long classifierPtr); - - private native boolean nativeSetParameterClassifier(String key, String value, - long classifierPtr); -} diff --git a/bordeaux/learning/stochastic_linear_ranker/jni/jni_stochastic_linear_ranker.cpp b/bordeaux/learning/stochastic_linear_ranker/jni/jni_stochastic_linear_ranker.cpp deleted file mode 100644 index 34709e457..000000000 --- a/bordeaux/learning/stochastic_linear_ranker/jni/jni_stochastic_linear_ranker.cpp +++ /dev/null @@ -1,461 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "jni/jni_stochastic_linear_ranker.h" -#include "native/common_defs.h" -#include "native/sparse_weight_vector.h" -#include "native/stochastic_linear_ranker.h" - -#include -#include -using std::string; -using std::vector; -using std::unordered_map; -using learning_stochastic_linear::StochasticLinearRanker; -using learning_stochastic_linear::SparseWeightVector; - -void CreateSparseWeightVector(JNIEnv* env, const jobjectArray keys, const float* values, - const int length, SparseWeightVector * sample) { - - for (int i = 0; i < length; ++i) { - jboolean iscopy; - jstring s = (jstring) env->GetObjectArrayElement(keys, i); - const char *key = env->GetStringUTFChars(s, &iscopy); - sample->SetElement(key, static_cast(values[i])); - env->ReleaseStringUTFChars(s,key); - } -} - -void ConvertParameter2Object(JNIEnv* env, jobjectArray *keys, jobjectArray *values, - const char * name , const char * paramValue, int index) { - - jstring jstrK = env->NewStringUTF(name); - jstring jstrV = env->NewStringUTF(paramValue); - env->SetObjectArrayElement(*keys, index, jstrK); - env->SetObjectArrayElement(*values, index, jstrV); -} - -void DecomposeSparseWeightVector(JNIEnv* env, jobjectArray *keys, jfloatArray *values, - SparseWeightVector *sample) { - - SparseWeightVector::Wmap w_ = sample->GetMap(); - int i=0; - for ( SparseWeightVector::Witer_const iter = w_.begin(); - iter != w_.end(); ++iter) { - std::string key = iter->first; - float value = (float) iter->second; - jstring jstr = env->NewStringUTF(key.c_str()); - env->SetObjectArrayElement(*keys, i, jstr); - jfloat s[1]; - s[0] = value; - env->SetFloatArrayRegion(*values, i, 1, s); - i++; - } -} - -jboolean Java_android_bordeaux_learning_StochasticLinearRanker_nativeSetWeightClassifier( - JNIEnv* env, - jobject /* thiz */, - jobjectArray key_array_model, - jfloatArray value_array_model, - jfloat normalizer_model, - jlong paPtr) { - - StochasticLinearRanker* classifier = (StochasticLinearRanker*) paPtr; - if (classifier && key_array_model && value_array_model && normalizer_model) { - const int keys_m_len = env->GetArrayLength(key_array_model); - jfloat* values_m = env->GetFloatArrayElements(value_array_model, NULL); - const int values_m_len = env->GetArrayLength(value_array_model); - - if (values_m && key_array_model && values_m_len == keys_m_len) { - SparseWeightVector model; - CreateSparseWeightVector(env, key_array_model, values_m, values_m_len, &model); - model.SetNormalizer(normalizer_model); - classifier->LoadWeights(model); - env->ReleaseFloatArrayElements(value_array_model, values_m, JNI_ABORT); - return JNI_TRUE; - } - } - return JNI_FALSE; -} - -jboolean Java_android_bordeaux_learning_StochasticLinearRanker_nativeSetParameterClassifier( - JNIEnv* env, - jobject /* thiz */, - jstring key, - jstring value, - jlong paPtr) { - - StochasticLinearRanker* classifier = (StochasticLinearRanker*) paPtr; - jboolean iscopy; - const char *cKey = env->GetStringUTFChars(key, &iscopy); - const char *cValue = env->GetStringUTFChars(value, &iscopy); - float v; - if (strcmp(cKey, ITR_NUM) == 0){ - sscanf(cValue, "%f", &v); - classifier->SetIterationNumber((uint64) v); - return JNI_TRUE; - } - else if (strcmp(cKey, NORM_CONSTRAINT) == 0){ - sscanf(cValue, "%f", &v); - classifier->SetNormConstraint((double) v); - return JNI_TRUE; - } - else if (strcmp(cKey, REG_TYPE) == 0){ - if (strcmp(cValue, REG_TYPE_L0 ) == 0) - classifier->SetRegularizationType(learning_stochastic_linear::L0); - else if (strcmp(cValue, REG_TYPE_L1 ) == 0) - classifier->SetRegularizationType(learning_stochastic_linear::L1); - else if (strcmp(cValue, REG_TYPE_L2 ) == 0) - classifier->SetRegularizationType(learning_stochastic_linear::L2); - else if (strcmp(cValue, REG_TYPE_L1L2 ) == 0) - classifier->SetRegularizationType(learning_stochastic_linear::L1L2); - else if (strcmp(cValue, REG_TYPE_L1LInf ) == 0) - classifier->SetRegularizationType(learning_stochastic_linear::L1LInf); - else { - ALOGE("Error: %s is not a Regularization Type", cValue); - return JNI_FALSE; - } - return JNI_TRUE; - } - else if (strcmp(cKey, LAMBDA) == 0){ - sscanf(cValue, "%f", &v); - classifier->SetLambda((double) v); - return JNI_TRUE; - } - else if (strcmp(cKey, UPDATE_TYPE) == 0){ - if (strcmp(cValue, UPDATE_TYPE_FULL_CS) == 0) - classifier->SetUpdateType(learning_stochastic_linear::FULL_CS); - else if (strcmp(cValue, UPDATE_TYPE_CLIP_CS) == 0) - classifier->SetUpdateType(learning_stochastic_linear::CLIP_CS); - else if (strcmp(cValue, UPDATE_TYPE_REG_CS ) == 0) - classifier->SetUpdateType(learning_stochastic_linear::REG_CS); - else if (strcmp(cValue, UPDATE_TYPE_SL) == 0) - classifier->SetUpdateType(learning_stochastic_linear::SL); - else if (strcmp(cValue, UPDATE_TYPE_ADAPTIVE_REG) == 0) - classifier->SetUpdateType(learning_stochastic_linear::ADAPTIVE_REG); - else { - ALOGE("Error: %s is not an Update Type", cValue); - return JNI_FALSE; - } - return JNI_TRUE; - } - else if (strcmp(cKey, ADAPT_MODE) == 0){ - if (strcmp(cValue, ADAPT_MODE_CONST ) == 0) - classifier->SetAdaptationMode(learning_stochastic_linear::CONST); - else if (strcmp(cValue, ADAPT_MODE_INV_LINEAR ) == 0) - classifier->SetAdaptationMode(learning_stochastic_linear::INV_LINEAR); - else if (strcmp(cValue, ADAPT_MODE_INV_QUADRATIC ) == 0) - classifier->SetAdaptationMode(learning_stochastic_linear::INV_QUADRATIC); - else if (strcmp(cValue, ADAPT_MODE_INV_SQRT ) == 0) - classifier->SetAdaptationMode(learning_stochastic_linear::INV_SQRT); - else { - ALOGE("Error: %s is not an Adaptation Mode", cValue); - return JNI_FALSE; - } - return JNI_TRUE; - } - else if (strcmp(cKey, KERNEL_TYPE) == 0){ - if (strcmp(cValue, KERNEL_TYPE_LINEAR ) == 0) - classifier->SetKernelType(learning_stochastic_linear::LINEAR); - else if (strcmp(cValue, KERNEL_TYPE_POLY ) == 0) - classifier->SetKernelType(learning_stochastic_linear::POLY); - else if (strcmp(cValue, KERNEL_TYPE_RBF ) == 0) - classifier->SetKernelType(learning_stochastic_linear::RBF); - else { - ALOGE("Error: %s is not a Kernel Type", cValue); - return JNI_FALSE; - } - return JNI_TRUE; - } - else if (strcmp(cKey, KERNEL_PARAM) == 0){ - sscanf(cValue, "%f", &v); - classifier->SetKernelParam((double) v); - return JNI_TRUE; - } - else if (strcmp(cKey, KERNEL_GAIN) == 0){ - sscanf(cValue, "%f", &v); - classifier->SetKernelGain((double) v); - return JNI_TRUE; - } - else if (strcmp(cKey, KERNEL_BIAS) == 0){ - sscanf(cValue, "%f", &v); - classifier->SetKernelBias((double) v); - return JNI_TRUE; - } - else if (strcmp(cKey, LOSS_TYPE) == 0){ - if (strcmp(cValue, LOSS_TYPE_PAIRWISE ) == 0) - classifier->SetRankLossType(learning_stochastic_linear::PAIRWISE); - else if (strcmp(cValue, LOSS_TYPE_RECIPROCAL_RANK ) == 0) - classifier->SetRankLossType(learning_stochastic_linear::RECIPROCAL_RANK); - else { - ALOGE("Error: %s is not a Kernel Type", cValue); - return JNI_FALSE; - } - return JNI_TRUE; - } - else if (strcmp(cKey, ACC_PROB) == 0){ - sscanf(cValue, "%f", &v); - classifier->SetAcceptanceProbability((double) v); - return JNI_TRUE; - } - else if (strcmp(cKey, MIN_BATCH_SIZE) == 0){ - sscanf(cValue, "%f", &v); - classifier->SetMiniBatchSize((uint64) v); - return JNI_TRUE; - } - else if (strcmp(cKey, GRAD_L0_NORM) == 0){ - sscanf(cValue, "%f", &v); - classifier->SetGradientL0Norm((int32) v); - return JNI_TRUE; - } - ALOGE("Error: %s is not a ranker parameter", cKey); - return JNI_FALSE; -} - -jint Java_android_bordeaux_learning_StochasticLinearRanker_nativeGetLengthClassifier( - JNIEnv* /* env */, - jobject /* thiz */, - jlong paPtr) { - - StochasticLinearRanker* classifier = (StochasticLinearRanker*) paPtr; - SparseWeightVector M_weights; - classifier->SaveWeights(&M_weights); - - SparseWeightVector::Wmap w_map = M_weights.GetMap(); - int len = w_map.size(); - return len; -} - -std::string ConvertFloat2String(float v){ - std::stringstream converter; - converter << v; - return converter.str(); -} - -void Java_android_bordeaux_learning_StochasticLinearRanker_nativeGetParameterClassifier( - JNIEnv* env, - jobject /* thiz */, - jobjectArray key_array_param, - jobjectArray value_array_param, - jlong paPtr){ - - std::string s; - StochasticLinearRanker* classifier = (StochasticLinearRanker*) paPtr; - s = ConvertFloat2String((float) classifier->GetIterationNumber()); - ConvertParameter2Object(env, &key_array_param, &value_array_param, ITR_NUM, s.c_str(), 0 ); - - s = ConvertFloat2String((float) classifier->GetNormContraint()); - ConvertParameter2Object(env, &key_array_param, &value_array_param, NORM_CONSTRAINT, s.c_str(), 1 ); - - float value = (float) classifier->GetRegularizationType(); - switch ((int) value) { - case learning_stochastic_linear::L0 : - s = REG_TYPE_L0; - break; - case learning_stochastic_linear::L1 : - s = REG_TYPE_L1; - break; - case learning_stochastic_linear::L2 : - s = REG_TYPE_L2; - break; - case learning_stochastic_linear::L1L2 : - s = REG_TYPE_L1L2; - break; - case learning_stochastic_linear::L1LInf : - s = REG_TYPE_L1LInf; - break; - } - ConvertParameter2Object(env, &key_array_param, &value_array_param, REG_TYPE, s.c_str(), 2 ); - - s = ConvertFloat2String((float) classifier->GetLambda()); - ConvertParameter2Object(env, &key_array_param, &value_array_param, LAMBDA, s.c_str(), 3 ); - - value = (float) classifier->GetUpdateType(); - switch ((int) value) { - case learning_stochastic_linear::FULL_CS : - s = UPDATE_TYPE_FULL_CS; - break; - case learning_stochastic_linear::CLIP_CS : - s = UPDATE_TYPE_CLIP_CS; - break; - case learning_stochastic_linear::REG_CS : - s = UPDATE_TYPE_REG_CS; - break; - case learning_stochastic_linear::SL : - s = UPDATE_TYPE_SL; - break; - case learning_stochastic_linear::ADAPTIVE_REG : - s = UPDATE_TYPE_ADAPTIVE_REG; - break; - } - ConvertParameter2Object(env, &key_array_param, &value_array_param, UPDATE_TYPE, s.c_str(), 4 ); - - value = (float) classifier->GetAdaptationMode(); - switch ((int) value) { - case learning_stochastic_linear::CONST : - s = ADAPT_MODE_CONST; - break; - case learning_stochastic_linear::INV_LINEAR : - s = ADAPT_MODE_INV_LINEAR; - break; - case learning_stochastic_linear::INV_QUADRATIC : - s = ADAPT_MODE_INV_QUADRATIC; - break; - case learning_stochastic_linear::INV_SQRT : - s = ADAPT_MODE_INV_SQRT; - break; - } - ConvertParameter2Object(env, &key_array_param, &value_array_param, ADAPT_MODE, s.c_str(), 5 ); - - value = (float) classifier->GetKernelType(); - switch ((int) value) { - case learning_stochastic_linear::LINEAR : - s = KERNEL_TYPE_LINEAR; - break; - case learning_stochastic_linear::POLY : - s = KERNEL_TYPE_POLY; - break; - case learning_stochastic_linear::RBF : - s = KERNEL_TYPE_RBF; - break; - } - ConvertParameter2Object(env, &key_array_param, &value_array_param, KERNEL_TYPE, s.c_str(), 6 ); - - s = ConvertFloat2String((float) classifier->GetKernelParam()); - ConvertParameter2Object(env, &key_array_param, &value_array_param, KERNEL_PARAM, s.c_str(), 7 ); - - s = ConvertFloat2String((float) classifier->GetKernelGain()); - ConvertParameter2Object(env, &key_array_param, &value_array_param, KERNEL_GAIN, s.c_str(), 8 ); - - s = ConvertFloat2String((float)classifier->GetKernelBias()); - ConvertParameter2Object(env, &key_array_param, &value_array_param, KERNEL_BIAS, s.c_str(), 9 ); - - value = (float) classifier->GetRankLossType(); - switch ((int) value) { - case learning_stochastic_linear::PAIRWISE : - s = LOSS_TYPE_PAIRWISE; - break; - case learning_stochastic_linear::RECIPROCAL_RANK : - s = LOSS_TYPE_RECIPROCAL_RANK; - break; - } - ConvertParameter2Object(env, &key_array_param, &value_array_param, LOSS_TYPE, s.c_str(), 10 ); - - s = ConvertFloat2String((float) classifier->GetAcceptanceProbability()); - ConvertParameter2Object(env, &key_array_param, &value_array_param, ACC_PROB, s.c_str(), 11 ); - - s = ConvertFloat2String((float) classifier->GetMiniBatchSize()); - ConvertParameter2Object(env, &key_array_param, &value_array_param, MIN_BATCH_SIZE, s.c_str(), 12 ); - - s = ConvertFloat2String((float) classifier->GetGradientL0Norm()); - ConvertParameter2Object(env, &key_array_param, &value_array_param, GRAD_L0_NORM, s.c_str(), 13 ); -} - -void Java_android_bordeaux_learning_StochasticLinearRanker_nativeGetWeightClassifier( - JNIEnv* env, - jobject /* thiz */, - jobjectArray key_array_model, - jfloatArray value_array_model, - jfloat /* normalizer */, - jlong paPtr) { - - StochasticLinearRanker* classifier = (StochasticLinearRanker*) paPtr; - SparseWeightVector M_weights; - classifier->SaveWeights(&M_weights); - SparseWeightVector::Wmap w_map = M_weights.GetMap(); - DecomposeSparseWeightVector(env, &key_array_model, &value_array_model, &M_weights); -} - -jlong Java_android_bordeaux_learning_StochasticLinearRanker_initNativeClassifier( - JNIEnv* /* env */, - jobject /* thiz */) { - StochasticLinearRanker* classifier = new StochasticLinearRanker(); - return ((jlong) classifier); -} - -jboolean Java_android_bordeaux_learning_StochasticLinearRanker_deleteNativeClassifier( - JNIEnv* /* env */, - jobject /* thiz */, - jlong paPtr) { - StochasticLinearRanker* classifier = (StochasticLinearRanker*) paPtr; - delete classifier; - return JNI_TRUE; -} - -jboolean Java_android_bordeaux_learning_StochasticLinearRanker_nativeUpdateClassifier( - JNIEnv* env, - jobject /* thiz */, - jobjectArray key_array_positive, - jfloatArray value_array_positive, - jobjectArray key_array_negative, - jfloatArray value_array_negative, - jlong paPtr) { - StochasticLinearRanker* classifier = (StochasticLinearRanker*) paPtr; - - if (classifier && key_array_positive && value_array_positive && - key_array_negative && value_array_negative) { - - const int keys_p_len = env->GetArrayLength(key_array_positive); - jfloat* values_p = env->GetFloatArrayElements(value_array_positive, NULL); - const int values_p_len = env->GetArrayLength(value_array_positive); - jfloat* values_n = env->GetFloatArrayElements(value_array_negative, NULL); - const int values_n_len = env->GetArrayLength(value_array_negative); - const int keys_n_len = env->GetArrayLength(key_array_negative); - - if (values_p && key_array_positive && values_p_len == keys_p_len && - values_n && key_array_negative && values_n_len == keys_n_len) { - - SparseWeightVector sample_pos; - SparseWeightVector sample_neg; - CreateSparseWeightVector(env, key_array_positive, values_p, values_p_len, &sample_pos); - CreateSparseWeightVector(env, key_array_negative, values_n, values_n_len, &sample_neg); - classifier->UpdateClassifier(sample_pos, sample_neg); - env->ReleaseFloatArrayElements(value_array_negative, values_n, JNI_ABORT); - env->ReleaseFloatArrayElements(value_array_positive, values_p, JNI_ABORT); - - return JNI_TRUE; - } - env->ReleaseFloatArrayElements(value_array_negative, values_n, JNI_ABORT); - env->ReleaseFloatArrayElements(value_array_positive, values_p, JNI_ABORT); - } - return JNI_FALSE; -} - -jfloat Java_android_bordeaux_learning_StochasticLinearRanker_nativeScoreSample( - JNIEnv* env, - jobject /* thiz */, - jobjectArray key_array, - jfloatArray value_array, - jlong paPtr) { - - StochasticLinearRanker* classifier = (StochasticLinearRanker*) paPtr; - - if (classifier && key_array && value_array) { - - jfloat* values = env->GetFloatArrayElements(value_array, NULL); - const int values_len = env->GetArrayLength(value_array); - const int keys_len = env->GetArrayLength(key_array); - - if (values && key_array && values_len == keys_len) { - SparseWeightVector sample; - CreateSparseWeightVector(env, key_array, values, values_len, &sample); - env->ReleaseFloatArrayElements(value_array, values, JNI_ABORT); - return classifier->ScoreSample(sample); - } - } - return -1; -} diff --git a/bordeaux/learning/stochastic_linear_ranker/jni/jni_stochastic_linear_ranker.h b/bordeaux/learning/stochastic_linear_ranker/jni/jni_stochastic_linear_ranker.h deleted file mode 100644 index fd187b009..000000000 --- a/bordeaux/learning/stochastic_linear_ranker/jni/jni_stochastic_linear_ranker.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LEARNING_JNI_STOCHASTIC_LINEAR_RANKER_H -#define LEARNING_JNI_STOCHASTIC_LINEAR_RANKER_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Counts the number of learning iterations. */ -const char * ITR_NUM = "IterationNumber"; - -/* The maximum norm of the weight vector. If norm of weights are larger than NormConstraint - they will be reprojected using RegularizationType to satisfy this constraint. */ -const char * NORM_CONSTRAINT = "NormConstraint"; - -/* Ddetermines type of the regularization used in learning. - This regularization can be based on different norms. - Options: "L0", "L1", "L2", "L1L2", "L1LInf". - Default : LINEAR */ -const char * REG_TYPE = "RegularizationType"; - -/* Lambda is a factor that is multiplied with the step size in learning. This can be used - to change the step size. - Default : 1.0 */ -const char * LAMBDA = "Lambda"; - -/* This parameter determines the update type in learning process. - Options: "FULL_CS" , "CLIP_CS", "REG_CS", "SL", "ADAPTIVE_REG" - Default : "SL" */ -const char * UPDATE_TYPE = "UpdateType"; - -/* Options: "CONST", "INV_LINEAR", "INV_QUADRATIC", "INV_SQRT" - Default: "INV_LINEAR". */ -const char * ADAPT_MODE = "AdaptationMode"; - -/* Three differnt kernels are supported: Linear "LINEAR", Polynomial "POLY", and RBF "RBF" - Default : "LINEAR" */ -const char * KERNEL_TYPE = "KernelType"; - -/* Kernel param is kernel-specific. In case of polynomial kernel, it is the degree of the - polynomial. In case of RBF kernel, it implies the sigma parameter. In case of linear - kernel, it is not used. */ -const char * KERNEL_PARAM = "KernelParameter"; - -/* Kernel gain is typically a multiplicative factor to the dot product while calculating - the kernel function. In most use cases, gain should be set to 1.0. */ -const char * KERNEL_GAIN = "KernelGain"; - -/* Kernel bias is typically an additive factors to the dot product while calculating - the kernel function. In most use cases, bias should be set to 0.0. */ -const char * KERNEL_BIAS = "KernelBias"; - -/* This parameter determines the type of loss function to minimize. - Options : "PAIRWISE", "RECIPROCAL_RANK" - Default : "PAIRWISE" */ -const char * LOSS_TYPE = "LossType"; - -/* The minimum percent of training pairs that are used in training. - Default : "0.1" */ -const char * ACC_PROB = "AcceptaceProbability"; - -/* The code averages out gradient updates for MinimumBatchSize samples - before performing an iteration of the algorithm. */ -const char * MIN_BATCH_SIZE = "MinimumBatchSize"; - -/* Specifies the number of non-zero entries allowed in a gradient. - Default is -1 which means we take the gradient as given by data without - adding any new constraints. positive number is treated as an L0 constraint */ -const char * GRAD_L0_NORM = "GradientL0Nrom"; - -const char * REG_TYPE_L0 = "L0"; -const char * REG_TYPE_L1 = "L1"; -const char * REG_TYPE_L2 = "L2"; -const char * REG_TYPE_L1L2 = "L1L2"; -const char * REG_TYPE_L1LInf = "L1LInf"; -const char * UPDATE_TYPE_FULL_CS = "FULL_CS"; -const char * UPDATE_TYPE_CLIP_CS = "CLIP_CS"; -const char * UPDATE_TYPE_REG_CS = "REG_CS"; -const char * UPDATE_TYPE_SL = "SL"; -const char * UPDATE_TYPE_ADAPTIVE_REG = "ADAPTIVE_REG"; -const char * ADAPT_MODE_CONST = "CONST"; -const char * ADAPT_MODE_INV_LINEAR = "INV_LINEAR"; -const char * ADAPT_MODE_INV_QUADRATIC = "INV_QUADRATIC"; -const char * ADAPT_MODE_INV_SQRT = "INV_SQRT"; -const char * KERNEL_TYPE_LINEAR = "LINEAR"; -const char * KERNEL_TYPE_POLY = "POLY"; -const char * KERNEL_TYPE_RBF = "RBF"; -const char * LOSS_TYPE_PAIRWISE = "PAIRWISE"; -const char * LOSS_TYPE_RECIPROCAL_RANK = "RECIPROCAL_RANK"; - -JNIEXPORT jlong JNICALL -Java_android_bordeaux_learning_StochasticLinearRanker_initNativeClassifier( - JNIEnv* env, - jobject thiz); - - -JNIEXPORT jboolean JNICALL -Java_android_bordeaux_learning_StochasticLinearRanker_deleteNativeClassifier( - JNIEnv* env, - jobject thiz, - jlong paPtr); - -JNIEXPORT jboolean JNICALL -Java_android_bordeaux_learning_StochasticLinearRanker_nativeUpdateClassifier( - JNIEnv* env, - jobject thiz, - jobjectArray key_array_positive, - jfloatArray value_array_positive, - jobjectArray key_array_negative, - jfloatArray value_array_negative, - jlong paPtr); - -JNIEXPORT jfloat JNICALL -Java_android_bordeaux_learning_StochasticLinearRanker_nativeScoreSample( - JNIEnv* env, - jobject thiz, - jobjectArray key_array, - jfloatArray value_array, - jlong paPtr); - -JNIEXPORT void JNICALL -Java_android_bordeaux_learning_StochasticLinearRanker_nativeGetWeightClassifier( - JNIEnv* env, - jobject thiz, - jobjectArray key_array_weight, - jfloatArray value_array_weight, - jfloat normalizer, - jlong paPtr); - -JNIEXPORT void JNICALL -Java_android_bordeaux_learning_StochasticLinearRanker_nativeGetParameterClassifier( - JNIEnv* env, - jobject thiz, - jobjectArray key_array_param, - jobjectArray value_array_param, - jlong paPtr); - -JNIEXPORT jint JNICALL -Java_android_bordeaux_learning_StochasticLinearRanker_nativeGetLengthClassifier( - JNIEnv* env, - jobject thiz, - jlong paPtr); - -JNIEXPORT jboolean JNICALL -Java_android_bordeaux_learning_StochasticLinearRanker_nativeSetWeightClassifier( - JNIEnv* env, - jobject thiz, - jobjectArray key_array_model, - jfloatArray value_array_model, - jfloat normalizer_model, - jlong paPtr); - -JNIEXPORT jboolean JNICALL -Java_android_bordeaux_learning_StochasticLinearRanker_nativeSetParameterClassifier( - JNIEnv* env, - jobject thiz, - jstring key, - jstring value, - jlong paPtr); - -#ifdef __cplusplus -} -#endif - -#endif /* ANDROID_LEARNING_JNI_STOCHASTIC_LINEAR_RANKER_H */ diff --git a/bordeaux/learning/stochastic_linear_ranker/native/common_defs.h b/bordeaux/learning/stochastic_linear_ranker/native/common_defs.h deleted file mode 100644 index 4df8686c5..000000000 --- a/bordeaux/learning/stochastic_linear_ranker/native/common_defs.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// Contains definitions commom to all classification and ranking algorithms -// in this package. - -#ifndef LEARNING_STOCHASTIC_LINEAR_COMMON_DEFS_H_ -#define LEARNING_STOCHASTIC_LINEAR_COMMON_DEFS_H_ - -namespace learning_stochastic_linear { -// Defines standard types of regulariation methods. -enum RegularizationType { L0, L1, L2, L1L2, L1LInf }; - -// Defines standard adaptation modes for which Stochastic Sub-Gradient -// methods are known to converge. -enum AdaptationMode { CONST, INV_LINEAR, INV_QUADRATIC, INV_SQRT }; -enum UpdateType { FULL_CS, CLIP_CS, REG_CS, SL, ADAPTIVE_REG }; -enum RankLossType { PAIRWISE, RECIPROCAL_RANK }; -enum KernelType { LINEAR, POLY, RBF }; -enum MulticlassUpdateType { MAX, RANK }; -} // namespace learning_stochastic_linear - -#ifdef ANDROID -#define uint32 uint32_t -#define int32 int32_t -#define uint64 uint64_t -#define int64 int64_t -#include -#define CHECK_GT(x,y) if ((x)<(y)) ALOGE("CHECK_GT failed at file %s line %d", \ - __FILE__, __LINE__); -#endif - -#endif // LEARNING_STOCHASTIC_LINEAR_COMMON_DEFS_H_ diff --git a/bordeaux/learning/stochastic_linear_ranker/native/learning_rate_controller-inl.h b/bordeaux/learning/stochastic_linear_ranker/native/learning_rate_controller-inl.h deleted file mode 100644 index 8aa01f00b..000000000 --- a/bordeaux/learning/stochastic_linear_ranker/native/learning_rate_controller-inl.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// Implements learning rate adaptations common to most stochastic algorithms. - -#ifndef LEARNING_STOCHASTIC_LINEAR_LEARNING_RATE_CONTROLLER_INL_H_ -#define LEARNING_STOCHASTIC_LINEAR_LEARNING_RATE_CONTROLLER_INL_H_ - -#include -#include "common_defs.h" - -namespace learning_stochastic_linear { - -class LearningRateController { - public: - LearningRateController() { - iteration_num_ = 1; - lambda_ = 1.0; - mini_batch_size_ = 1; - mini_batch_counter_ = 1; - sample_num_ = 1; - mode_ = INV_LINEAR; - is_first_sample_ = true; - } - ~LearningRateController() {} - // Getters and Setters for learning rate parameter lambda_ - double GetLambda() const { - return lambda_; - } - void SetLambda(double lambda) { - lambda_ = lambda; - } - // Operations on current iteration number - void SetIterationNumber(uint64 num) { - iteration_num_ = num; - } - void IncrementIteration() { - ++iteration_num_; - } - uint64 GetIterationNumber() const { - return iteration_num_; - } - // Mini batch operations - uint64 GetMiniBatchSize() const { - return mini_batch_size_; - } - void SetMiniBatchSize(uint64 size) { - //CHECK_GT(size, 0); - mini_batch_size_ = size; - } - void IncrementSample() { - // If this is the first sample we've already counted it to prevent NaNs - // in the learning rate computation - if (is_first_sample_) { - is_first_sample_ = false; - return; - } - ++sample_num_; - if (1 == mini_batch_size_) { - IncrementIteration(); - mini_batch_counter_ = 0; - } else { - ++mini_batch_counter_; - if ((mini_batch_counter_ % mini_batch_size_ == 0)) { - IncrementIteration(); - mini_batch_counter_ = 0; - } - } - } - uint64 GetMiniBatchCounter() const { - return mini_batch_counter_; - } - // Getters and setters for adaptation mode - AdaptationMode GetAdaptationMode() const { - return mode_; - } - void SetAdaptationMode(AdaptationMode m) { - mode_ = m; - } - double GetLearningRate() const { - if (mode_ == CONST) { - return (1.0 / (lambda_ * mini_batch_size_)); - } else if (mode_ == INV_LINEAR) { - return (1.0 / (lambda_ * iteration_num_ * mini_batch_size_)); - } else if (mode_ == INV_QUADRATIC) { - return (1.0 / (lambda_ * - mini_batch_size_ * - (static_cast(iteration_num_) * iteration_num_))); - } else if (mode_ == INV_SQRT) { - return (1.0 / (lambda_ * - mini_batch_size_ * - sqrt((double)iteration_num_))); - } - return 0; - } - void CopyFrom(const LearningRateController &other) { - iteration_num_ = other.iteration_num_; - sample_num_ = other.sample_num_; - mini_batch_size_ = other.mini_batch_size_; - mini_batch_counter_ = other.mini_batch_counter_; - mode_ = other.mode_; - is_first_sample_ = other.is_first_sample_; - } - private: - uint64 iteration_num_; - uint64 sample_num_; - uint64 mini_batch_size_; - uint64 mini_batch_counter_; - double lambda_; - AdaptationMode mode_; - bool is_first_sample_; -}; -} // namespace learning_stochastic_linear -#endif // LEARNING_STOCHASTIC_LINEAR_LEARNING_RATE_CONTROLLER_INL_H_ diff --git a/bordeaux/learning/stochastic_linear_ranker/native/sparse_weight_vector.cpp b/bordeaux/learning/stochastic_linear_ranker/native/sparse_weight_vector.cpp deleted file mode 100644 index 52ce11853..000000000 --- a/bordeaux/learning/stochastic_linear_ranker/native/sparse_weight_vector.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "sparse_weight_vector.h" - -#include -#include -#include -#include - -using std::vector; -using std::list; -using std::max; - -namespace learning_stochastic_linear { - -// Max/Min permitted values of normalizer_ for preventing under/overflows. -static double kNormalizerMin = 1e-20; -static double kNormalizerMax = 1e20; - -template -bool SparseWeightVector::IsValid() const { - if (isnan(normalizer_) || __isinff(normalizer_)) - return false; - for (Witer_const iter = w_.begin(); - iter != w_.end(); - ++iter) { - if (isnanf(iter->second) || __isinff(iter->second)) - return false; - } - return true; -} - -template -void SparseWeightVector::AdditiveWeightUpdate( - const double multiplier, - const SparseWeightVector &w1, - const double additive_const) { - for (Witer_const iter = w1.w_.begin(); - iter != w1.w_.end(); - ++iter) { - w_[iter->first] += ((multiplier * iter->second) / w1.normalizer_ - + additive_const) * normalizer_; - } - return; -} - -template -void SparseWeightVector::AdditiveSquaredWeightUpdate( - const double multiplier, - const SparseWeightVector &w1, - const double additive_const) { - for (Witer_const iter = w1.w_.begin(); - iter != w1.w_.end(); - ++iter) { - w_[iter->first] += ((multiplier * iter->second * iter->second) / - (w1.normalizer_ * w1.normalizer_) - + additive_const) * normalizer_; - } - return; -} - -template -void SparseWeightVector::AdditiveInvSqrtWeightUpdate( - const double multiplier, - const SparseWeightVector &w1, - const double additive_const) { - for (Witer_const iter = w1.w_.begin(); - iter != w1.w_.end(); - ++iter) { - if(iter->second > 0.0) { - w_[iter->first] += ((multiplier * sqrt(w1.normalizer_)) / - (sqrt(iter->second)) - + additive_const) * normalizer_; - } - } - return; -} - -template -void SparseWeightVector::AdditiveWeightUpdateBounded( - const double multiplier, - const SparseWeightVector &w1, - const double additive_const) { - double min_bound = 0; - double max_bound = 0; - for (Witer_const iter = w1.w_.begin(); - iter != w1.w_.end(); - ++iter) { - w_[iter->first] += ((multiplier * iter->second) / w1.normalizer_ - + additive_const) * normalizer_; - bool is_min_bounded = GetValue(wmin_, iter->first, &min_bound); - if (is_min_bounded) { - if ((w_[iter->first] / normalizer_) < min_bound) { - w_[iter->first] = min_bound*normalizer_; - continue; - } - } - bool is_max_bounded = GetValue(wmax_, iter->first, &max_bound); - if (is_max_bounded) { - if ((w_[iter->first] / normalizer_) > max_bound) - w_[iter->first] = max_bound*normalizer_; - } - } - return; -} - -template -void SparseWeightVector::MultWeightUpdate( - const SparseWeightVector &w1) { - for (Witer iter = w_.begin(); - iter != w_.end(); - ++iter) { - iter->second *= w1.GetElement(iter->first); - } - normalizer_ *= w1.normalizer_; - return; -} - -template -void SparseWeightVector::MultWeightUpdateBounded( - const SparseWeightVector &w1) { - double min_bound = 0; - double max_bound = 0; - - normalizer_ *= w1.normalizer_; - for (Witer iter = w_.begin(); - iter != w_.end(); - ++iter) { - iter->second *= w1.GetElement(iter->first); - bool is_min_bounded = GetValue(wmin_, iter->first, &min_bound); - if (is_min_bounded) { - if ((iter->second / normalizer_) < min_bound) { - iter->second = min_bound*normalizer_; - continue; - } - } - bool is_max_bounded = GetValue(wmax_, iter->first, &max_bound); - if (is_max_bounded) { - if ((iter->second / normalizer_) > max_bound) - iter->second = max_bound*normalizer_; - } - } - return; -} - -template -void SparseWeightVector::ResetNormalizer() { - for (Witer iter = w_.begin(); - iter != w_.end(); - ++iter) { - iter->second /= normalizer_; - } - normalizer_ = 1.0; -} - -template -void SparseWeightVector::ReprojectToBounds() { - double min_bound = 0; - double max_bound = 0; - - for (Witer iter = w_.begin(); - iter != w_.end(); - ++iter) { - bool is_min_bounded = GetValue(wmin_, iter->first, &min_bound); - if (is_min_bounded) { - if ((iter->second/normalizer_) < min_bound) { - iter->second = min_bound*normalizer_; - continue; - } - } - bool is_max_bounded = GetValue(wmax_, iter->first, &max_bound); - if (is_max_bounded) { - if ((iter->second/normalizer_) > max_bound) - iter->second = max_bound*normalizer_; - } - } -} - -template -double SparseWeightVector::DotProduct( - const SparseWeightVector &w1) const { - double result = 0; - if (w_.size() > w1.w_.size()) { - for (Witer_const iter = w1.w_.begin(); - iter != w1.w_.end(); - ++iter) { - result += iter->second * GetElement(iter->first); - } - result /= (this->normalizer_ * w1.normalizer_); - } else { - for (Witer_const iter = w_.begin(); - iter != w_.end(); - ++iter) { - result += iter->second * w1.GetElement(iter->first); - } - result /= (this->normalizer_ * w1.normalizer_); - } - return result; -} - -template -double SparseWeightVector::LxNorm(const double x) const { - double result = 0; - CHECK_GT(x, 0); - for (Witer_const iter = w_.begin(); - iter != w_.end(); - ++iter) { - result += pow(iter->second, x); - } - return (pow(result, 1.0 / x) / normalizer_); -} - -template -double SparseWeightVector::L2Norm() const { - double result = 0; - for (Witer_const iter = w_.begin(); - iter != w_.end(); - ++iter) { - result += iter->second * iter->second; - } - return sqrt(result)/normalizer_; -} - -template -double SparseWeightVector::L1Norm() const { - double result = 0; - for (Witer_const iter = w_.begin(); - iter != w_.end(); - ++iter) { - result += fabs(iter->second); - } - return result / normalizer_; -} - -template -double SparseWeightVector::L0Norm( - const double epsilon) const { - double result = 0; - for (Witer_const iter = w_.begin(); - iter != w_.end(); - ++iter) { - if (fabs(iter->second / normalizer_) > epsilon) - ++result; - } - return result; -} - -// Algorithm for L0 projection which takes O(n log(n)), where n is -// the number of non-zero elements in the vector. -template -void SparseWeightVector::ReprojectL0(const double l0_norm) { -// First calculates the order-statistics of the sparse vector -// and then reprojects to the L0 orthant with the requested norm. - CHECK_GT(l0_norm, 0); - uint64 req_l0_norm = static_cast(l0_norm); - // Compute order statistics and the current L0 norm. - vector abs_val_vec; - uint64 curr_l0_norm = 0; - const double epsilone = 1E-05; - for (Witer iter = w_.begin(); - iter != w_.end(); - ++iter) { - if (fabs(iter->second/normalizer_) > epsilone) { - abs_val_vec.push_back(fabs(iter->second/normalizer_)); - ++curr_l0_norm; - } - } - // check if a projection is necessary - if (curr_l0_norm < req_l0_norm) { - return; - } - std::nth_element(&abs_val_vec[0], - &abs_val_vec[curr_l0_norm - req_l0_norm], - &abs_val_vec[curr_l0_norm]); - const double theta = abs_val_vec[curr_l0_norm - req_l0_norm]; - // compute the final projection. - for (Witer iter = w_.begin(); - iter != w_.end(); - ++iter) { - if ((fabs(iter->second/normalizer_) - theta) < 0) { - iter->second = 0; - } - } -} - -// Slow algorithm for accurate L1 projection which takes O(n log(n)), where n is -// the number of non-zero elements in the vector. -template -void SparseWeightVector::ReprojectL1(const double l1_norm) { -// First calculates the order-statistics of the sparse vector -// applies a probability simplex projection to the abs(vector) -// and reprojects back to the original with the appropriate sign. -// For ref. see "Efficient Projections into the l1-ball for Learning -// in High Dimensions" - CHECK_GT(l1_norm, 0); - // Compute order statistics and the current L1 norm. - list abs_val_list; - double curr_l1_norm = 0; - for (Witer iter = w_.begin(); - iter != w_.end(); - ++iter) { - abs_val_list.push_back(fabs(iter->second/normalizer_)); - curr_l1_norm += fabs(iter->second/normalizer_); - } - // check if a projection is necessary - if (curr_l1_norm < l1_norm) { - return; - } - abs_val_list.sort(); - abs_val_list.reverse(); - // Compute projection on the probability simplex. - double curr_index = 1; - double theta = 0; - double cum_sum = 0; - for (list::iterator val_iter = abs_val_list.begin(); - val_iter != abs_val_list.end(); - ++val_iter) { - cum_sum += *val_iter; - theta = (cum_sum - l1_norm)/curr_index; - if (((*val_iter) - theta) <= 0) { - break; - } - ++curr_index; - } - // compute the final projection. - for (Witer iter = w_.begin(); - iter != w_.end(); - ++iter) { - int sign_mul = iter->second > 0; - iter->second = max(sign_mul * normalizer_ * - (fabs(iter->second/normalizer_) - theta), - 0.0); - } -} - -template -void SparseWeightVector::ReprojectL2(const double l2_norm) { - CHECK_GT(l2_norm, 0); - double curr_l2_norm = L2Norm(); - // Check if a projection is necessary. - if (curr_l2_norm > l2_norm) { - normalizer_ *= curr_l2_norm / l2_norm; - } -} - -template -int32 SparseWeightVector::Reproject(const double norm, - const RegularizationType r) { - CHECK_GT(norm, 0); - if (r == L0) { - ReprojectL0(norm); - } else if (r == L1) { - ReprojectL1(norm); - } else if (r == L2) { - ReprojectL2(norm); - } else { - // This else is just to ensure that if other RegularizationTypes are - // supported in the enum later which require manipulations not related - // to SparseWeightVector then we catch the accidental argument here. - ALOGE("Unsupported regularization type requested"); - return -1; - } - // If the normalizer gets dangerously large or small, normalize the - // entire vector. This stops projections from sending the vector - // weights and the normalizer simultaneously all very small or - // large, causing under/over flows. But if you hit this too often - // it's a sign you've chosen a bad lambda. - if (normalizer_ < kNormalizerMin) { - ALOGE("Resetting normalizer to 1.0 to prevent underflow. " - "Is lambda too large?"); - ResetNormalizer(); - } - if (normalizer_ > kNormalizerMax) { - ALOGE("Resetting normalizer to 1.0 to prevent overflow. " - "Is lambda too small?"); - ResetNormalizer(); - } - return 0; -} - -template class SparseWeightVector >; -template class SparseWeightVector >; -template class SparseWeightVector >; -} // namespace learning_stochastic_linear diff --git a/bordeaux/learning/stochastic_linear_ranker/native/sparse_weight_vector.h b/bordeaux/learning/stochastic_linear_ranker/native/sparse_weight_vector.h deleted file mode 100644 index b5f1ff5af..000000000 --- a/bordeaux/learning/stochastic_linear_ranker/native/sparse_weight_vector.h +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// Purpose: A container for sparse weight vectors -// Maintains the sparse vector as a list of (name, value) pairs alongwith -// a normalizer_. All operations assume that (name, value/normalizer_) is the -// true value in question. - -#ifndef LEARNING_STOCHASTIC_LINEAR_SPARSE_WEIGHT_VECTOR_H_ -#define LEARNING_STOCHASTIC_LINEAR_SPARSE_WEIGHT_VECTOR_H_ - -#include - -#include -#include -#include -#include - -#include "common_defs.h" - -namespace learning_stochastic_linear { - -template > -class SparseWeightVector { - public: - typedef Hash Wmap; - typedef typename Wmap::iterator Witer; - typedef typename Wmap::const_iterator Witer_const; - SparseWeightVector() { - normalizer_ = 1.0; - } - ~SparseWeightVector() {} - explicit SparseWeightVector(const SparseWeightVector &other) { - CopyFrom(other); - } - void operator=(const SparseWeightVector &other) { - CopyFrom(other); - } - void CopyFrom(const SparseWeightVector &other) { - w_ = other.w_; - wmin_ = other.wmin_; - wmax_ = other.wmax_; - normalizer_ = other.normalizer_; - } - - // This function implements checks to prevent unbounded vectors. It returns - // true if the checks succeed and false otherwise. A vector is deemed invalid - // if any of these conditions are met: - // 1. it has no values. - // 2. its normalizer is nan or inf or close to zero. - // 3. any of its values are nan or inf. - // 4. its L0 norm is close to zero. - bool IsValid() const; - - // Normalizer getters and setters. - double GetNormalizer() const { - return normalizer_; - } - void SetNormalizer(const double norm) { - normalizer_ = norm; - } - void NormalizerMultUpdate(const double mul) { - normalizer_ = normalizer_ * mul; - } - void NormalizerAddUpdate(const double add) { - normalizer_ += add; - } - - // Divides all the values by the normalizer, then it resets it to 1.0 - void ResetNormalizer(); - - // Bound getters and setters. - // True if there is a bound with val containing the bound. false otherwise. - bool GetElementMinBound(const Key &fname, double *val) const { - return GetValue(wmin_, fname, val); - } - bool GetElementMaxBound(const Key &fname, double *val) const { - return GetValue(wmax_, fname, val); - } - void SetElementMinBound(const Key &fname, const double bound) { - wmin_[fname] = bound; - } - void SetElementMaxBound(const Key &fname, const double bound) { - wmax_[fname] = bound; - } - // Element getters and setters. - double GetElement(const Key &fname) const { - double val = 0; - GetValue(w_, fname, &val); - return val; - } - void SetElement(const Key &fname, const double val) { - //DCHECK(!isnan(val)); - w_[fname] = val; - } - void AddUpdateElement(const Key &fname, const double val) { - w_[fname] += val; - } - void MultUpdateElement(const Key &fname, const double val) { - w_[fname] *= val; - } - // Load another weight vectors. Will overwrite the current vector. - void LoadWeightVector(const SparseWeightVector &vec) { - w_.clear(); - w_.insert(vec.w_.begin(), vec.w_.end()); - wmax_.insert(vec.wmax_.begin(), vec.wmax_.end()); - wmin_.insert(vec.wmin_.begin(), vec.wmin_.end()); - normalizer_ = vec.normalizer_; - } - void Clear() { - w_.clear(); - wmax_.clear(); - wmin_.clear(); - } - const Wmap& GetMap() const { - return w_; - } - // Vector Operations. - void AdditiveWeightUpdate(const double multiplier, - const SparseWeightVector &w1, - const double additive_const); - void AdditiveSquaredWeightUpdate(const double multiplier, - const SparseWeightVector &w1, - const double additive_const); - void AdditiveInvSqrtWeightUpdate(const double multiplier, - const SparseWeightVector &w1, - const double additive_const); - void MultWeightUpdate(const SparseWeightVector &w1); - double DotProduct(const SparseWeightVector &s) const; - // L-x norm. eg. L1, L2. - double LxNorm(const double x) const; - double L2Norm() const; - double L1Norm() const; - double L0Norm(const double epsilon) const; - // Bound preserving updates. - void AdditiveWeightUpdateBounded(const double multiplier, - const SparseWeightVector &w1, - const double additive_const); - void MultWeightUpdateBounded(const SparseWeightVector &w1); - void ReprojectToBounds(); - void ReprojectL0(const double l0_norm); - void ReprojectL1(const double l1_norm); - void ReprojectL2(const double l2_norm); - // Reproject using the given norm. - // Will also rescale regularizer_ if it gets too small/large. - int32 Reproject(const double norm, const RegularizationType r); - // Convert this vector to a string, simply for debugging. - std::string DebugString() const { - std::stringstream stream; - stream << *this; - return stream.str(); - } - private: - // The weight map. - Wmap w_; - // Constraint bounds. - Wmap wmin_; - Wmap wmax_; - // Normalizing constant in magnitude measurement. - double normalizer_; - // This function is necessary since by default unordered_map inserts an - // element if it does not find the key through [] operator. It implements a - // lookup without the space overhead of an add. - bool GetValue(const Wmap &w1, const Key &fname, double *val) const { - Witer_const iter = w1.find(fname); - if (iter != w1.end()) { - (*val) = iter->second; - return true; - } else { - (*val) = 0; - return false; - } - } -}; - -// Outputs a SparseWeightVector, for debugging. -template -std::ostream& operator<<(std::ostream &stream, - const SparseWeightVector &vector) { - typename SparseWeightVector::Wmap w_map = vector.GetMap(); - stream << "[[ "; - for (typename SparseWeightVector::Witer_const iter = w_map.begin(); - iter != w_map.end(); - ++iter) { - stream << "<" << iter->first << ", " << iter->second << "> "; - } - return stream << " ]]"; -}; - -} // namespace learning_stochastic_linear -#endif // LEARNING_STOCHASTIC_LINEAR_SPARSE_WEIGHT_VECTOR_H_ diff --git a/bordeaux/learning/stochastic_linear_ranker/native/stochastic_linear_ranker.cpp b/bordeaux/learning/stochastic_linear_ranker/native/stochastic_linear_ranker.cpp deleted file mode 100644 index db702ad57..000000000 --- a/bordeaux/learning/stochastic_linear_ranker/native/stochastic_linear_ranker.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include "stochastic_linear_ranker.h" - -namespace learning_stochastic_linear { - -template -void StochasticLinearRanker::UpdateSubGradient( - const SparseWeightVector &positive, - const SparseWeightVector &negative, - const double learning_rate, - const double positive_score, - const double negative_score, - const int32 gradient_l0_norm) { - SparseWeightVector gradient; - double final_learning_rate; - gradient.AdditiveWeightUpdate(1.0, positive, 0.0); - gradient.AdditiveWeightUpdate(-1.0, negative, 0.0); - if (update_type_ == FULL_CS || update_type_ == REG_CS) { - const double loss = std::max(0.0, (1 - positive_score + negative_score)); - const double gradient_norm = gradient.L2Norm(); - const double kMinGradientNorm = 1e-8; - const double kMaxGradientNorm = 1e8; - if (gradient_norm < kMinGradientNorm || gradient_norm > kMaxGradientNorm) - return; - if (update_type_ == FULL_CS) - final_learning_rate = - std::min(lambda_, loss / (gradient_norm * gradient_norm)); - else - final_learning_rate = - loss / (gradient_norm * gradient_norm + 1 / (2 * lambda_)); - } else { - gradient.AdditiveWeightUpdate(-lambda_, weight_, 0.0); - final_learning_rate = learning_rate; - } - if (gradient_l0_norm > 0) { - gradient.ReprojectL0(gradient_l0_norm); - } - - if (gradient.IsValid()) - weight_.AdditiveWeightUpdate(final_learning_rate, gradient, 0.0); -} - -template -int StochasticLinearRanker::UpdateClassifier( - const SparseWeightVector &positive, - const SparseWeightVector &negative) { - // Create a backup of the weight vector in case the iteration results in - // unbounded weights. - SparseWeightVector weight_backup; - weight_backup.CopyFrom(weight_); - - const double positive_score = ScoreSample(positive); - const double negative_score = ScoreSample(negative); - if ((positive_score - negative_score) < 1) { - ++mini_batch_counter_; - if ((mini_batch_counter_ % mini_batch_size_ == 0) || - (iteration_num_ == 0)) { - ++iteration_num_; - mini_batch_counter_ = 0; - } - learning_rate_controller_.IncrementSample(); - double learning_rate = learning_rate_controller_.GetLearningRate(); - - if (rank_loss_type_ == PAIRWISE) { - UpdateSubGradient(positive, negative, learning_rate, - positive_score, negative_score, - gradient_l0_norm_); - } else if (rank_loss_type_ == RECIPROCAL_RANK) { - const double current_negative_score = ScoreSample(current_negative_); - if ((negative_score > current_negative_score) || - ((rand()/RAND_MAX) < acceptence_probability_)) { - UpdateSubGradient(positive, negative, learning_rate, - positive_score, negative_score, - gradient_l0_norm_); - current_negative_.Clear(); - current_negative_.LoadWeightVector(negative); - } else { - UpdateSubGradient(positive, current_negative_, learning_rate, - positive_score, negative_score, - gradient_l0_norm_); - } - } else { - ALOGE("Unknown rank loss type: %d", rank_loss_type_); - } - - int return_code; - if ((mini_batch_counter_ == 0) && (update_type_ == SL)) { - return_code = 1; - switch (regularization_type_) { - case L1: - weight_.ReprojectL1(norm_constraint_); - break; - case L2: - weight_.ReprojectL2(norm_constraint_); - break; - case L0: - weight_.ReprojectL0(norm_constraint_); - break; - default: - ALOGE("Unsupported optimization type specified"); - return_code = -1; - } - } else if (update_type_ == SL) { - return_code = 2; - } else { - return_code = 1; - } - - if (!weight_.IsValid()) - weight_.CopyFrom(weight_backup); - return return_code; - } - - return 0; -} - -template class StochasticLinearRanker >; -template class StochasticLinearRanker >; -template class StochasticLinearRanker >; - -} // namespace learning_stochastic_linear diff --git a/bordeaux/learning/stochastic_linear_ranker/native/stochastic_linear_ranker.h b/bordeaux/learning/stochastic_linear_ranker/native/stochastic_linear_ranker.h deleted file mode 100644 index 5419a5a30..000000000 --- a/bordeaux/learning/stochastic_linear_ranker/native/stochastic_linear_ranker.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// Stochastic Linear Ranking algorithms. -// This class will implement a set of incremental algorithms for ranking tasks -// They support both L1 and L2 regularizations. - - -#ifndef LEARNING_STOCHASTIC_LINEAR_STOCHASTIC_LINEAR_RANKER_H_ -#define LEARNING_STOCHASTIC_LINEAR_STOCHASTIC_LINEAR_RANKER_H_ - -#include - -#include -#include -#include - -#include "cutils/log.h" -#include "common_defs.h" -#include "learning_rate_controller-inl.h" -#include "sparse_weight_vector.h" - -namespace learning_stochastic_linear { - -// NOTE: This Stochastic Linear Ranker supports only the following update types: -// SL: Stochastic Linear -// CS: Constraint Satisfaction -template > -class StochasticLinearRanker { - public: - // initialize lambda_ and constraint to a meaningful default. Will give - // equal weight to the error and regularizer. - StochasticLinearRanker() { - iteration_num_ = 0; - lambda_ = 1.0; - learning_rate_controller_.SetLambda(lambda_); - mini_batch_size_ = 1; - learning_rate_controller_.SetMiniBatchSize(mini_batch_size_); - adaptation_mode_ = INV_LINEAR; - learning_rate_controller_.SetAdaptationMode(adaptation_mode_); - update_type_ = SL; - regularization_type_ = L2; - kernel_type_ = LINEAR; - kernel_param_ = 1.0; - kernel_gain_ = 1.0; - kernel_bias_ = 0.0; - rank_loss_type_ = PAIRWISE; - acceptence_probability_ = 0.1; - mini_batch_counter_ = 0; - gradient_l0_norm_ = -1; - norm_constraint_ = 1.0; - } - - ~StochasticLinearRanker() {} - // Getters and setters - double GetIterationNumber() const { - return iteration_num_; - } - double GetNormContraint() const { - return norm_constraint_; - } - RegularizationType GetRegularizationType() const { - return regularization_type_; - } - double GetLambda() const { - return lambda_; - } - uint64 GetMiniBatchSize() const { - return mini_batch_size_; - } - int32 GetGradientL0Norm() const { - return gradient_l0_norm_; - } - UpdateType GetUpdateType() const { - return update_type_; - } - AdaptationMode GetAdaptationMode() const { - return adaptation_mode_; - } - KernelType GetKernelType() const { - return kernel_type_; - } - // This function returns the basic kernel parameter. In case of - // polynomial kernel, it implies the degree of the polynomial. In case of - // RBF kernel, it implies the sigma parameter. In case of linear kernel, - // it is not used. - double GetKernelParam() const { - return kernel_param_; - } - double GetKernelGain() const { - return kernel_gain_;; - } - double GetKernelBias() const { - return kernel_bias_; - } - RankLossType GetRankLossType() const { - return rank_loss_type_; - } - double GetAcceptanceProbability() const { - return acceptence_probability_; - } - void SetIterationNumber(uint64 num) { - iteration_num_=num; - } - void SetNormConstraint(const double norm) { - norm_constraint_ = norm; - } - void SetRegularizationType(const RegularizationType r) { - regularization_type_ = r; - } - void SetLambda(double l) { - lambda_ = l; - learning_rate_controller_.SetLambda(l); - } - void SetMiniBatchSize(const uint64 msize) { - mini_batch_size_ = msize; - learning_rate_controller_.SetMiniBatchSize(msize); - } - void SetAdaptationMode(AdaptationMode m) { - adaptation_mode_ = m; - learning_rate_controller_.SetAdaptationMode(m); - } - void SetKernelType(KernelType k ) { - kernel_type_ = k; - } - // This function sets the basic kernel parameter. In case of - // polynomial kernel, it implies the degree of the polynomial. In case of - // RBF kernel, it implies the sigma parameter. In case of linear kernel, - // it is not used. - void SetKernelParam(double param) { - kernel_param_ = param; - } - // This function sets the kernel gain. NOTE: in most use cases, gain should - // be set to 1.0. - void SetKernelGain(double gain) { - kernel_gain_ = gain; - } - // This function sets the kernel bias. NOTE: in most use cases, bias should - // be set to 0.0. - void SetKernelBias(double bias) { - kernel_bias_ = bias; - } - void SetUpdateType(UpdateType u) { - update_type_ = u; - } - void SetRankLossType(RankLossType r) { - rank_loss_type_ = r; - } - void SetAcceptanceProbability(double p) { - acceptence_probability_ = p; - } - void SetGradientL0Norm(const int32 gradient_l0_norm) { - gradient_l0_norm_ = gradient_l0_norm; - } - // Load an existing model - void LoadWeights(const SparseWeightVector &model) { - weight_.LoadWeightVector(model); - } - // Save current model - void SaveWeights(SparseWeightVector *model) { - model->LoadWeightVector(weight_); - } - // Scoring - double ScoreSample(const SparseWeightVector &sample) { - const double dot = weight_.DotProduct(sample); - double w_square; - double s_square; - switch (kernel_type_) { - case LINEAR: - return dot; - case POLY: - return pow(kernel_gain_ * dot + kernel_bias_, kernel_param_); - case RBF: - w_square = weight_.L2Norm(); - s_square = sample.L2Norm(); - return exp(-1 * kernel_param_ * (w_square + s_square - 2 * dot)); - default: - ALOGE("unsupported kernel: %d", kernel_type_); - } - return -1; - } - // Learning Functions - // Return values: - // 1 :full update went through - // 2 :partial update went through (for SL only) - // 0 :no update necessary. - // -1:error. - int UpdateClassifier(const SparseWeightVector &positive, - const SparseWeightVector &negative); - - private: - SparseWeightVector weight_; - double norm_constraint_; - double lambda_; - RegularizationType regularization_type_; - AdaptationMode adaptation_mode_; - UpdateType update_type_; - RankLossType rank_loss_type_; - KernelType kernel_type_; - // Kernel gain and bias are typically multiplicative and additive factors to - // the dot product while calculating the kernel function. Kernel param is - // kernel-specific. In case of polynomial kernel, it is the degree of the - // polynomial. - double kernel_param_; - double kernel_gain_; - double kernel_bias_; - double acceptence_probability_; - SparseWeightVector current_negative_; - LearningRateController learning_rate_controller_; - uint64 iteration_num_; - // We average out gradient updates for mini_batch_size_ samples - // before performing an iteration of the algorithm. - uint64 mini_batch_counter_; - uint64 mini_batch_size_; - // Specifies the number of non-zero entries allowed in a gradient. - // Default is -1 which means we take the gradient as given by data without - // adding any new constraints. positive number is treated as an L0 constraint - int32 gradient_l0_norm_; - // Sub-Gradient Updates - // Pure Sub-Gradient update without any reprojection - // Note that a form of L2 regularization is built into this - void UpdateSubGradient(const SparseWeightVector &positive, - const SparseWeightVector &negative, - const double learning_rate, - const double positive_score, - const double negative_score, - const int32 gradient_l0_norm); - -}; -} // namespace learning_stochastic_linear -#endif // LEARNING_STOCHASTIC_LINEAR_STOCHASTIC_LINEAR_RANKER_H_ diff --git a/bordeaux/service/Android.mk b/bordeaux/service/Android.mk deleted file mode 100644 index 1d4464b15..000000000 --- a/bordeaux/service/Android.mk +++ /dev/null @@ -1,79 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := optional - -# Only compile source java files in this apk. -LOCAL_SRC_FILES := $(call all-java-files-under, src) -LOCAL_SRC_FILES += \ - src/android/bordeaux/services/IBordeauxServiceCallback.aidl \ - src/android/bordeaux/services/IAggregatorManager.aidl \ - src/android/bordeaux/services/ILearning_MulticlassPA.aidl \ - src/android/bordeaux/services/IPredictor.aidl \ - src/android/bordeaux/services/ILearning_StochasticLinearRanker.aidl \ - src/android/bordeaux/services/IBordeauxService.aidl \ - -LOCAL_STATIC_JAVA_LIBRARIES := bordeaux_learners -LOCAL_JNI_SHARED_LIBRARIES := libbordeaux - -LOCAL_PACKAGE_NAME := bordeaux - - -include $(BUILD_PACKAGE) - -## -# Build java lib -## -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := optional - -LOCAL_SRC_FILES += \ - src/android/bordeaux/services/IntFloat.java \ - src/android/bordeaux/services/StringFloat.java \ - src/android/bordeaux/services/StringString.java \ - src/android/bordeaux/services/BordeauxClassifier.java \ - src/android/bordeaux/services/BordeauxRanker.java \ - src/android/bordeaux/services/BordeauxPredictor.java \ - src/android/bordeaux/services/BordeauxAggregatorManager.java \ - src/android/bordeaux/services/BordeauxManagerService.java \ - src/android/bordeaux/services/IBordeauxServiceCallback.aidl \ - src/android/bordeaux/services/IAggregatorManager.aidl \ - src/android/bordeaux/services/IPredictor.aidl \ - src/android/bordeaux/services/ILearning_MulticlassPA.aidl \ - src/android/bordeaux/services/ILearning_StochasticLinearRanker.aidl \ - src/android/bordeaux/services/IBordeauxService.aidl \ - -LOCAL_MODULE := bordeaux_service -LOCAL_STATIC_JAVA_LIBRARIES := bordeaux_learners - -LOCAL_PROGUARD_ENABLED := disabled - -include $(BUILD_STATIC_JAVA_LIBRARY) - -## Building the whole Bordeaux service -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := optional - -# Only compile source java files in this apk. -LOCAL_SRC_FILES := $(call all-java-files-under, src) -LOCAL_SRC_FILES += \ - src/android/bordeaux/services/IBordeauxServiceCallback.aidl \ - src/android/bordeaux/services/IAggregatorManager.aidl \ - src/android/bordeaux/services/ILearning_MulticlassPA.aidl \ - src/android/bordeaux/services/IPredictor.aidl \ - src/android/bordeaux/services/ILearning_StochasticLinearRanker.aidl \ - src/android/bordeaux/services/IBordeauxService.aidl \ - -LOCAL_STATIC_JAVA_LIBRARIES := bordeaux_learners -LOCAL_JNI_SHARED_LIBRARIES := libbordeaux - -LOCAL_JAVA_RESOURCE_DIRS := res -LOCAL_MODULE := bordeaux_whole_service -LOCAL_PROGUARD_ENABLED := disabled - -include $(BUILD_STATIC_JAVA_LIBRARY) - -# Use the folloing include to make our test apk. -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/bordeaux/service/AndroidManifest.xml b/bordeaux/service/AndroidManifest.xml deleted file mode 100644 index 5e5ec3f2c..000000000 --- a/bordeaux/service/AndroidManifest.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/bordeaux/service/res/drawable-hdpi/ic_bordeaux.png b/bordeaux/service/res/drawable-hdpi/ic_bordeaux.png deleted file mode 100644 index b191d46d2..000000000 Binary files a/bordeaux/service/res/drawable-hdpi/ic_bordeaux.png and /dev/null differ diff --git a/bordeaux/service/res/drawable-mdpi/ic_bordeaux.png b/bordeaux/service/res/drawable-mdpi/ic_bordeaux.png deleted file mode 100644 index 8975f9bf4..000000000 Binary files a/bordeaux/service/res/drawable-mdpi/ic_bordeaux.png and /dev/null differ diff --git a/bordeaux/service/res/drawable-xhdpi/ic_bordeaux.png b/bordeaux/service/res/drawable-xhdpi/ic_bordeaux.png deleted file mode 100644 index ac7513d3e..000000000 Binary files a/bordeaux/service/res/drawable-xhdpi/ic_bordeaux.png and /dev/null differ diff --git a/bordeaux/service/res/layout/lava_messenger_service_binding.xml b/bordeaux/service/res/layout/lava_messenger_service_binding.xml deleted file mode 100644 index 4fa314c05..000000000 --- a/bordeaux/service/res/layout/lava_messenger_service_binding.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/bordeaux/service/res/layout/lava_service_binding.xml b/bordeaux/service/res/layout/lava_service_binding.xml deleted file mode 100644 index c41980c4e..000000000 --- a/bordeaux/service/res/layout/lava_service_binding.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/bordeaux/service/res/layout/lava_service_controller.xml b/bordeaux/service/res/layout/lava_service_controller.xml deleted file mode 100644 index 804589aba..000000000 --- a/bordeaux/service/res/layout/lava_service_controller.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/bordeaux/service/res/values/strings.xml b/bordeaux/service/res/values/strings.xml deleted file mode 100644 index f49d1a090..000000000 --- a/bordeaux/service/res/values/strings.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - Bordeaux Apps - Send Learning Data - - Local service has started - Local service has stopped - Sample Local Service - - App/Service/Local Service Controller - This demonstrates how you can implement persistent services that - may be started and stopped as desired. - Start Service - Stop Service - - App/Service/Local Service Binding - This demonstrates how you can connect with a persistent - service. Notice how it automatically starts for you, and play around with the - interaction between this and Local Service Controller. - Bind Service - Unbind Service - Connected to local service - Disconnected from local service - - Remote service has started - Remote service has stopped - Sample Remote Service - - Bordeaux Service Controller - This demonstrates how you can implement persistent services - running in a separate process that may be started and stopped as desired. - - Bordeaux Service - This demonstrates how you can connect with a persistent - service running in another process. Use the kill button to see what happens when - the process crashes. - Kill Process - Connected to remote service - Disconnected from remote service - Unbinding due to disconnect - Failure calling remote service - - - diff --git a/bordeaux/service/src/android/bordeaux/services/Aggregator.java b/bordeaux/service/src/android/bordeaux/services/Aggregator.java deleted file mode 100644 index a5aced04a..000000000 --- a/bordeaux/service/src/android/bordeaux/services/Aggregator.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import java.util.Map; - -abstract class Aggregator { - protected AggregatorManager mAggregatorManager; - public void setManager(AggregatorManager m) { - mAggregatorManager = m; - } - abstract public String[] getListOfFeatures(); - abstract public Map getFeatureValue(String featureName); -} diff --git a/bordeaux/service/src/android/bordeaux/services/AggregatorManager.java b/bordeaux/service/src/android/bordeaux/services/AggregatorManager.java deleted file mode 100644 index 0fea228a7..000000000 --- a/bordeaux/service/src/android/bordeaux/services/AggregatorManager.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - - -import android.bordeaux.services.StringString; -import android.content.Context; -import android.util.Log; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -class AggregatorManager extends IAggregatorManager.Stub { - private final String TAG = "AggregatorMnager"; - // this maps from the aggregator name to the registered aggregator instance - private static HashMap mAggregators = new HashMap(); - // this maps from the feature names to the aggregator that generates the feature - private static HashMap sFeatureMap = new HashMap(); - private static AggregatorManager mManager = null; - - private String mFakeLocation = null; - private String mFakeTimeOfDay = null; - private String mFakeDayOfWeek = null; - - private AggregatorManager() { - sFeatureMap = new HashMap(); - } - - public static AggregatorManager getInstance() { - if (mManager == null ) - mManager = new AggregatorManager(); - return mManager; - } - - public String[] getListOfFeatures() { - String[] s = new String[sFeatureMap.size()]; - int i = 0; - for (Map.Entry x : sFeatureMap.entrySet()) { - s[i] = x.getKey(); - i++; - } - return s; - } - - public void registerAggregator(Aggregator agg, AggregatorManager m) { - if (mAggregators.get(agg.getClass().getName()) != null) { - // only one instance - // throw new RuntimeException("Can't register more than one instance"); - } - mAggregators.put(agg.getClass().getName(), agg); - agg.setManager(m); - String[] fl = agg.getListOfFeatures(); - for ( int i = 0; i< fl.length; i ++) - sFeatureMap.put(fl[i], agg); - } - - // Start of IAggregatorManager interface - public ArrayList getData(String dataName) { - return getList(getDataMap(dataName)); - } - - public List getLocationClusters() { - LocationStatsAggregator agg = (LocationStatsAggregator) - mAggregators.get(LocationStatsAggregator.class.getName()); - if (agg == null) return new ArrayList (); - return agg.getClusterNames(); - } - - public List getTimeOfDayValues() { - TimeStatsAggregator agg = (TimeStatsAggregator) - mAggregators.get(TimeStatsAggregator.class.getName()); - if (agg == null) return new ArrayList(); - return agg.getTimeOfDayValues(); - } - - public List getDayOfWeekValues() { - TimeStatsAggregator agg = (TimeStatsAggregator) - mAggregators.get(TimeStatsAggregator.class.getName()); - if (agg == null) return new ArrayList(); - return agg.getDayOfWeekValues(); - } - - // Set an empty string "" to disable the fake location - public boolean setFakeLocation(String location) { - LocationStatsAggregator agg = (LocationStatsAggregator) - mAggregators.get(LocationStatsAggregator.class.getName()); - if (agg == null) return false; - agg.setFakeLocation(location); - mFakeLocation = location; - return true; - } - - // Set an empty string "" to disable the fake time of day - public boolean setFakeTimeOfDay(String time_of_day) { - TimeStatsAggregator agg = (TimeStatsAggregator) - mAggregators.get(TimeStatsAggregator.class.getName()); - if (agg == null) return false; - agg.setFakeTimeOfDay(time_of_day); - mFakeTimeOfDay = time_of_day; - return true; - } - - // Set an empty string "" to disable the fake day of week - public boolean setFakeDayOfWeek(String day_of_week) { - TimeStatsAggregator agg = (TimeStatsAggregator) - mAggregators.get(TimeStatsAggregator.class.getName()); - if (agg == null) return false; - agg.setFakeDayOfWeek(day_of_week); - mFakeDayOfWeek = day_of_week; - return true; - } - - // Get the current mode, if fake mode return true - public boolean getFakeMode() { - boolean fakeMode = false; - // checking any features that are in the fake mode - if (mFakeLocation != null && mFakeLocation.length() != 0) - fakeMode = true; - if (mFakeTimeOfDay != null && mFakeTimeOfDay.length() != 0) - fakeMode = true; - if (mFakeDayOfWeek != null && mFakeDayOfWeek.length() != 0) - fakeMode = true; - return fakeMode; - } - // End of IAggregatorManger interface - - public Map getDataMap(String dataName) { - if (sFeatureMap.get(dataName) != null) - return sFeatureMap.get(dataName).getFeatureValue(dataName); - else - Log.e(TAG, "There is no feature called " + dataName); - return null; - } - - private ArrayList getList(final Map sample) { - ArrayList StringString_sample = new ArrayList(); - for (Map.Entry x : sample.entrySet()) { - StringString v = new StringString(); - v.key = x.getKey(); - v.value = x.getValue(); - StringString_sample.add(v); - } - return StringString_sample; - } -} diff --git a/bordeaux/service/src/android/bordeaux/services/AggregatorRecordStorage.java b/bordeaux/service/src/android/bordeaux/services/AggregatorRecordStorage.java deleted file mode 100644 index 4bf677f59..000000000 --- a/bordeaux/service/src/android/bordeaux/services/AggregatorRecordStorage.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.database.SQLException; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.util.Log; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/* This class implements record like data storage for aggregator. - * The data is stored in the sqlite database row by row without primary key, all - * columns are assume having string value. - * Sample usage: - * AggregatorRecordStorage db = new AggregatorRecordStorage(this, "TestTable", - * new String[]{"clusterid", "long", "lat"}); - * db.removeAllData(); - * HashMap row = new HashMap(); - * row.put("clusterid", "home"); - * row.put("long", "110.203"); - * row.put("lat", "-13.787"); - * db.addData(row); - * row.put("clusterid", "office"); - * row.put("long", "1.203"); - * row.put("lat", "33.787"); - * db.addData(row); - * List > allData = db.getAllData(); - * Log.i(TAG,"Total data in database: " + allData.size()); - */ -class AggregatorRecordStorage extends AggregatorStorage { - private static final String TAG = "AggregatorRecordStorage"; - private String mTableName; - private List mColumnNames; - - public AggregatorRecordStorage(Context context, String tableName, String [] columnNames) { - if (columnNames.length < 1) { - throw new RuntimeException("No column keys"); - } - mColumnNames = Arrays.asList(columnNames); - mTableName = tableName; - - String tableCmd = "create table " + tableName + "( " + columnNames[0] + - " TEXT"; - for (int i = 1; i < columnNames.length; ++i) - tableCmd = tableCmd + ", " + columnNames[i] + " TEXT"; - tableCmd = tableCmd + ");"; - Log.i(TAG, tableCmd); - try { - mDbHelper = new DBHelper(context, tableName, tableCmd); - mDatabase = mDbHelper.getWritableDatabase(); - } catch (SQLException e) { - throw new RuntimeException("Can't open table: " + tableName); - } - } - - // Adding one more row to the table. - // the data is a map of pair. - public boolean addData(Map data) { - ContentValues content = new ContentValues(); - for (Map.Entry item : data.entrySet()) { - content.put(item.getKey(), item.getValue()); - } - long rowID = - mDatabase.insert(mTableName, null, content); - return rowID >= 0; - } - - // Return all data as a list of Map. - // Notice that the column names are repeated for each row. - public List> getAllData() { - ArrayList > allData = new ArrayList >(); - - Cursor cursor = mDatabase.rawQuery("select * from " + mTableName + ";", null); - if (cursor.getCount() == 0) { - return allData; - } - cursor.moveToFirst(); - do { - HashMap oneRow = new HashMap(); - for (String column : mColumnNames) { - int columnIndex = cursor.getColumnIndex(column); - if (!cursor.isNull(columnIndex)) { - String value = cursor.getString(columnIndex); - oneRow.put(column, value); - } - } - allData.add(oneRow); - } while (cursor.moveToNext()); - return allData; - } - - // Empty the storage. - public int removeAllData() { - int nDeleteRows = mDatabase.delete(mTableName, "1", null); - Log.i(TAG, "Number of rows in table deleted: " + nDeleteRows); - return nDeleteRows; - } -} diff --git a/bordeaux/service/src/android/bordeaux/services/AggregatorStorage.java b/bordeaux/service/src/android/bordeaux/services/AggregatorStorage.java deleted file mode 100644 index 1d8886e66..000000000 --- a/bordeaux/service/src/android/bordeaux/services/AggregatorStorage.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.content.Context; -import android.database.SQLException; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.util.Log; - -// Base Helper class for aggregator storage database -class AggregatorStorage { - private static final String TAG = "AggregatorStorage"; - private static final String DATABASE_NAME = "aggregator"; - private static final int DATABASE_VERSION = 1; - - protected DBHelper mDbHelper; - protected SQLiteDatabase mDatabase; - - class DBHelper extends SQLiteOpenHelper { - private String mTableCmd; - private String mTableName; - DBHelper(Context context, String tableName, String tableCmd) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); - mTableName = tableName; - mTableCmd = tableCmd; - } - - @Override - public void onCreate(SQLiteDatabase db) { - db.execSQL(mTableCmd); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - Log.w(TAG, "Upgrading database from version " + oldVersion + " to " - + newVersion + ", which will destroy all old data"); - - db.execSQL("DROP TABLE IF EXISTS " + mTableName); - onCreate(db); - } - } -} diff --git a/bordeaux/service/src/android/bordeaux/services/BaseCluster.java b/bordeaux/service/src/android/bordeaux/services/BaseCluster.java deleted file mode 100644 index 03574a9fa..000000000 --- a/bordeaux/service/src/android/bordeaux/services/BaseCluster.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.bordeaux.services; -import android.location.Location; -import android.text.format.Time; -import android.util.Log; - -import java.lang.Math; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -public class BaseCluster { - - public static String TAG = "BaseCluster"; - - public double[] mCenter; - // protected double[] mCenter; - - protected static final int VECTOR_LENGTH = 3; - - private static final long FORGETTING_ENUMERATOR = 95; - private static final long FORGETTING_DENOMINATOR = 100; - - // Histogram illustrates the pattern of visit during time of day, - protected HashMap mHistogram = new HashMap(); - - protected long mDuration; - - protected String mSemanticId; - - protected static final double EARTH_RADIUS = 6378100f; - - public BaseCluster(Location location) { - mCenter = getLocationVector(location); - mDuration = 0; - } - - public BaseCluster(String semanticId, double longitude, double latitude, - long duration) { - mSemanticId = semanticId; - mCenter = getLocationVector(longitude, latitude); - mDuration = duration; - } - - public String getSemanticId() { - return mSemanticId; - } - - public void generateSemanticId(long index) { - mSemanticId = "cluser: " + String.valueOf(index); - } - - public long getDuration() { - return mDuration; - } - - public boolean hasSemanticId() { - return mSemanticId != null; - } - - protected double[] getLocationVector(Location location) { - return getLocationVector(location.getLongitude(), location.getLatitude()); - } - - protected double[] getLocationVector(double longitude, double latitude) { - double vector[] = new double[VECTOR_LENGTH]; - double lambda = Math.toRadians(longitude); - double phi = Math.toRadians(latitude); - - vector[0] = Math.cos(lambda) * Math.cos(phi); - vector[1] = Math.sin(lambda) * Math.cos(phi); - vector[2] = Math.sin(phi); - return vector; - } - - protected double getCenterLongitude() { - // Because latitude ranges from -90 to 90 degrees, cosPhi >= 0. - double cosPhi = Math.cos(Math.asin(mCenter[2])); - double longitude = Math.toDegrees(Math.asin(mCenter[1] / cosPhi)); - if (mCenter[0] < 0) { - longitude = (longitude > 0) ? 180f - longitude : -180 - longitude; - } - return longitude; - } - - protected double getCenterLatitude() { - return Math.toDegrees(Math.asin(mCenter[2])); - } - - private double computeDistance(double[] vector1, double[] vector2) { - double product = 0f; - for (int i = 0; i < VECTOR_LENGTH; ++i) { - product += vector1[i] * vector2[i]; - } - double radian = Math.acos(Math.min(product, 1f)); - return radian * EARTH_RADIUS; - } - - /* - * This computes the distance from loation to the cluster center in meter. - */ - public float distanceToCenter(Location location) { - return (float) computeDistance(mCenter, getLocationVector(location)); - } - - public float distanceToCluster(BaseCluster cluster) { - return (float) computeDistance(mCenter, cluster.mCenter); - } - - public void absorbCluster(BaseCluster cluster) { - averageCenter(cluster.mCenter, cluster.mDuration); - absorbHistogram(cluster); - } - - public void setCluster(BaseCluster cluster) { - for (int i = 0; i < VECTOR_LENGTH; ++i) { - mCenter[i] = cluster.mCenter[i]; - } - mHistogram.clear(); - mHistogram.putAll(cluster.mHistogram); - mDuration = cluster.mDuration; - } - - private void absorbHistogram(BaseCluster cluster) { - for (Map.Entry entry : cluster.mHistogram.entrySet()) { - String timeLabel = entry.getKey(); - long duration = entry.getValue(); - - if (mHistogram.containsKey(timeLabel)) { - duration += mHistogram.get(timeLabel); - } - mHistogram.put(timeLabel, duration); - } - mDuration += cluster.mDuration; - } - - public boolean passThreshold(long durationThreshold) { - // TODO: might want to keep semantic cluster - return mDuration > durationThreshold; - } - - public final HashMap getHistogram() { - return mHistogram; - } - - public void setHistogram(Map histogram) { - mHistogram.clear(); - mHistogram.putAll(histogram); - - mDuration = 0; - if (mHistogram.containsKey(TimeStatsAggregator.WEEKEND)) { - mDuration += mHistogram.get(TimeStatsAggregator.WEEKEND); - } - if (mHistogram.containsKey(TimeStatsAggregator.WEEKDAY)) { - mDuration += mHistogram.get(TimeStatsAggregator.WEEKDAY); - } - } - - public void forgetPastHistory() { - mDuration *= FORGETTING_ENUMERATOR; - mDuration /= FORGETTING_DENOMINATOR; - - for (Map.Entry entry : mHistogram.entrySet()) { - String key = entry.getKey(); - long value = entry.getValue(); - - value *= FORGETTING_ENUMERATOR; - value /= FORGETTING_DENOMINATOR; - - mHistogram.put(key, value); - } - } - - protected void normalizeCenter() { - double norm = 0; - for (int i = 0; i < VECTOR_LENGTH; ++i) { - norm += mCenter[i] * mCenter[i]; - } - norm = Math.sqrt(norm); - for (int i = 0; i < VECTOR_LENGTH; ++i) { - mCenter[i] /= norm; - } - } - - protected void averageCenter(double[] newCenter, long newDuration) { - double weight = ((double) mDuration) / (mDuration + newDuration); - double newWeight = 1f - weight; - - double norm = 0; - for (int i = 0; i < VECTOR_LENGTH; ++i) { - mCenter[i] = weight * mCenter[i] + newWeight * newCenter[i]; - norm += mCenter[i] * mCenter[i]; - } - norm = Math.sqrt(norm); - for (int i = 0; i < VECTOR_LENGTH; ++i) { - mCenter[i] /= norm; - } - } -} diff --git a/bordeaux/service/src/android/bordeaux/services/BordeauxAggregatorManager.java b/bordeaux/service/src/android/bordeaux/services/BordeauxAggregatorManager.java deleted file mode 100644 index 7a01233ab..000000000 --- a/bordeaux/service/src/android/bordeaux/services/BordeauxAggregatorManager.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.bordeaux.services.IAggregatorManager; -import android.bordeaux.services.StringString; -import android.content.Context; -import android.os.RemoteException; -import android.util.Log; -import java.util.List; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -/** AggregatorManger for Learning framework. - */ -public class BordeauxAggregatorManager { - static final String TAG = "BordeauxAggregatorManager"; - static final String AggregatorManager_NOTAVAILABLE = "AggregatorManager not Available"; - private Context mContext; - private IAggregatorManager mAggregatorManager; - - public boolean retrieveAggregatorManager() { - if (mAggregatorManager == null) { - mAggregatorManager = BordeauxManagerService.getAggregatorManager(mContext); - if (mAggregatorManager == null) { - Log.e(TAG, AggregatorManager_NOTAVAILABLE); - return false; - } - } - return true; - } - - public BordeauxAggregatorManager (Context context) { - mContext = context; - mAggregatorManager = BordeauxManagerService.getAggregatorManager(mContext); - } - - public Map GetData(final String dataName) { - if (!retrieveAggregatorManager()) - throw new RuntimeException(AggregatorManager_NOTAVAILABLE); - try { - return getMap(mAggregatorManager.getData(dataName)); - } catch (RemoteException e) { - Log.e(TAG,"Exception in Getting " + dataName); - throw new RuntimeException(AggregatorManager_NOTAVAILABLE); - } - } - - public List getLocationClusters() { - if (!retrieveAggregatorManager()) - throw new RuntimeException(AggregatorManager_NOTAVAILABLE); - try { - return mAggregatorManager.getLocationClusters(); - } catch (RemoteException e) { - Log.e(TAG,"Error getting location clusters"); - throw new RuntimeException(AggregatorManager_NOTAVAILABLE); - } - } - - public List getTimeOfDayValues() { - if (!retrieveAggregatorManager()) - throw new RuntimeException(AggregatorManager_NOTAVAILABLE); - try { - return mAggregatorManager.getTimeOfDayValues(); - } catch (RemoteException e) { - Log.e(TAG,"Error getting time of day values"); - throw new RuntimeException(AggregatorManager_NOTAVAILABLE); - } - } - - public List getDayOfWeekValues() { - if (!retrieveAggregatorManager()) - throw new RuntimeException(AggregatorManager_NOTAVAILABLE); - try { - return mAggregatorManager.getDayOfWeekValues(); - } catch (RemoteException e) { - Log.e(TAG,"Error getting day of week values"); - throw new RuntimeException(AggregatorManager_NOTAVAILABLE); - } - } - - public boolean setFakeLocation(final String name) { - if (!retrieveAggregatorManager()) - throw new RuntimeException(AggregatorManager_NOTAVAILABLE); - try { - return mAggregatorManager.setFakeLocation(name); - } catch (RemoteException e) { - Log.e(TAG,"Error setting fake location:" + name); - throw new RuntimeException(AggregatorManager_NOTAVAILABLE); - } - } - - public boolean setFakeTimeOfDay(final String time_of_day) { - if (!retrieveAggregatorManager()) - throw new RuntimeException(AggregatorManager_NOTAVAILABLE); - try { - return mAggregatorManager.setFakeTimeOfDay(time_of_day); - } catch (RemoteException e) { - Log.e(TAG,"Error setting fake time of day:" + time_of_day); - throw new RuntimeException(AggregatorManager_NOTAVAILABLE); - } - } - - public boolean setFakeDayOfWeek(final String day_of_week) { - if (!retrieveAggregatorManager()) - throw new RuntimeException(AggregatorManager_NOTAVAILABLE); - try { - return mAggregatorManager.setFakeDayOfWeek(day_of_week); - } catch (RemoteException e) { - Log.e(TAG,"Error setting fake day of week:" + day_of_week); - throw new RuntimeException(AggregatorManager_NOTAVAILABLE); - } - } - - public boolean getFakeMode() { - if (!retrieveAggregatorManager()) - throw new RuntimeException(AggregatorManager_NOTAVAILABLE); - try { - return mAggregatorManager.getFakeMode(); - } catch (RemoteException e) { - Log.e(TAG,"Error getting fake mode"); - throw new RuntimeException(AggregatorManager_NOTAVAILABLE); - } - } - - private Map getMap(final List sample) { - HashMap map = new HashMap(); - for (int i =0; i < sample.size(); i++) { - map.put(sample.get(i).key, sample.get(i).value); - } - return (Map) map; - } -} diff --git a/bordeaux/service/src/android/bordeaux/services/BordeauxClassifier.java b/bordeaux/service/src/android/bordeaux/services/BordeauxClassifier.java deleted file mode 100644 index 348cd0cb8..000000000 --- a/bordeaux/service/src/android/bordeaux/services/BordeauxClassifier.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.bordeaux.services.ILearning_MulticlassPA; -import android.bordeaux.services.IntFloat; -import android.content.Context; -import android.os.RemoteException; -import android.util.Log; - -import java.util.ArrayList; -import java.util.List; -import java.util.HashMap; -import java.util.Map; - -/** Classifier for the Learning framework. - * For training: call trainOneSample - * For classifying: call classify - * Data is represented as sparse key, value pair. And key is an integer, value - * is a float. Class label(target) for the training data is an integer. - * Note: since the actual classifier is running in a remote the service. - * Sometimes the connection may be lost or not established. - * - */ -public class BordeauxClassifier { - static final String TAG = "BordeauxClassifier"; - private Context mContext; - private String mName; - private ILearning_MulticlassPA mClassifier; - private ArrayList getArrayList(final HashMap sample) { - ArrayList intfloat_sample = new ArrayList(); - for (Map.Entry x : sample.entrySet()) { - IntFloat v = new IntFloat(); - v.index = x.getKey(); - v.value = x.getValue(); - intfloat_sample.add(v); - } - return intfloat_sample; - } - - private boolean retrieveClassifier() { - if (mClassifier == null) - mClassifier = BordeauxManagerService.getClassifier(mContext, mName); - // if classifier is not available, return false - if (mClassifier == null) { - Log.i(TAG,"Classifier not available."); - return false; - } - return true; - } - - public BordeauxClassifier(Context context) { - mContext = context; - mName = "defaultClassifier"; - mClassifier = BordeauxManagerService.getClassifier(context, mName); - } - - public BordeauxClassifier(Context context, String name) { - mContext = context; - mName = name; - mClassifier = BordeauxManagerService.getClassifier(context, mName); - } - - public boolean update(final HashMap sample, int target) { - if (!retrieveClassifier()) - return false; - try { - mClassifier.TrainOneSample(getArrayList(sample), target); - } catch (RemoteException e) { - Log.e(TAG,"Exception: training one sample."); - return false; - } - return true; - } - - public int classify(final HashMap sample) { - // if classifier is not available return -1 as an indication of fail. - if (!retrieveClassifier()) - return -1; - try { - return mClassifier.Classify(getArrayList(sample)); - } catch (RemoteException e) { - Log.e(TAG,"Exception: classify the sample."); - // return an invalid number. - // TODO: throw exception. - return -1; - } - } -} diff --git a/bordeaux/service/src/android/bordeaux/services/BordeauxManagerService.java b/bordeaux/service/src/android/bordeaux/services/BordeauxManagerService.java deleted file mode 100644 index 00fbb30f8..000000000 --- a/bordeaux/service/src/android/bordeaux/services/BordeauxManagerService.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.PointF; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.os.Process; -import android.os.RemoteException; -import android.util.Log; - -/** - * {@hide} - * This is used to provide a convenience to access the actual remote running - * service. - * TODO: Eventally the remote service will be running in the system server, and - * this will need to be served as a stub for the remote running service. And - * extends from IBordeauxManager.stub - */ -public class BordeauxManagerService { - - static private final String TAG = "BordeauxMangerService"; - static private IBordeauxService mService = null; - static private ILearning_StochasticLinearRanker mRanker = null; - static private IAggregatorManager mAggregatorManager = null; - static private IPredictor mPredictor = null; - static private ILearning_MulticlassPA mClassifier = null; - static private boolean mStarted = false; - - public BordeauxManagerService() { - } - - static private synchronized void bindServices(Context context) { - if (mStarted) return; - context.bindService(new Intent(IBordeauxService.class.getName()), - mConnection, Context.BIND_AUTO_CREATE); - mStarted = true; - } - - // Call the release, before the Context gets destroyed. - static public synchronized void release(Context context) { - if (mStarted && mConnection != null) { - context.unbindService(mConnection); - mService = null; - mStarted = false; - } - } - - static public synchronized IBordeauxService getService(Context context) { - if (mService == null) bindServices(context); - return mService; - } - - static public synchronized IAggregatorManager getAggregatorManager(Context context) { - if (mService == null) { - bindServices(context); - return null; - } - try { - mAggregatorManager = IAggregatorManager.Stub.asInterface( - mService.getAggregatorManager()); - } catch (RemoteException e) { - mAggregatorManager = null; - } - return mAggregatorManager; - } - - static public synchronized IPredictor getPredictor(Context context, String name) { - if (mService == null) { - bindServices(context); - return null; - } - try { - mPredictor = IPredictor.Stub.asInterface(mService.getPredictor(name)); - } catch (RemoteException e) { - mPredictor = null; - } - return mPredictor; - } - - static public synchronized ILearning_StochasticLinearRanker - getRanker(Context context, String name) { - if (mService == null) { - bindServices(context); - return null; - } - try { - mRanker = - ILearning_StochasticLinearRanker.Stub.asInterface( - mService.getRanker(name)); - } catch (RemoteException e) { - mRanker = null; - } - return mRanker; - } - - static public synchronized ILearning_MulticlassPA - getClassifier(Context context, String name) { - if (mService == null) { - bindServices(context); - return null; - } - try { - mClassifier = - ILearning_MulticlassPA.Stub.asInterface(mService.getClassifier(name)); - } catch (RemoteException e) { - mClassifier = null; - } - return mClassifier; - } - - /** - * Class for interacting with the main interface of the service. - */ - static private ServiceConnection mConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName className, - IBinder service) { - // This is called when the connection with the service has been - // established. - mService = IBordeauxService.Stub.asInterface(service); - } - - public void onServiceDisconnected(ComponentName className) { - // This is called when the connection with the service has been - // unexpectedly disconnected -- that is, its process crashed. - mService = null; - mStarted = false; // needs to bind again - } - }; -} diff --git a/bordeaux/service/src/android/bordeaux/services/BordeauxPredictor.java b/bordeaux/service/src/android/bordeaux/services/BordeauxPredictor.java deleted file mode 100644 index ac46af11f..000000000 --- a/bordeaux/service/src/android/bordeaux/services/BordeauxPredictor.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.bordeaux.services.IPredictor; -import android.content.Context; -import android.os.RemoteException; -import android.util.Log; -import android.util.Pair; - -import java.util.ArrayList; -import java.util.List; -import java.util.HashMap; -import java.util.Map; - -/** Predictor for the Learning framework. - */ -public class BordeauxPredictor { - static final String TAG = "BordeauxPredictor"; - static final String PREDICTOR_NOTAVAILABLE = "Predictor is not available."; - private Context mContext; - private String mName; - private IPredictor mPredictor; - - public BordeauxPredictor(Context context) { - mContext = context; - mName = "defaultPredictor"; - mPredictor = BordeauxManagerService.getPredictor(context, mName); - } - - public BordeauxPredictor(Context context, String name) { - mContext = context; - mName = name; - mPredictor = BordeauxManagerService.getPredictor(context, mName); - } - - public boolean reset() { - if (!retrievePredictor()){ - Log.e(TAG, "reset: " + PREDICTOR_NOTAVAILABLE); - return false; - } - try { - mPredictor.resetPredictor(); - return true; - } catch (RemoteException e) { - } - return false; - } - - public boolean retrievePredictor() { - if (mPredictor == null) { - mPredictor = BordeauxManagerService.getPredictor(mContext, mName); - } - if (mPredictor == null) { - Log.e(TAG, "retrievePredictor: " + PREDICTOR_NOTAVAILABLE); - return false; - } - return true; - } - - public void addSample(String sampleName) { - if (!retrievePredictor()) - throw new RuntimeException(PREDICTOR_NOTAVAILABLE); - try { - mPredictor.pushNewSample(sampleName); - } catch (RemoteException e) { - Log.e(TAG,"Exception: pushing a new example"); - throw new RuntimeException(PREDICTOR_NOTAVAILABLE); - } - } - - public ArrayList > getTopSamples() { - return getTopSamples(0); - } - - public ArrayList > getTopSamples(int topK) { - try { - ArrayList topList = - (ArrayList) mPredictor.getTopCandidates(topK); - - ArrayList > topSamples = - new ArrayList >(topList.size()); - for (int i = 0; i < topList.size(); ++i) { - topSamples.add(new Pair(topList.get(i).key, topList.get(i).value)); - } - return topSamples; - } catch(RemoteException e) { - Log.e(TAG,"Exception: getTopSamples"); - throw new RuntimeException(PREDICTOR_NOTAVAILABLE); - } - } - - public boolean setParameter(String key, String value) { - if (!retrievePredictor()) - throw new RuntimeException(PREDICTOR_NOTAVAILABLE); - try { - return mPredictor.setPredictorParameter(key, value); - } catch (RemoteException e) { - Log.e(TAG,"Exception: setting predictor parameter"); - throw new RuntimeException(PREDICTOR_NOTAVAILABLE); - } - } -} diff --git a/bordeaux/service/src/android/bordeaux/services/BordeauxRanker.java b/bordeaux/service/src/android/bordeaux/services/BordeauxRanker.java deleted file mode 100644 index 1ae5fcb62..000000000 --- a/bordeaux/service/src/android/bordeaux/services/BordeauxRanker.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.bordeaux.services.ILearning_StochasticLinearRanker; -import android.bordeaux.services.StringFloat; -import android.content.Context; -import android.os.RemoteException; -import android.util.Log; - -import java.util.ArrayList; -import java.util.List; -import java.util.HashMap; -import java.util.Map; - -/** Ranker for the Learning framework. - * For training: call updateClassifier with a pair of samples. - * For ranking: call scoreSample to the score of the rank - * Data is represented as sparse key, value pair. And key is a String, value - * is a float. - * Note: since the actual ranker is running in a remote the service. - * Sometimes the connection may be lost or not established. - * - */ -public class BordeauxRanker { - static final String TAG = "BordeauxRanker"; - static final String RANKER_NOTAVAILABLE = "Ranker not Available"; - private Context mContext; - private String mName; - private ILearning_StochasticLinearRanker mRanker; - private ArrayList getArrayList(final HashMap sample) { - ArrayList stringfloat_sample = new ArrayList(); - for (Map.Entry x : sample.entrySet()) { - StringFloat v = new StringFloat(); - v.key = x.getKey(); - v.value = x.getValue(); - stringfloat_sample.add(v); - } - return stringfloat_sample; - } - - public boolean retrieveRanker() { - if (mRanker == null) - mRanker = BordeauxManagerService.getRanker(mContext, mName); - // if classifier is not available, return false - if (mRanker == null) { - Log.e(TAG,"Ranker not available."); - return false; - } - return true; - } - - public BordeauxRanker(Context context) { - mContext = context; - mName = "defaultRanker"; - mRanker = BordeauxManagerService.getRanker(context, mName); - } - - public BordeauxRanker(Context context, String name) { - mContext = context; - mName = name; - mRanker = BordeauxManagerService.getRanker(context, mName); - } - - // Update the ranker with two samples, sample1 has higher rank than - // sample2. - public boolean update(final HashMap sample1, - final HashMap sample2) { - if (!retrieveRanker()) - return false; - try { - mRanker.UpdateClassifier(getArrayList(sample1), getArrayList(sample2)); - } catch (RemoteException e) { - Log.e(TAG,"Exception: updateClassifier."); - return false; - } - return true; - } - - public boolean reset() { - if (!retrieveRanker()){ - Log.e(TAG,"Exception: Ranker is not availible"); - return false; - } - try { - mRanker.ResetRanker(); - return true; - } catch (RemoteException e) { - } - return false; - } - - public float scoreSample(final HashMap sample) { - if (!retrieveRanker()) - throw new RuntimeException(RANKER_NOTAVAILABLE); - try { - return mRanker.ScoreSample(getArrayList(sample)); - } catch (RemoteException e) { - Log.e(TAG,"Exception: scoring the sample."); - throw new RuntimeException(RANKER_NOTAVAILABLE); - } - } - - public boolean setPriorWeight(final HashMap sample) { - if (!retrieveRanker()) - throw new RuntimeException(RANKER_NOTAVAILABLE); - try { - return mRanker.SetModelPriorWeight(getArrayList(sample)); - } catch (RemoteException e) { - Log.e(TAG,"Exception: set prior Weights"); - throw new RuntimeException(RANKER_NOTAVAILABLE); - } - } - - public boolean setParameter(String key, String value) { - if (!retrieveRanker()) - throw new RuntimeException(RANKER_NOTAVAILABLE); - try { - return mRanker.SetModelParameter(key, value); - } catch (RemoteException e) { - Log.e(TAG,"Exception: Setting Parameter"); - throw new RuntimeException(RANKER_NOTAVAILABLE); - } - } -} diff --git a/bordeaux/service/src/android/bordeaux/services/BordeauxService.java b/bordeaux/service/src/android/bordeaux/services/BordeauxService.java deleted file mode 100644 index 48d41d942..000000000 --- a/bordeaux/service/src/android/bordeaux/services/BordeauxService.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.app.Activity; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.app.Service; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.ServiceConnection; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.os.Process; -import android.os.RemoteCallbackList; -import android.os.RemoteException; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.TextView; -import android.widget.Toast; - -//import android.bordeaux.R; -import android.util.Log; - -import java.io.*; - -/** - * Machine Learning service that runs in a remote process. - * The application doesn't use this class directly. - * - */ -public class BordeauxService extends Service { - private final String TAG = "BordeauxService"; - /** - * This is a list of callbacks that have been registered with the - * service. - * It's a place holder for future communications with all registered - * clients. - */ - final RemoteCallbackList mCallbacks = - new RemoteCallbackList(); - - int mValue = 0; - NotificationManager mNotificationManager; - - BordeauxSessionManager mSessionManager; - AggregatorManager mAggregatorManager; - TimeStatsAggregator mTimeStatsAggregator; - LocationStatsAggregator mLocationStatsAggregator; - MotionStatsAggregator mMotionStatsAggregator; - - @Override - public void onCreate() { - Log.i(TAG, "Bordeaux service created."); - //mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); - mSessionManager = new BordeauxSessionManager(this); - mMotionStatsAggregator = new MotionStatsAggregator(); - mLocationStatsAggregator = new LocationStatsAggregator(this); - mTimeStatsAggregator = new TimeStatsAggregator(); - mAggregatorManager = AggregatorManager.getInstance(); - mAggregatorManager.registerAggregator(mMotionStatsAggregator, mAggregatorManager); - mAggregatorManager.registerAggregator(mLocationStatsAggregator, mAggregatorManager); - mAggregatorManager.registerAggregator(mTimeStatsAggregator, mAggregatorManager); - - // Display a notification about us starting. - // TODO: don't display the notification after the service is - // automatically started by the system, currently it's useful for - // debugging. - showNotification(); - } - - @Override - public void onDestroy() { - // Save the sessions - mSessionManager.saveSessions(); - - // Cancel the persistent notification. - //mNotificationManager.cancel(R.string.remote_service_started); - - // Tell the user we stopped. - //Toast.makeText(this, R.string.remote_service_stopped, Toast.LENGTH_SHORT).show(); - - // Unregister all callbacks. - mCallbacks.kill(); - - mLocationStatsAggregator.release(); - - Log.i(TAG, "Bordeaux service stopped."); - } - - @Override - public IBinder onBind(Intent intent) { - // Return the requested interface. - if (IBordeauxService.class.getName().equals(intent.getAction())) { - return mBinder; - } - return null; - } - - - // The main interface implemented by the service. - private final IBordeauxService.Stub mBinder = new IBordeauxService.Stub() { - private IBinder getLearningSession(Class learnerClass, String name) { - PackageManager pm = getPackageManager(); - String uidname = pm.getNameForUid(getCallingUid()); - Log.i(TAG,"Name for uid: " + uidname); - BordeauxSessionManager.SessionKey key = - mSessionManager.getSessionKey(uidname, learnerClass, name); - Log.i(TAG, "request learning session: " + key.value); - try { - IBinder iLearner = mSessionManager.getSessionBinder(learnerClass, key); - return iLearner; - } catch (RuntimeException e) { - Log.e(TAG, "Error getting learning interface" + e); - return null; - } - } - - public IBinder getClassifier(String name) { - return getLearningSession(Learning_MulticlassPA.class, name); - } - - public IBinder getRanker(String name) { - return getLearningSession(Learning_StochasticLinearRanker.class, name); - } - - public IBinder getPredictor(String name) { - return getLearningSession(Predictor.class, name); - } - - public IBinder getAggregatorManager() { - return (IBinder) mAggregatorManager; - } - - public void registerCallback(IBordeauxServiceCallback cb) { - if (cb != null) mCallbacks.register(cb); - } - - public void unregisterCallback(IBordeauxServiceCallback cb) { - if (cb != null) mCallbacks.unregister(cb); - } - }; - - @Override - public void onTaskRemoved(Intent rootIntent) { - Toast.makeText(this, "Task removed: " + rootIntent, Toast.LENGTH_LONG).show(); - } - - /** - * Show a notification while this service is running. - * TODO: remove the code after production (when service is loaded - * automatically by the system). - */ - private void showNotification() { - /*// In this sample, we'll use the same text for the ticker and the expanded notification - CharSequence text = getText(R.string.remote_service_started); - - // The PendingIntent to launch our activity if the user selects this notification - PendingIntent contentIntent = - PendingIntent.getActivity(this, 0, - new Intent("android.bordeaux.DEBUG_CONTROLLER"), 0); - - // // Set the info for the views that show in the notification panel. - - Notification.Builder builder = new Notification.Builder(this); - builder.setSmallIcon(R.drawable.ic_bordeaux); - builder.setWhen(System.currentTimeMillis()); - builder.setTicker(text); - builder.setContentTitle(text); - builder.setContentIntent(contentIntent); - Notification notification = builder.getNotification(); - // Send the notification. - // We use a string id because it is a unique number. We use it later to cancel. - mNotificationManager.notify(R.string.remote_service_started, notification); */ - } - -} diff --git a/bordeaux/service/src/android/bordeaux/services/BordeauxSessionManager.java b/bordeaux/service/src/android/bordeaux/services/BordeauxSessionManager.java deleted file mode 100644 index 89fcac29e..000000000 --- a/bordeaux/service/src/android/bordeaux/services/BordeauxSessionManager.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.bordeaux.services.IBordeauxLearner.ModelChangeCallback; -import android.content.Context; -import android.os.IBinder; -import android.util.Log; - -import java.lang.NoSuchMethodException; -import java.lang.InstantiationException; -import java.util.concurrent.ConcurrentHashMap; -import java.util.HashMap; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -// This class manages the learning sessions from multiple applications. -// The learning sessions are automatically backed up to the storage. -// -class BordeauxSessionManager { - - static private final String TAG = "BordeauxSessionManager"; - private BordeauxSessionStorage mSessionStorage; - - static class Session { - Class learnerClass; - IBordeauxLearner learner; - boolean modified = false; - }; - - static class SessionKey { - String value; - }; - - // Thread to periodically save the sessions to storage - class PeriodicSave extends Thread implements Runnable { - long mSavingInterval = 60000; // 60 seconds - boolean mQuit = false; - PeriodicSave() {} - public void run() { - while (!mQuit) { - try { - sleep(mSavingInterval); - } catch (InterruptedException e) { - // thread waked up. - // ignore - } - saveSessions(); - } - } - } - - PeriodicSave mSavingThread = new PeriodicSave(); - - private ConcurrentHashMap mSessions = - new ConcurrentHashMap(); - - public BordeauxSessionManager(final Context context) { - mSessionStorage = new BordeauxSessionStorage(context); - mSavingThread.start(); - } - - class LearningUpdateCallback implements ModelChangeCallback { - private String mKey; - - public LearningUpdateCallback(String key) { - mKey = key; - } - - public void modelChanged(IBordeauxLearner learner) { - // Save the session - Session session = mSessions.get(mKey); - if (session != null) { - synchronized(session) { - if (session.learner != learner) { - throw new RuntimeException("Session data corrupted!"); - } - session.modified = true; - } - } - } - } - - // internal unique key that identifies the learning instance. - // Composed by the package id of the calling process, learning class name - // and user specified name. - public SessionKey getSessionKey(String callingUid, Class learnerClass, String name) { - SessionKey key = new SessionKey(); - key.value = callingUid + "#" + "_" + name + "_" + learnerClass.getName(); - return key; - } - - public IBinder getSessionBinder(Class learnerClass, SessionKey key) { - if (mSessions.containsKey(key.value)) { - return mSessions.get(key.value).learner.getBinder(); - } - // not in memory cache - try { - // try to find it in the database - Session stored = mSessionStorage.getSession(key.value); - if (stored != null) { - // set the callback, so that we can save the state - stored.learner.setModelChangeCallback(new LearningUpdateCallback(key.value)); - // found session in the storage, put in the cache - mSessions.put(key.value, stored); - return stored.learner.getBinder(); - } - - // if session is not already stored, create a new one. - Log.i(TAG, "create a new learning session: " + key.value); - IBordeauxLearner learner = - (IBordeauxLearner) learnerClass.getConstructor().newInstance(); - // set the callback, so that we can save the state - learner.setModelChangeCallback(new LearningUpdateCallback(key.value)); - Session session = new Session(); - session.learnerClass = learnerClass; - session.learner = learner; - mSessions.put(key.value, session); - return learner.getBinder(); - } catch (Exception e) { - throw new RuntimeException("Can't instantiate class: " + - learnerClass.getName()); - } - } - - public void saveSessions() { - for (Map.Entry session : mSessions.entrySet()) { - synchronized(session) { - // Save the session if it's modified. - if (session.getValue().modified) { - SessionKey skey = new SessionKey(); - skey.value = session.getKey(); - saveSession(skey); - } - } - } - } - - public boolean saveSession(SessionKey key) { - Session session = mSessions.get(key.value); - if (session != null) { - synchronized(session) { - byte[] model = session.learner.getModel(); - - // write to database - boolean res = mSessionStorage.saveSession(key.value, session.learnerClass, model); - if (res) - session.modified = false; - else { - Log.e(TAG, "Can't save session: " + key.value); - } - return res; - } - } - Log.e(TAG, "Session not found: " + key.value); - return false; - } - - // Load all session data into memory. - // The session data will be loaded into the memory from the database, even - // if this method is not called. - public void loadSessions() { - synchronized(mSessions) { - mSessionStorage.getAllSessions(mSessions); - for (Map.Entry session : mSessions.entrySet()) { - // set the callback, so that we can save the state - session.getValue().learner.setModelChangeCallback( - new LearningUpdateCallback(session.getKey())); - } - } - } - - public void removeAllSessionsFromCaller(String callingUid) { - // remove in the hash table - ArrayList remove_keys = new ArrayList(); - for (Map.Entry session : mSessions.entrySet()) { - if (session.getKey().startsWith(callingUid + "#")) { - remove_keys.add(session.getKey()); - } - } - for (String key : remove_keys) { - mSessions.remove(key); - } - // remove all session data from the callingUid in database - // % is used as wild match for the rest of the string in sql - int nDeleted = mSessionStorage.removeSessions(callingUid + "#%"); - if (nDeleted > 0) - Log.i(TAG, "Successfully deleted " + nDeleted + "sessions"); - } -} diff --git a/bordeaux/service/src/android/bordeaux/services/BordeauxSessionStorage.java b/bordeaux/service/src/android/bordeaux/services/BordeauxSessionStorage.java deleted file mode 100644 index 89c347204..000000000 --- a/bordeaux/service/src/android/bordeaux/services/BordeauxSessionStorage.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.database.SQLException; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.util.Log; - -import java.lang.System; -import java.util.concurrent.ConcurrentHashMap; - -// This class manages the database for storing the session data. -// -class BordeauxSessionStorage { - - private static final String TAG = "BordeauxSessionStorage"; - // unique key for the session - public static final String COLUMN_KEY = "key"; - // name of the learning class - public static final String COLUMN_CLASS = "class"; - // data of the learning model - public static final String COLUMN_MODEL = "model"; - // last update time - public static final String COLUMN_TIME = "time"; - - private static final String DATABASE_NAME = "bordeaux"; - private static final String SESSION_TABLE = "sessions"; - private static final int DATABASE_VERSION = 1; - private static final String DATABASE_CREATE = - "create table " + SESSION_TABLE + "( " + COLUMN_KEY + - " TEXT primary key, " + COLUMN_CLASS + " TEXT, " + - COLUMN_MODEL + " BLOB, " + COLUMN_TIME + " INTEGER);"; - - private SessionDBHelper mDbHelper; - private SQLiteDatabase mDbSessions; - - BordeauxSessionStorage(final Context context) { - try { - mDbHelper = new SessionDBHelper(context); - mDbSessions = mDbHelper.getWritableDatabase(); - } catch (SQLException e) { - throw new RuntimeException("Can't open session database"); - } - } - - private class SessionDBHelper extends SQLiteOpenHelper { - SessionDBHelper(Context context) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); - } - - @Override - public void onCreate(SQLiteDatabase db) { - db.execSQL(DATABASE_CREATE); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - Log.w(TAG, "Upgrading database from version " + oldVersion + " to " - + newVersion + ", which will destroy all old data"); - - db.execSQL("DROP TABLE IF EXISTS " + SESSION_TABLE); - onCreate(db); - } - } - - private ContentValues createSessionEntry(String key, Class learner, byte[] model) { - ContentValues entry = new ContentValues(); - entry.put(COLUMN_KEY, key); - entry.put(COLUMN_TIME, System.currentTimeMillis()); - entry.put(COLUMN_MODEL, model); - entry.put(COLUMN_CLASS, learner.getName()); - return entry; - } - - boolean saveSession(String key, Class learner, byte[] model) { - ContentValues content = createSessionEntry(key, learner, model); - long rowID = - mDbSessions.insertWithOnConflict(SESSION_TABLE, null, content, - SQLiteDatabase.CONFLICT_REPLACE); - return rowID >= 0; - } - - private BordeauxSessionManager.Session getSessionFromCursor(Cursor cursor) { - BordeauxSessionManager.Session session = new BordeauxSessionManager.Session(); - String className = cursor.getString(cursor.getColumnIndex(COLUMN_CLASS)); - try { - session.learnerClass = Class.forName(className); - session.learner = (IBordeauxLearner) session.learnerClass.getConstructor().newInstance(); - } catch (Exception e) { - throw new RuntimeException("Can't instantiate class: " + className); - } - byte[] model = cursor.getBlob(cursor.getColumnIndex(COLUMN_MODEL)); - session.learner.setModel(model); - return session; - } - - BordeauxSessionManager.Session getSession(String key) { - Cursor cursor = mDbSessions.query(true, SESSION_TABLE, - new String[]{COLUMN_KEY, COLUMN_CLASS, COLUMN_MODEL, COLUMN_TIME}, - COLUMN_KEY + "=\"" + key + "\"", null, null, null, null, null); - if ((cursor == null) | (cursor.getCount() == 0)) { - cursor.close(); - return null; - } - if (cursor.getCount() > 1) { - cursor.close(); - throw new RuntimeException("Unexpected duplication in session table for key:" + key); - } - cursor.moveToFirst(); - BordeauxSessionManager.Session s = getSessionFromCursor(cursor); - cursor.close(); - return s; - } - - void getAllSessions(ConcurrentHashMap sessions) { - Cursor cursor = mDbSessions.rawQuery("select * from ?;", new String[]{SESSION_TABLE}); - if (cursor == null) return; - cursor.moveToFirst(); - do { - String key = cursor.getString(cursor.getColumnIndex(COLUMN_KEY)); - BordeauxSessionManager.Session session = getSessionFromCursor(cursor); - sessions.put(key, session); - } while (cursor.moveToNext()); - } - - // remove all sessions that have the key that matches the given sql regular - // expression. - int removeSessions(String reKey) { - int nDeleteRows = mDbSessions.delete(SESSION_TABLE, "? like \"?\"", - new String[]{COLUMN_KEY, reKey}); - Log.i(TAG, "Number of rows in session table deleted: " + nDeleteRows); - return nDeleteRows; - } -} diff --git a/bordeaux/service/src/android/bordeaux/services/ClusterManager.java b/bordeaux/service/src/android/bordeaux/services/ClusterManager.java deleted file mode 100644 index 71e77a34e..000000000 --- a/bordeaux/service/src/android/bordeaux/services/ClusterManager.java +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.content.Context; -import android.location.Location; -import android.text.format.Time; -import android.util.Log; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; - -/** - * ClusterManager incrementally indentify representitve clusters from the input location - * stream. Clusters are updated online using leader based clustering algorithm. The input - * locations initially are kept by the clusters. Periodially, a cluster consolidating - * procedure is carried out to refine the cluster centers. After consolidation, the - * location data are released. - */ -public class ClusterManager { - - private static String TAG = "ClusterManager"; - - private static float LOCATION_CLUSTER_RADIUS = 25; // meter - - private static float SEMANTIC_CLUSTER_RADIUS = 75; // meter - - // Consoliate location clusters (and check for new semantic clusters) - // every 10 minutes (600 seconds). - private static final long CONSOLIDATE_INTERVAL = 600; - - // A location cluster can be labeled as a semantic cluster if it has been - // stayed for at least 10 minutes (600 seconds) within a day. - private static final long SEMANTIC_CLUSTER_THRESHOLD = 600; // seconds - - // Reset location cluters every 24 hours (86400 seconds). - private static final long LOCATION_REFRESH_PERIOD = 86400; // seconds - - private static String UNKNOWN_LOCATION = "Unknown Location"; - - private Location mLastLocation = null; - - private long mClusterDuration; - - private long mConsolidateRef = 0; - - private long mRefreshRef = 0; - - private long mSemanticClusterCount = 0; - - private ArrayList mLocationClusters = new ArrayList(); - - private ArrayList mSemanticClusters = new ArrayList(); - - private AggregatorRecordStorage mStorage; - - private static String SEMANTIC_TABLE = "SemanticTable"; - - private static String SEMANTIC_ID = "ID"; - - private static final String SEMANTIC_LONGITUDE = "Longitude"; - - private static final String SEMANTIC_LATITUDE = "Latitude"; - - private static final String SEMANTIC_DURATION = "Duration"; - - private static final String[] SEMANTIC_COLUMNS = - new String[]{ SEMANTIC_ID, - SEMANTIC_LONGITUDE, - SEMANTIC_LATITUDE, - SEMANTIC_DURATION, - TimeStatsAggregator.WEEKEND, - TimeStatsAggregator.WEEKDAY, - TimeStatsAggregator.MORNING, - TimeStatsAggregator.NOON, - TimeStatsAggregator.AFTERNOON, - TimeStatsAggregator.EVENING, - TimeStatsAggregator.NIGHT, - TimeStatsAggregator.LATENIGHT }; - - private static final int mFeatureValueStart = 4; - private static final int mFeatureValueEnd = 11; - - public ClusterManager(Context context) { - mStorage = new AggregatorRecordStorage(context, SEMANTIC_TABLE, SEMANTIC_COLUMNS); - - loadSemanticClusters(); - } - - public void addSample(Location location) { - float bestClusterDistance = Float.MAX_VALUE; - int bestClusterIndex = -1; - long lastDuration; - long currentTime = location.getTime() / 1000; // measure time in seconds - - if (mLastLocation != null) { - if (location.getTime() == mLastLocation.getTime()) { - return; - } - // get the duration spent in the last location - long duration = (location.getTime() - mLastLocation.getTime()) / 1000; - mClusterDuration += duration; - - Log.v(TAG, "sample duration: " + duration + - ", number of clusters: " + mLocationClusters.size()); - - synchronized (mLocationClusters) { - // add the last location to cluster. - // first find the cluster it belongs to. - for (int i = 0; i < mLocationClusters.size(); ++i) { - float distance = mLocationClusters.get(i).distanceToCenter(mLastLocation); - Log.v(TAG, "clulster " + i + " is within " + distance + " meters"); - if (distance < bestClusterDistance) { - bestClusterDistance = distance; - bestClusterIndex = i; - } - } - - // add the location to the selected cluster - if (bestClusterDistance < LOCATION_CLUSTER_RADIUS) { - mLocationClusters.get(bestClusterIndex).addSample(mLastLocation, duration); - } else { - // if it is far away from all existing clusters, create a new cluster. - LocationCluster cluster = new LocationCluster(mLastLocation, duration); - mLocationClusters.add(cluster); - } - } - } else { - mConsolidateRef = currentTime; - mRefreshRef = currentTime; - - if (mLocationClusters.isEmpty()) { - mClusterDuration = 0; - } - } - - long collectDuration = currentTime - mConsolidateRef; - Log.v(TAG, "collect duration: " + collectDuration); - if (collectDuration > CONSOLIDATE_INTERVAL) { - // TODO : conslidation takes time. move this to a separate thread later. - consolidateClusters(); - mConsolidateRef = currentTime; - - long refreshDuration = currentTime - mRefreshRef; - Log.v(TAG, "refresh duration: " + refreshDuration); - if (refreshDuration > LOCATION_REFRESH_PERIOD) { - updateSemanticClusters(); - mRefreshRef = currentTime; - } - saveSemanticClusters(); - } - - mLastLocation = location; - } - - private void consolidateClusters() { - synchronized (mSemanticClusters) { - LocationCluster locationCluster; - for (int i = mLocationClusters.size() - 1; i >= 0; --i) { - locationCluster = mLocationClusters.get(i); - locationCluster.consolidate(); - } - - // merge clusters whose regions are overlapped. note that after merge - // cluster center changes but cluster size remains unchanged. - for (int i = mLocationClusters.size() - 1; i >= 0; --i) { - locationCluster = mLocationClusters.get(i); - for (int j = i - 1; j >= 0; --j) { - float distance = - mLocationClusters.get(j).distanceToCluster(locationCluster); - if (distance < LOCATION_CLUSTER_RADIUS) { - mLocationClusters.get(j).absorbCluster(locationCluster); - mLocationClusters.remove(locationCluster); - } - } - } - Log.v(TAG, mLocationClusters.size() + " location clusters after consolidate"); - - // assign each candidate to a semantic cluster and check if new semantic - // clusters are found - for (LocationCluster candidate : mLocationClusters) { - if (candidate.hasSemanticId() || - candidate.hasSemanticClusterId() || - !candidate.passThreshold(SEMANTIC_CLUSTER_THRESHOLD)) { - continue; - } - - // find the closest semantic cluster - float bestClusterDistance = Float.MAX_VALUE; - String bestClusterId = "Unused Id"; - for (BaseCluster cluster : mSemanticClusters) { - float distance = cluster.distanceToCluster(candidate); - Log.v(TAG, distance + "distance to semantic cluster: " + - cluster.getSemanticId()); - - if (distance < bestClusterDistance) { - bestClusterDistance = distance; - bestClusterId = cluster.getSemanticId(); - } - } - - // if candidate doesn't belong to any semantic cluster, create a new - // semantic cluster - if (bestClusterDistance > SEMANTIC_CLUSTER_RADIUS) { - candidate.generateSemanticId(mSemanticClusterCount++); - mSemanticClusters.add(candidate); - } else { - candidate.setSemanticClusterId(bestClusterId); - } - } - Log.v(TAG, mSemanticClusters.size() + " semantic clusters after consolidate"); - } - } - - private void updateSemanticClusters() { - synchronized (mSemanticClusters) { - // create index to cluster map - HashMap semanticIdMap = - new HashMap(); - for (BaseCluster cluster : mSemanticClusters) { - // TODO: apply forgetting factor on existing semantic cluster stats, - // duration, histogram, etc. - cluster.forgetPastHistory(); - semanticIdMap.put(cluster.getSemanticId(), cluster); - } - - // assign each candidate to a semantic cluster - for (LocationCluster cluster : mLocationClusters) { - if (cluster.hasSemanticClusterId()) { - BaseCluster semanticCluster = - semanticIdMap.get(cluster.getSemanticClusterId()); - semanticCluster.absorbCluster(cluster); - } - } - // reset location clusters. - mLocationClusters.clear(); - } - } - - private void loadSemanticClusters() { - List > allData = mStorage.getAllData(); - HashMap histogram = new HashMap(); - - synchronized (mSemanticClusters) { - mSemanticClusters.clear(); - for (Map map : allData) { - String semanticId = map.get(SEMANTIC_ID); - double longitude = Double.parseDouble(map.get(SEMANTIC_LONGITUDE)); - double latitude = Double.parseDouble(map.get(SEMANTIC_LATITUDE)); - long duration = Long.parseLong(map.get(SEMANTIC_DURATION)); - BaseCluster cluster = - new BaseCluster(semanticId, longitude, latitude, duration); - - histogram.clear(); - for (int i = mFeatureValueStart; i <= mFeatureValueEnd; i++) { - String featureValue = SEMANTIC_COLUMNS[i]; - if (map.containsKey(featureValue)) { - histogram.put(featureValue, Long.valueOf(map.get(featureValue))); - } - } - cluster.setHistogram(histogram); - mSemanticClusters.add(cluster); - } - mSemanticClusterCount = mSemanticClusters.size(); - Log.e(TAG, "load " + mSemanticClusterCount + " semantic clusters."); - } - } - - private void saveSemanticClusters() { - HashMap rowFeatures = new HashMap(); - - mStorage.removeAllData(); - synchronized (mSemanticClusters) { - for (BaseCluster cluster : mSemanticClusters) { - rowFeatures.clear(); - rowFeatures.put(SEMANTIC_ID, cluster.getSemanticId()); - - rowFeatures.put(SEMANTIC_LONGITUDE, - String.valueOf(cluster.getCenterLongitude())); - rowFeatures.put(SEMANTIC_LATITUDE, - String.valueOf(cluster.getCenterLatitude())); - rowFeatures.put(SEMANTIC_DURATION, - String.valueOf(cluster.getDuration())); - - HashMap histogram = cluster.getHistogram(); - for (Map.Entry entry : histogram.entrySet()) { - rowFeatures.put(entry.getKey(), String.valueOf(entry.getValue())); - } - mStorage.addData(rowFeatures); - Log.e(TAG, "saving semantic cluster: " + rowFeatures); - } - } - } - - public String getSemanticLocation() { - String label = LocationStatsAggregator.UNKNOWN_LOCATION; - - // instead of using the last location, try acquiring the latest location. - if (mLastLocation != null) { - // TODO: use fast neatest neighbor search speed up location search - synchronized (mSemanticClusters) { - for (BaseCluster cluster: mSemanticClusters) { - if (cluster.distanceToCenter(mLastLocation) < SEMANTIC_CLUSTER_RADIUS) { - return cluster.getSemanticId(); - } - } - } - } - return label; - } - - public List getClusterNames() { - ArrayList clusters = new ArrayList(); - synchronized (mSemanticClusters) { - for (BaseCluster cluster: mSemanticClusters) { - clusters.add(cluster.getSemanticId()); - } - } - return clusters; - } -} diff --git a/bordeaux/service/src/android/bordeaux/services/FeatureAssembly.java b/bordeaux/service/src/android/bordeaux/services/FeatureAssembly.java deleted file mode 100644 index 75a4a9f28..000000000 --- a/bordeaux/service/src/android/bordeaux/services/FeatureAssembly.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.os.IBinder; -import android.util.Log; -import android.util.Pair; -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; -import java.util.List; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; -import java.util.Iterator; - -class FeatureAssembly { - private static final String TAG = "FeatureAssembly"; - private List mPossibleFeatures; - private HashSet mUseFeatures; - private HashSet > mUsePairedFeatures; - private AggregatorManager mAggregatorManager; - - public FeatureAssembly() { - mAggregatorManager = AggregatorManager.getInstance(); - mPossibleFeatures = Arrays.asList(mAggregatorManager.getListOfFeatures()); - mUseFeatures = new HashSet(); - mUsePairedFeatures = new HashSet >(); - } - - public boolean registerFeature(String s) { - if (mPossibleFeatures.contains(s)) { - mUseFeatures.add(s); - return true; - } else { - return false; - } - } - - public boolean registerFeaturePair(String[] features) { - if (features.length != 2 || - !mPossibleFeatures.contains(features[0]) || - !mPossibleFeatures.contains(features[1])) { - return false; - } else { - mUseFeatures.add(features[0]); - mUseFeatures.add(features[1]); - mUsePairedFeatures.add(Pair.create(features[0], features[1])); - return true; - } - } - - public Set getUsedFeatures() { - return (Set) mUseFeatures; - } - - public Map getFeatureMap() { - HashMap featureMap = new HashMap(); - - Iterator itr = mUseFeatures.iterator(); - while(itr.hasNext()) { - String f = (String) itr.next(); - Map features = mAggregatorManager.getDataMap(f); - - // TODO: sanity check for now. - if (features.size() > 1) { - throw new RuntimeException("Incorrect feature format extracted from aggregator."); - } - featureMap.putAll(features); - } - - if (!mUsePairedFeatures.isEmpty()) { - itr = mUsePairedFeatures.iterator(); - while(itr.hasNext()) { - Pair pair = (Pair) itr.next(); - if (featureMap.containsKey(pair.first) && - featureMap.containsKey(pair.second)) { - String key = pair.first + Predictor.FEATURE_SEPARATOR + pair.second; - String value = featureMap.get(pair.first) + Predictor.FEATURE_SEPARATOR + - featureMap.get(pair.second); - featureMap.put(key, value); - } - } - } - return (Map)featureMap; - } - - - public String augmentFeatureInputString(String s) { - String fs = s; - Iterator itr = mUseFeatures.iterator(); - while(itr.hasNext()) { - String f = (String) itr.next(); - fs = fs + "+" + mAggregatorManager.getDataMap(f).get(f); - } - return fs; - } -} diff --git a/bordeaux/service/src/android/bordeaux/services/IAggregatorManager.aidl b/bordeaux/service/src/android/bordeaux/services/IAggregatorManager.aidl deleted file mode 100644 index 06afb401f..000000000 --- a/bordeaux/service/src/android/bordeaux/services/IAggregatorManager.aidl +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.bordeaux.services.StringString; - -interface IAggregatorManager { - List getData(in String dataName); - - // TODO: remove the following interfaces in production - // they are only used for demo purpose - List getLocationClusters(); - List getTimeOfDayValues(); - List getDayOfWeekValues(); - // use "" to disable the fake location - boolean setFakeLocation(in String cluster); - // use "" to disable the fake time - boolean setFakeTimeOfDay(in String time_of_day); - // use "" to disable the fake day - boolean setFakeDayOfWeek(in String day_of_week); - // return whether the service is in fake mode - // it's in fake mode, if any of the location, time and day is fake - boolean getFakeMode(); -} diff --git a/bordeaux/service/src/android/bordeaux/services/IBordeauxLearner.java b/bordeaux/service/src/android/bordeaux/services/IBordeauxLearner.java deleted file mode 100644 index 114d29410..000000000 --- a/bordeaux/service/src/android/bordeaux/services/IBordeauxLearner.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.os.IBinder; - -interface IBordeauxLearner { - - interface ModelChangeCallback { - - public void modelChanged(IBordeauxLearner learner); - - } - - public byte [] getModel(); - - public boolean setModel(final byte [] modelData); - - public IBinder getBinder(); - - // call back for the learner model change - public void setModelChangeCallback(ModelChangeCallback callback); -} diff --git a/bordeaux/service/src/android/bordeaux/services/IBordeauxService.aidl b/bordeaux/service/src/android/bordeaux/services/IBordeauxService.aidl deleted file mode 100644 index 4aa4f08de..000000000 --- a/bordeaux/service/src/android/bordeaux/services/IBordeauxService.aidl +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.bordeaux.services.IBordeauxServiceCallback; - -/** - * Main learning interface of bordeaux service - * (running in another process). - */ -interface IBordeauxService { - /* Request a Ranker - */ - IBinder getRanker(String name); - - /* Request a MulticlassPA - */ - IBinder getClassifier(String name); - - /* Request to access AggregatorManager - */ - IBinder getAggregatorManager(); - /* Request a Predictor - */ - IBinder getPredictor(String name); - /** - * Often you want to allow a service to call back to its clients. - * This shows how to do so, by registering a callback interface with - * the service. - */ - void registerCallback(IBordeauxServiceCallback cb); - - /** - * Remove a previously registered callback interface. - */ - void unregisterCallback(IBordeauxServiceCallback cb); -} diff --git a/bordeaux/service/src/android/bordeaux/services/IBordeauxServiceCallback.aidl b/bordeaux/service/src/android/bordeaux/services/IBordeauxServiceCallback.aidl deleted file mode 100644 index ad87ceeda..000000000 --- a/bordeaux/service/src/android/bordeaux/services/IBordeauxServiceCallback.aidl +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -/** - * Example of a callback interface used by IRemoteService to send - * synchronous notifications back to its clients. Note that this is a - * one-way interface so the server does not block waiting for the client. - */ -oneway interface IBordeauxServiceCallback { - /** - * Called when the service has a new value for you. - */ - void valueChanged(int value); -} diff --git a/bordeaux/service/src/android/bordeaux/services/ILearning_MulticlassPA.aidl b/bordeaux/service/src/android/bordeaux/services/ILearning_MulticlassPA.aidl deleted file mode 100644 index a62eb788b..000000000 --- a/bordeaux/service/src/android/bordeaux/services/ILearning_MulticlassPA.aidl +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -/** - * Example of a secondary interface associated with a service. (Note that - * the interface itself doesn't impact, it is just a matter of how you - * retrieve it from the service.) - */ -import android.bordeaux.services.IntFloat; - -interface ILearning_MulticlassPA { - void TrainOneSample(in List sample, int target); - int Classify(in List sample); -} diff --git a/bordeaux/service/src/android/bordeaux/services/ILearning_StochasticLinearRanker.aidl b/bordeaux/service/src/android/bordeaux/services/ILearning_StochasticLinearRanker.aidl deleted file mode 100644 index f89ce0aef..000000000 --- a/bordeaux/service/src/android/bordeaux/services/ILearning_StochasticLinearRanker.aidl +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -/** - * Example of a secondary interface associated with a service. (Note that - * the interface itself doesn't impact, it is just a matter of how you - * retrieve it from the service.) - */ -import android.bordeaux.services.StringFloat; - - -interface ILearning_StochasticLinearRanker { - - boolean UpdateClassifier(in List sample_1, in List sample_2); - float ScoreSample(in List sample); - void ResetRanker(); - boolean SetModelPriorWeight(in List weight); - boolean SetModelParameter(in String key, in String value); -} diff --git a/bordeaux/service/src/android/bordeaux/services/IPredictor.aidl b/bordeaux/service/src/android/bordeaux/services/IPredictor.aidl deleted file mode 100644 index 0986cd0a7..000000000 --- a/bordeaux/service/src/android/bordeaux/services/IPredictor.aidl +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.bordeaux.services.StringFloat; - -interface IPredictor { - boolean setPredictorParameter(in String key, in String value); - void pushNewSample(in String sampleName); - void resetPredictor(); - List getTopCandidates(in int topK); -} diff --git a/bordeaux/service/src/android/bordeaux/services/IntFloat.aidl b/bordeaux/service/src/android/bordeaux/services/IntFloat.aidl deleted file mode 100644 index 3b561aecb..000000000 --- a/bordeaux/service/src/android/bordeaux/services/IntFloat.aidl +++ /dev/null @@ -1,3 +0,0 @@ -package android.bordeaux.services; - -parcelable IntFloat; diff --git a/bordeaux/service/src/android/bordeaux/services/IntFloat.java b/bordeaux/service/src/android/bordeaux/services/IntFloat.java deleted file mode 100644 index b9803264c..000000000 --- a/bordeaux/service/src/android/bordeaux/services/IntFloat.java +++ /dev/null @@ -1,40 +0,0 @@ -package android.bordeaux.services; - -import android.os.Parcel; -import android.os.Parcelable; - -public final class IntFloat implements Parcelable { - public int index; - public float value; - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - public IntFloat createFromParcel(Parcel in) { - return new IntFloat(in); - } - - public IntFloat[] newArray(int size) { - return new IntFloat[size]; - } - }; - - public IntFloat() { - } - - private IntFloat(Parcel in) { - readFromParcel(in); - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel out, int flags) { - out.writeInt(index); - out.writeFloat(value); - } - - public void readFromParcel(Parcel in) { - index = in.readInt(); - value = in.readFloat(); - } -} diff --git a/bordeaux/service/src/android/bordeaux/services/Learning_MulticlassPA.java b/bordeaux/service/src/android/bordeaux/services/Learning_MulticlassPA.java deleted file mode 100644 index 438398d0f..000000000 --- a/bordeaux/service/src/android/bordeaux/services/Learning_MulticlassPA.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.bordeaux.learning.MulticlassPA; -import android.os.IBinder; - -import java.util.List; -import java.util.ArrayList; - -public class Learning_MulticlassPA extends ILearning_MulticlassPA.Stub - implements IBordeauxLearner { - private MulticlassPA mMulticlassPA_learner; - private ModelChangeCallback modelChangeCallback = null; - - class IntFloatArray { - int[] indexArray; - float[] floatArray; - }; - - private IntFloatArray splitIntFloatArray(List sample) { - IntFloatArray splited = new IntFloatArray(); - ArrayList s = (ArrayList)sample; - splited.indexArray = new int[s.size()]; - splited.floatArray = new float[s.size()]; - for (int i = 0; i < s.size(); i++) { - splited.indexArray[i] = s.get(i).index; - splited.floatArray[i] = s.get(i).value; - } - return splited; - } - - public Learning_MulticlassPA() { - mMulticlassPA_learner = new MulticlassPA(2, 2, 0.001f); - } - - // Beginning of the IBordeauxLearner Interface implementation - public byte [] getModel() { - return null; - } - - public boolean setModel(final byte [] modelData) { - return false; - } - - public IBinder getBinder() { - return this; - } - - public void setModelChangeCallback(ModelChangeCallback callback) { - modelChangeCallback = callback; - } - // End of IBordeauxLearner Interface implemenation - - // This implementation, combines training and prediction in one step. - // The return value is the prediction value for the supplied sample. It - // also update the model with the current sample. - public void TrainOneSample(List sample, int target) { - IntFloatArray splited = splitIntFloatArray(sample); - mMulticlassPA_learner.sparseTrainOneExample(splited.indexArray, - splited.floatArray, - target); - if (modelChangeCallback != null) { - modelChangeCallback.modelChanged(this); - } - } - - public int Classify(List sample) { - IntFloatArray splited = splitIntFloatArray(sample); - int prediction = mMulticlassPA_learner.sparseGetClass(splited.indexArray, - splited.floatArray); - return prediction; - } - -} diff --git a/bordeaux/service/src/android/bordeaux/services/Learning_StochasticLinearRanker.java b/bordeaux/service/src/android/bordeaux/services/Learning_StochasticLinearRanker.java deleted file mode 100644 index c648bd2d1..000000000 --- a/bordeaux/service/src/android/bordeaux/services/Learning_StochasticLinearRanker.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.bordeaux.learning.StochasticLinearRanker; -import android.bordeaux.services.IBordeauxLearner.ModelChangeCallback; -import android.os.IBinder; -import android.util.Log; -import java.util.List; -import java.util.ArrayList; -import java.io.*; -import java.lang.ClassNotFoundException; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.List; -import java.util.Scanner; -import java.io.ByteArrayOutputStream; -import java.util.HashMap; -import java.util.Map; - -public class Learning_StochasticLinearRanker extends ILearning_StochasticLinearRanker.Stub - implements IBordeauxLearner { - - private final String TAG = "ILearning_StochasticLinearRanker"; - private StochasticLinearRankerWithPrior mLearningSlRanker = null; - private ModelChangeCallback modelChangeCallback = null; - - public Learning_StochasticLinearRanker(){ - } - - public void ResetRanker(){ - if (mLearningSlRanker == null) - mLearningSlRanker = new StochasticLinearRankerWithPrior(); - mLearningSlRanker.resetRanker(); - } - - public boolean UpdateClassifier(List sample_1, List sample_2){ - ArrayList temp_1 = (ArrayList)sample_1; - String[] keys_1 = new String[temp_1.size()]; - float[] values_1 = new float[temp_1.size()]; - for (int i = 0; i < temp_1.size(); i++){ - keys_1[i] = temp_1.get(i).key; - values_1[i] = temp_1.get(i).value; - } - ArrayList temp_2 = (ArrayList)sample_2; - String[] keys_2 = new String[temp_2.size()]; - float[] values_2 = new float[temp_2.size()]; - for (int i = 0; i < temp_2.size(); i++){ - keys_2[i] = temp_2.get(i).key; - values_2[i] = temp_2.get(i).value; - } - if (mLearningSlRanker == null) - mLearningSlRanker = new StochasticLinearRankerWithPrior(); - boolean res = mLearningSlRanker.updateClassifier(keys_1,values_1,keys_2,values_2); - if (res && modelChangeCallback != null) { - modelChangeCallback.modelChanged(this); - } - return res; - } - - public float ScoreSample(List sample) { - ArrayList temp = (ArrayList)sample; - String[] keys = new String[temp.size()]; - float[] values = new float[temp.size()]; - for (int i = 0; i < temp.size(); i++){ - keys[i] = temp.get(i).key; - values[i] = temp.get(i).value; - } - if (mLearningSlRanker == null) - mLearningSlRanker = new StochasticLinearRankerWithPrior(); - return mLearningSlRanker.scoreSample(keys,values); - } - - public boolean SetModelPriorWeight(List sample) { - ArrayList temp = (ArrayList)sample; - HashMap weights = new HashMap(); - for (int i = 0; i < temp.size(); i++) - weights.put(temp.get(i).key, temp.get(i).value); - if (mLearningSlRanker == null) - mLearningSlRanker = new StochasticLinearRankerWithPrior(); - return mLearningSlRanker.setModelPriorWeights(weights); - } - - public boolean SetModelParameter(String key, String value) { - if (mLearningSlRanker == null) - mLearningSlRanker = new StochasticLinearRankerWithPrior(); - return mLearningSlRanker.setModelParameter(key,value); - } - - // Beginning of the IBordeauxLearner Interface implementation - public byte [] getModel() { - if (mLearningSlRanker == null) - mLearningSlRanker = new StochasticLinearRankerWithPrior(); - StochasticLinearRankerWithPrior.Model model = mLearningSlRanker.getModel(); - try { - ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); - ObjectOutputStream objStream = new ObjectOutputStream(byteStream); - objStream.writeObject(model); - //return byteStream.toByteArray(); - byte[] bytes = byteStream.toByteArray(); - return bytes; - } catch (IOException e) { - throw new RuntimeException("Can't get model"); - } - } - - public boolean setModel(final byte [] modelData) { - try { - ByteArrayInputStream input = new ByteArrayInputStream(modelData); - ObjectInputStream objStream = new ObjectInputStream(input); - StochasticLinearRankerWithPrior.Model model = - (StochasticLinearRankerWithPrior.Model) objStream.readObject(); - if (mLearningSlRanker == null) - mLearningSlRanker = new StochasticLinearRankerWithPrior(); - boolean res = mLearningSlRanker.loadModel(model); - return res; - } catch (IOException e) { - throw new RuntimeException("Can't load model"); - } catch (ClassNotFoundException e) { - throw new RuntimeException("Learning class not found"); - } - } - - public IBinder getBinder() { - return this; - } - - public void setModelChangeCallback(ModelChangeCallback callback) { - modelChangeCallback = callback; - } - // End of IBordeauxLearner Interface implemenation -} diff --git a/bordeaux/service/src/android/bordeaux/services/LocationCluster.java b/bordeaux/service/src/android/bordeaux/services/LocationCluster.java deleted file mode 100644 index c9f753f76..000000000 --- a/bordeaux/service/src/android/bordeaux/services/LocationCluster.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.bordeaux.services; - -import android.location.Location; -import android.text.format.Time; -import android.util.Log; - -import java.lang.Math; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -public class LocationCluster extends BaseCluster { - public static String TAG = "LocationCluster"; - - private ArrayList mLocations = new ArrayList(); - private HashMap mNewHistogram = new HashMap(); - - private String mSemanticClusterId = null; - - public void setSemanticClusterId(String semanticClusterId) { - mSemanticClusterId = semanticClusterId; - } - - public String getSemanticClusterId() { - return mSemanticClusterId; - } - - public boolean hasSemanticClusterId() { - return mSemanticClusterId != null; - } - - // TODO: make it a singleton class - public LocationCluster(Location location, long duration) { - super(location); - addSample(location, duration); - } - - public void addSample(Location location, long duration) { - updateTemporalHistogram(location.getTime(), duration); - - // use time field to store duation of this location - // TODO: extend Location class with additional field for this. - location.setTime(duration); - mLocations.add(location); - } - - public void consolidate() { - // If there is no new location added during this period, do nothing. - if (mLocations.size() == 0) { - return; - } - - double[] newCenter = {0f, 0f, 0f}; - long newDuration = 0l; - // update cluster center - for (Location location : mLocations) { - double[] vector = getLocationVector(location); - long duration = location.getTime(); // in seconds - - if (duration == 0) { - throw new RuntimeException("location duration is zero"); - } - - newDuration += duration; - for (int i = 0; i < VECTOR_LENGTH; ++i) { - newCenter[i] += vector[i] * duration; - } - } - if (newDuration == 0l) { - throw new RuntimeException("new duration is zero!"); - } - for (int i = 0; i < VECTOR_LENGTH; ++i) { - newCenter[i] /= newDuration; - } - // remove location data - mLocations.clear(); - - // The updated center is the weighted average of the existing and the new - // centers. Note that if the cluster is consolidated for the first time, - // the weight for the existing cluster would be zero. - averageCenter(newCenter, newDuration); - - // update histogram - for (Map.Entry entry : mNewHistogram.entrySet()) { - String timeLabel = entry.getKey(); - long duration = entry.getValue(); - if (mHistogram.containsKey(timeLabel)) { - duration += mHistogram.get(timeLabel); - } - mHistogram.put(timeLabel, duration); - } - mDuration += newDuration; - mNewHistogram.clear(); - } - - /* - * if the new created cluster whose covered area overlaps with any existing - * cluster move the center away from that cluster till there is no overlap. - */ - public void moveAwayCluster(LocationCluster cluster, float distance) { - double[] vector = new double[VECTOR_LENGTH]; - - double dot = 0f; - for (int i = 0; i < VECTOR_LENGTH; ++i) { - dot += mCenter[i] * cluster.mCenter[i]; - } - double norm = 0f; - for (int i = 0; i < VECTOR_LENGTH; ++i) { - vector[i] = mCenter[i] - dot * cluster.mCenter[i]; - norm += vector[i] * vector[i]; - } - norm = Math.sqrt(norm); - - double radian = distance / EARTH_RADIUS; - for (int i = 0; i < VECTOR_LENGTH; ++i) { - mCenter[i] = cluster.mCenter[i] * Math.cos(radian) + - (vector[i] / norm) * Math.sin(radian); - } - } - - private void updateTemporalHistogram(long time, long duration) { - HashMap timeFeatures = TimeStatsAggregator.getAllTimeFeatures(time); - - String timeOfWeek = timeFeatures.get(TimeStatsAggregator.TIME_OF_WEEK); - long totalDuration = (mNewHistogram.containsKey(timeOfWeek)) ? - mNewHistogram.get(timeOfWeek) + duration : duration; - mNewHistogram.put(timeOfWeek, totalDuration); - - String timeOfDay = timeFeatures.get(TimeStatsAggregator.TIME_OF_DAY); - totalDuration = (mNewHistogram.containsKey(timeOfDay)) ? - mNewHistogram.get(timeOfDay) + duration : duration; - mNewHistogram.put(timeOfDay, totalDuration); - } -} diff --git a/bordeaux/service/src/android/bordeaux/services/LocationStatsAggregator.java b/bordeaux/service/src/android/bordeaux/services/LocationStatsAggregator.java deleted file mode 100644 index 6f792be77..000000000 --- a/bordeaux/service/src/android/bordeaux/services/LocationStatsAggregator.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.location.Criteria; -import android.location.Location; -import android.location.LocationListener; -import android.location.LocationManager; -import android.location.LocationProvider; -import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Message; -import android.os.Process; -import android.os.SystemClock; -import android.text.format.Time; -import android.util.Log; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -// TODO: add functionality to detect speed (use GPS) when needed -// withouth draining the battery quickly -public class LocationStatsAggregator extends Aggregator { - final String TAG = "LocationStatsAggregator"; - public static final String CURRENT_LOCATION = "Current Location"; - public static final String CURRENT_SPEED = "Current Speed"; - public static final String UNKNOWN_LOCATION = "Unknown Location"; - - private static final long REPEAT_INTERVAL = 120000; - - private static final long FRESH_THRESHOLD = 90000; - - private static final int LOCATION_CHANGE = 1; - - // record time when the location provider is set - private long mProviderSetTime; - - private Handler mHandler; - private HandlerThread mHandlerThread; - private AlarmManager mAlarmManager; - private LocationManager mLocationManager; - - private ClusterManager mClusterManager; - - private Criteria mCriteria = new Criteria(); - - private LocationUpdater mLocationUpdater; - - private Context mContext; - private PendingIntent mPendingIntent; - - // Fake location, used for testing. - private String mFakeLocation = null; - - public LocationStatsAggregator(final Context context) { - mLocationManager = - (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); - mAlarmManager = - (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - - setClusteringThread(context); - - mCriteria.setAccuracy(Criteria.ACCURACY_COARSE); - mCriteria.setPowerRequirement(Criteria.POWER_LOW); - /* - mCriteria.setAltitudeRequired(false); - mCriteria.setBearingRequired(false); - mCriteria.setSpeedRequired(true); - */ - mCriteria.setCostAllowed(true); - - - IntentFilter filter = new IntentFilter(LocationUpdater.LOCATION_UPDATE); - mLocationUpdater = new LocationUpdater(); - context.registerReceiver(mLocationUpdater, filter); - - Intent intent = new Intent(LocationUpdater.LOCATION_UPDATE); - - mContext = context; - mPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0); - - mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, - SystemClock.elapsedRealtime() + 30000, // - REPEAT_INTERVAL, - mPendingIntent); - } - - public void release() { - mContext.unregisterReceiver(mLocationUpdater); - mAlarmManager.cancel(mPendingIntent); - } - - public String[] getListOfFeatures(){ - String[] list = { CURRENT_LOCATION } ; - return list; - } - - public Map getFeatureValue(String featureName) { - HashMap feature = new HashMap(); - - if (featureName.equals(CURRENT_LOCATION)) { - // TODO: check last known location first before sending out location request. - /* - Location location = - mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); - */ - String location = mClusterManager.getSemanticLocation(); - if (!location.equals(UNKNOWN_LOCATION)) { - if (mFakeLocation != null) { - feature.put(CURRENT_LOCATION, mFakeLocation); - } else { - feature.put(CURRENT_LOCATION, location); - } - } - } - return (Map) feature; - } - - public List getClusterNames() { - return mClusterManager.getClusterNames(); - } - - // set a fake location using cluster name. - // Set an empty string "" to disable the fake location - public void setFakeLocation(String name) { - if (name != null && name.length() != 0) - mFakeLocation = name; - else mFakeLocation = null; - } - - private Location getLastKnownLocation() { - List providers = mLocationManager.getAllProviders(); - Location bestResult = null; - float bestAccuracy = Float.MAX_VALUE; - long bestTime; - - // get the latest location data - long currTime = System.currentTimeMillis(); - for (String provider : providers) { - Location location = mLocationManager.getLastKnownLocation(provider); - - if (location != null) { - float accuracy = location.getAccuracy(); - long time = location.getTime(); - - if (currTime - time < FRESH_THRESHOLD && accuracy < bestAccuracy) { - bestResult = location; - bestAccuracy = accuracy; - bestTime = time; - } - } - } - if (bestResult != null) { - Log.i(TAG, "found location for free: " + bestResult); - } - return bestResult; - } - - private class LocationUpdater extends BroadcastReceiver { - String TAG = "LocationUpdater"; - - public static final String LOCATION_UPDATE = "android.bordeaux.services.LOCATION_UPDATE"; - - @Override - public void onReceive(Context context, Intent intent) { - Location location = getLastKnownLocation(); - - if (location == null) { - String provider = mLocationManager.getBestProvider(mCriteria, true); - Log.i(TAG, "Best Available Location Provider: " + provider); - mLocationManager.requestSingleUpdate(provider, mLocationListener, - mHandlerThread.getLooper()); - } else { - mHandler.sendMessage(mHandler.obtainMessage(LOCATION_CHANGE, location)); - } - } - } - - private void setClusteringThread(Context context) { - mClusterManager = new ClusterManager(context); - - mHandlerThread = new HandlerThread("Location Handler", - Process.THREAD_PRIORITY_BACKGROUND); - mHandlerThread.start(); - mHandler = new Handler(mHandlerThread.getLooper()) { - - @Override - public void handleMessage(Message msg) { - if (!(msg.obj instanceof Location)) { - return; - } - Location location = (Location) msg.obj; - switch(msg.what) { - case LOCATION_CHANGE: - mClusterManager.addSample(location); - break; - default: - super.handleMessage(msg); - } - } - }; - } - - private final LocationListener mLocationListener = new LocationListener() { - private static final String TAG = "LocationListener"; - - public void onLocationChanged(Location location) { - mHandler.sendMessage(mHandler.obtainMessage(LOCATION_CHANGE, location)); - mLocationManager.removeUpdates(this); - } - - public void onStatusChanged(String provider, int status, Bundle extras) { } - - public void onProviderEnabled(String provider) { } - - public void onProviderDisabled(String provider) { } - }; -} diff --git a/bordeaux/service/src/android/bordeaux/services/MotionStatsAggregator.java b/bordeaux/service/src/android/bordeaux/services/MotionStatsAggregator.java deleted file mode 100644 index c34779e5e..000000000 --- a/bordeaux/service/src/android/bordeaux/services/MotionStatsAggregator.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.util.Log; -import java.util.HashMap; -import java.util.Map; - -public class MotionStatsAggregator extends Aggregator { - final String TAG = "MotionStatsAggregator"; - public static final String CURRENT_MOTION = "Current Motion"; - public String[] getListOfFeatures(){ - String [] list = new String[1]; - list[0] = CURRENT_MOTION; - return list; - } - public Map getFeatureValue(String featureName) { - HashMap m = new HashMap(); - if (featureName.equals(CURRENT_MOTION)) - m.put(CURRENT_MOTION,"Running"); //TODO maybe use clustering for user motion - else - Log.e(TAG, "There is no motion feature called " + featureName); - return (Map) m; - } -} diff --git a/bordeaux/service/src/android/bordeaux/services/Predictor.java b/bordeaux/service/src/android/bordeaux/services/Predictor.java deleted file mode 100644 index 9d9047a86..000000000 --- a/bordeaux/service/src/android/bordeaux/services/Predictor.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you my not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.os.IBinder; -import android.util.Log; -import java.util.HashMap; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.HashSet; -import java.util.Iterator; -import java.io.Serializable; -import java.io.*; -import java.lang.Boolean; -import android.bordeaux.services.FeatureAssembly; -import android.bordeaux.learning.HistogramPredictor; - -/** - * This is interface to implement Prediction based on histogram that - * uses predictor_histogram from learnerning section - */ -public class Predictor extends IPredictor.Stub - implements IBordeauxLearner { - private final String TAG = "Predictor"; - private ModelChangeCallback modelChangeCallback = null; - - private FeatureAssembly mFeatureAssembly = new FeatureAssembly(); - - public static final String SET_FEATURE = "SetFeature"; - public static final String SET_PAIRED_FEATURES = "SetPairedFeatures"; - public static final String FEATURE_SEPARATOR = ":"; - public static final String USE_HISTORY = "UseHistory"; - public static final String PREVIOUS_SAMPLE = "PreviousSample"; - - private boolean mUseHistory = false; - private long mHistorySpan = 0; - private String mPrevSample; - private long mPrevSampleTime; - - // TODO: blacklist should be set outside Bordeaux service! - private static final String[] APP_BLACKLIST = { - "com.android.contacts", - "com.android.chrome", - "com.android.providers.downloads.ui", - "com.android.settings", - "com.android.vending", - "com.android.mms", - "com.google.android.gm", - "com.google.android.gallery3d", - "com.google.android.apps.googlevoice", - }; - - private HistogramPredictor mPredictor = new HistogramPredictor(APP_BLACKLIST); - - - /** - * Reset the Predictor - */ - public void resetPredictor(){ - mPredictor.resetPredictor(); - - if (modelChangeCallback != null) { - modelChangeCallback.modelChanged(this); - } - } - - /** - * Input is a sampleName e.g.action name. This input is then augmented with requested build-in - * features such as time and location to create sampleFeatures. The sampleFeatures is then - * pushed to the histogram - */ - public void pushNewSample(String sampleName) { - Map sampleFeatures = getSampleFeatures(); - Log.i(TAG, "pushNewSample " + sampleName + ": " + sampleFeatures); - - // TODO: move to the end of the function? - mPrevSample = sampleName; - mPrevSampleTime = System.currentTimeMillis(); - - mPredictor.addSample(sampleName, sampleFeatures); - if (modelChangeCallback != null) { - modelChangeCallback.modelChanged(this); - } - } - - private Map getSampleFeatures() { - Map sampleFeatures = mFeatureAssembly.getFeatureMap(); - long currTime = System.currentTimeMillis(); - - if (mUseHistory && mPrevSample != null && - ((currTime - mPrevSampleTime) < mHistorySpan)) { - sampleFeatures.put(PREVIOUS_SAMPLE, mPrevSample); - } - - return sampleFeatures; - } - - // TODO: getTopK samples instead get scord for debugging only - /** - * return probabilty of an exmple using the histogram - */ - public List getTopCandidates(int topK) { - Map features = getSampleFeatures(); - List > topApps = mPredictor.findTopClasses(features, topK); - - int listSize = topApps.size(); - ArrayList result = new ArrayList(listSize); - for (int i = 0; i < listSize; ++i) { - Map.Entry entry = topApps.get(i); - result.add(new StringFloat(entry.getKey(), entry.getValue().floatValue())); - } - return result; - } - - /** - * Set parameters for 1) using History in probability estimations e.g. consider the last event - * and 2) featureAssembly e.g. time and location. - */ - public boolean setPredictorParameter(String key, String value) { - Log.i(TAG, "setParameter : " + key + ", " + value); - boolean result = true; - if (key.equals(SET_FEATURE)) { - result = mFeatureAssembly.registerFeature(value); - if (!result) { - Log.e(TAG,"Setting on feauture: " + value + " which is not available"); - } - } else if (key.equals(SET_PAIRED_FEATURES)) { - String[] features = value.split(FEATURE_SEPARATOR); - result = mFeatureAssembly.registerFeaturePair(features); - if (!result) { - Log.e(TAG,"Setting feauture pair: " + value + " is not valid"); - } - } else if (key.equals(USE_HISTORY)) { - mUseHistory = true; - mHistorySpan = Long.parseLong(value); - } else { - Log.e(TAG,"Setting parameter " + key + " with " + value + " is not valid"); - } - return result; - } - - // Beginning of the IBordeauxLearner Interface implementation - public byte [] getModel() { - return mPredictor.getModel(); - } - - public boolean setModel(final byte [] modelData) { - return mPredictor.setModel(modelData); - } - - public IBinder getBinder() { - return this; - } - - public void setModelChangeCallback(ModelChangeCallback callback) { - modelChangeCallback = callback; - } - // End of IBordeauxLearner Interface implemenation -} diff --git a/bordeaux/service/src/android/bordeaux/services/StochasticLinearRankerWithPrior.java b/bordeaux/service/src/android/bordeaux/services/StochasticLinearRankerWithPrior.java deleted file mode 100644 index fd56a2fd6..000000000 --- a/bordeaux/service/src/android/bordeaux/services/StochasticLinearRankerWithPrior.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; -import android.util.Log; - -import android.bordeaux.learning.StochasticLinearRanker; -import java.util.HashMap; -import java.util.Map; -import java.io.Serializable; - -public class StochasticLinearRankerWithPrior extends StochasticLinearRanker { - private final String TAG = "StochasticLinearRankerWithPrior"; - private final float EPSILON = 0.0001f; - - /* If the is parameter is true, the final score would be a - linear combination of user model and prior model */ - private final String USE_PRIOR = "usePriorInformation"; - - /* When prior model is used, this parmaeter will set the mixing factor, alpha. */ - private final String SET_ALPHA = "setAlpha"; - - /* When prior model is used, If this parameter is true then algorithm will use - the automatic cross validated alpha for mixing user model and prior model */ - private final String USE_AUTO_ALPHA = "useAutoAlpha"; - - /* When automatic cross validation is active, this parameter will - set the forget rate in cross validation. */ - private final String SET_FORGET_RATE = "setForgetRate"; - - /* When automatic cross validation is active, this parameter will - set the minium number of required training pairs before using the user model */ - private final String SET_MIN_TRAIN_PAIR = "setMinTrainingPair"; - - private final String SET_USER_PERF = "setUserPerformance"; - private final String SET_PRIOR_PERF = "setPriorPerformance"; - private final String SET_NUM_TRAIN_PAIR = "setNumberTrainingPairs"; - private final String SET_AUTO_ALPHA = "setAutoAlpha"; - - - - private HashMap mPriorWeights = new HashMap(); - private float mAlpha = 0; - private float mAutoAlpha = 0; - private float mForgetRate = 0; - private float mUserRankerPerf = 0; - private float mPriorRankerPerf = 0; - private int mMinReqTrainingPair = 0; - private int mNumTrainPair = 0; - private boolean mUsePrior = false; - private boolean mUseAutoAlpha = false; - - static public class Model implements Serializable { - public StochasticLinearRanker.Model uModel = new StochasticLinearRanker.Model(); - public HashMap priorWeights = new HashMap(); - public HashMap priorParameters = new HashMap(); - } - - @Override - public void resetRanker(){ - super.resetRanker(); - mPriorWeights.clear(); - mAlpha = 0; - mAutoAlpha = 0; - mForgetRate = 0; - mMinReqTrainingPair = 0; - mUserRankerPerf = 0; - mPriorRankerPerf = 0; - mNumTrainPair = 0; - mUsePrior = false; - mUseAutoAlpha = false; - } - - @Override - public float scoreSample(String[] keys, float[] values) { - if (!mUsePrior){ - return super.scoreSample(keys, values); - } else { - if (mUseAutoAlpha) { - if (mNumTrainPair > mMinReqTrainingPair) - return (1 - mAutoAlpha) * super.scoreSample(keys,values) + - mAutoAlpha * priorScoreSample(keys,values); - else - return priorScoreSample(keys,values); - } else - return (1 - mAlpha) * super.scoreSample(keys,values) + - mAlpha * priorScoreSample(keys,values); - } - } - - public float priorScoreSample(String[] keys, float[] values) { - float score = 0; - for (int i=0; i< keys.length; i++){ - if (mPriorWeights.get(keys[i]) != null ) - score = score + mPriorWeights.get(keys[i]) * values[i]; - } - return score; - } - - @Override - public boolean updateClassifier(String[] keys_positive, - float[] values_positive, - String[] keys_negative, - float[] values_negative){ - if (mUsePrior && mUseAutoAlpha && (mNumTrainPair > mMinReqTrainingPair)) - updateAutoAlpha(keys_positive, values_positive, keys_negative, values_negative); - mNumTrainPair ++; - return super.updateClassifier(keys_positive, values_positive, - keys_negative, values_negative); - } - - void updateAutoAlpha(String[] keys_positive, - float[] values_positive, - String[] keys_negative, - float[] values_negative) { - float positiveUserScore = super.scoreSample(keys_positive, values_positive); - float negativeUserScore = super.scoreSample(keys_negative, values_negative); - float positivePriorScore = priorScoreSample(keys_positive, values_positive); - float negativePriorScore = priorScoreSample(keys_negative, values_negative); - float userDecision = 0; - float priorDecision = 0; - if (positiveUserScore > negativeUserScore) - userDecision = 1; - if (positivePriorScore > negativePriorScore) - priorDecision = 1; - mUserRankerPerf = (1 - mForgetRate) * mUserRankerPerf + userDecision; - mPriorRankerPerf = (1 - mForgetRate) * mPriorRankerPerf + priorDecision; - mAutoAlpha = (mPriorRankerPerf + EPSILON) / (mUserRankerPerf + mPriorRankerPerf + EPSILON); - } - - public Model getModel(){ - Model m = new Model(); - m.uModel = super.getUModel(); - m.priorWeights.putAll(mPriorWeights); - m.priorParameters.put(SET_ALPHA, String.valueOf(mAlpha)); - m.priorParameters.put(SET_AUTO_ALPHA, String.valueOf(mAutoAlpha)); - m.priorParameters.put(SET_FORGET_RATE, String.valueOf(mForgetRate)); - m.priorParameters.put(SET_MIN_TRAIN_PAIR, String.valueOf(mMinReqTrainingPair)); - m.priorParameters.put(SET_USER_PERF, String.valueOf(mUserRankerPerf)); - m.priorParameters.put(SET_PRIOR_PERF, String.valueOf(mPriorRankerPerf)); - m.priorParameters.put(SET_NUM_TRAIN_PAIR, String.valueOf(mNumTrainPair)); - m.priorParameters.put(USE_AUTO_ALPHA, String.valueOf(mUseAutoAlpha)); - m.priorParameters.put(USE_PRIOR, String.valueOf(mUsePrior)); - return m; - } - - public boolean loadModel(Model m) { - mPriorWeights.clear(); - mPriorWeights.putAll(m.priorWeights); - for (Map.Entry e : m.priorParameters.entrySet()) { - boolean res = setModelParameter(e.getKey(), e.getValue()); - if (!res) return false; - } - return super.loadModel(m.uModel); - } - - public boolean setModelPriorWeights(HashMap pw){ - mPriorWeights.clear(); - mPriorWeights.putAll(pw); - return true; - } - - public boolean setModelParameter(String key, String value){ - if (key.equals(USE_AUTO_ALPHA)){ - mUseAutoAlpha = Boolean.parseBoolean(value); - } else if (key.equals(USE_PRIOR)){ - mUsePrior = Boolean.parseBoolean(value); - } else if (key.equals(SET_ALPHA)){ - mAlpha = Float.valueOf(value.trim()).floatValue(); - }else if (key.equals(SET_AUTO_ALPHA)){ - mAutoAlpha = Float.valueOf(value.trim()).floatValue(); - }else if (key.equals(SET_FORGET_RATE)){ - mForgetRate = Float.valueOf(value.trim()).floatValue(); - }else if (key.equals(SET_MIN_TRAIN_PAIR)){ - mMinReqTrainingPair = (int) Float.valueOf(value.trim()).floatValue(); - }else if (key.equals(SET_USER_PERF)){ - mUserRankerPerf = Float.valueOf(value.trim()).floatValue(); - }else if (key.equals(SET_PRIOR_PERF)){ - mPriorRankerPerf = Float.valueOf(value.trim()).floatValue(); - }else if (key.equals(SET_NUM_TRAIN_PAIR)){ - mNumTrainPair = (int) Float.valueOf(value.trim()).floatValue(); - }else - return super.setModelParameter(key, value); - return true; - } - - public void print(Model m){ - super.print(m.uModel); - String Spw = ""; - for (Map.Entry e : m.priorWeights.entrySet()) - Spw = Spw + "<" + e.getKey() + "," + e.getValue() + "> "; - Log.i(TAG, "Prior model is " + Spw); - String Spp = ""; - for (Map.Entry e : m.priorParameters.entrySet()) - Spp = Spp + "<" + e.getKey() + "," + e.getValue() + "> "; - Log.i(TAG, "Prior parameters are " + Spp); - } -} diff --git a/bordeaux/service/src/android/bordeaux/services/StringFloat.aidl b/bordeaux/service/src/android/bordeaux/services/StringFloat.aidl deleted file mode 100644 index f01f166eb..000000000 --- a/bordeaux/service/src/android/bordeaux/services/StringFloat.aidl +++ /dev/null @@ -1,3 +0,0 @@ -package android.bordeaux.services; - -parcelable StringFloat; diff --git a/bordeaux/service/src/android/bordeaux/services/StringFloat.java b/bordeaux/service/src/android/bordeaux/services/StringFloat.java deleted file mode 100644 index c95ccd29c..000000000 --- a/bordeaux/service/src/android/bordeaux/services/StringFloat.java +++ /dev/null @@ -1,46 +0,0 @@ -package android.bordeaux.services; - -import android.os.Parcel; -import android.os.Parcelable; - -public final class StringFloat implements Parcelable { - public String key; - public float value; - - public static final Parcelable.Creator - CREATOR = new Parcelable.Creator() { - public StringFloat createFromParcel(Parcel in) { - return new StringFloat(in); - } - - public StringFloat[] newArray(int size) { - return new StringFloat[size]; - } - }; - - public StringFloat() { - } - - public StringFloat(String newKey, float newValue) { - key = newKey; - value = newValue; - } - - private StringFloat(Parcel in) { - readFromParcel(in); - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel out, int flags) { - out.writeString(key); - out.writeFloat(value); - } - - public void readFromParcel(Parcel in) { - key = in.readString(); - value = in.readFloat(); - } -} diff --git a/bordeaux/service/src/android/bordeaux/services/StringString.aidl b/bordeaux/service/src/android/bordeaux/services/StringString.aidl deleted file mode 100644 index 3cb89b9cf..000000000 --- a/bordeaux/service/src/android/bordeaux/services/StringString.aidl +++ /dev/null @@ -1,3 +0,0 @@ -package android.bordeaux.services; - -parcelable StringString; diff --git a/bordeaux/service/src/android/bordeaux/services/StringString.java b/bordeaux/service/src/android/bordeaux/services/StringString.java deleted file mode 100644 index 109462e9f..000000000 --- a/bordeaux/service/src/android/bordeaux/services/StringString.java +++ /dev/null @@ -1,41 +0,0 @@ -package android.bordeaux.services; - -import android.os.Parcel; -import android.os.Parcelable; - -public final class StringString implements Parcelable { - public String key; - public String value; - - public static final Parcelable.Creator - CREATOR = new Parcelable.Creator() { - public StringString createFromParcel(Parcel in) { - return new StringString(in); - } - - public StringString[] newArray(int size) { - return new StringString[size]; - } - }; - - public StringString() { - } - - private StringString(Parcel in) { - readFromParcel(in); - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel out, int flags) { - out.writeString(key); - out.writeString(value); - } - - public void readFromParcel(Parcel in) { - key = in.readString(); - value = in.readString(); - } -} diff --git a/bordeaux/service/src/android/bordeaux/services/TimeStatsAggregator.java b/bordeaux/service/src/android/bordeaux/services/TimeStatsAggregator.java deleted file mode 100644 index a3e123c74..000000000 --- a/bordeaux/service/src/android/bordeaux/services/TimeStatsAggregator.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.bordeaux.services; - -import android.text.format.Time; -import android.util.Log; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -// import java.util.Date; - -// TODO: use build in functions in -// import android.text.format.Time; -public class TimeStatsAggregator extends Aggregator { - final String TAG = "TimeStatsAggregator"; - - public static final String TIME_OF_WEEK = "Time of Week"; - public static final String DAY_OF_WEEK = "Day of Week"; - public static final String TIME_OF_DAY = "Time of Day"; - public static final String PERIOD_OF_DAY = "Period of Day"; - - static final String WEEKEND = "Weekend"; - static final String WEEKDAY = "Weekday"; - static final String MONDAY = "Monday"; - static final String TUESDAY = "Tuesday"; - static final String WEDNESDAY = "Wednesday"; - static final String THURSDAY = "Thursday"; - static final String FRIDAY = "Friday"; - static final String SATURDAY = "Saturday"; - static final String SUNDAY = "Sunday"; - static final String MORNING = "Morning"; - static final String NOON = "Noon"; - static final String AFTERNOON = "AfterNoon"; - static final String EVENING = "Evening"; - static final String NIGHT = "Night"; - static final String LATENIGHT = "LateNight"; - static final String DAYTIME = "Daytime"; - static final String NIGHTTIME = "Nighttime"; - - static String mFakeTimeOfDay = null; - static String mFakeDayOfWeek = null; - - static final String[] TIME_OF_DAY_VALUES = - {MORNING, NOON, AFTERNOON, EVENING, NIGHT, LATENIGHT}; - - static final String[] DAY_OF_WEEK_VALUES = - {SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY}; - - static final String[] DAYTIME_VALUES = {MORNING, NOON, AFTERNOON, EVENING}; - - public String[] getListOfFeatures(){ - String [] list = new String[4]; - list[0] = TIME_OF_WEEK; - list[1] = DAY_OF_WEEK; - list[2] = TIME_OF_DAY; - list[3] = PERIOD_OF_DAY; - return list; - } - - public Map getFeatureValue(String featureName) { - HashMap feature = new HashMap(); - - HashMap features = - getAllTimeFeatures(System.currentTimeMillis()); - if (features.containsKey(featureName)) { - feature.put(featureName, features.get(featureName)); - } else { - Log.e(TAG, "There is no Time feature called " + featureName); - } - return (Map)feature; - } - - private static String getTimeOfDay(int hour) { - if (hour >= 5 && hour < 11) { - return MORNING; - } else if (hour >= 11 && hour < 14) { - return NOON; - } else if (hour >= 14 && hour < 18) { - return AFTERNOON; - } else if (hour >= 18 && hour < 21) { - return EVENING; - } else if ((hour >= 21 && hour < 24) || - (hour >= 0 && hour < 1)) { - return NIGHT; - } else { - return LATENIGHT; - } - } - - private static String getDayOfWeek(int day) { - switch (day) { - case Time.SATURDAY: - return SATURDAY; - case Time.SUNDAY: - return SUNDAY; - case Time.MONDAY: - return MONDAY; - case Time.TUESDAY: - return TUESDAY; - case Time.WEDNESDAY: - return WEDNESDAY; - case Time.THURSDAY: - return THURSDAY; - default: - return FRIDAY; - } - } - - private static String getPeriodOfDay(int hour) { - if (hour > 6 && hour < 19) { - return DAYTIME; - } else { - return NIGHTTIME; - } - } - - static HashMap getAllTimeFeatures(long utcTime) { - HashMap features = new HashMap(); - Time time = new Time(); - time.set(utcTime); - - if (mFakeTimeOfDay != null && mFakeTimeOfDay.length() != 0) { - List day_list = Arrays.asList(DAYTIME_VALUES); - - if (day_list.contains(mFakeTimeOfDay)) { - features.put(PERIOD_OF_DAY, DAYTIME); - } else { - features.put(PERIOD_OF_DAY, NIGHTTIME); - } - features.put(TIME_OF_DAY, mFakeTimeOfDay); - } else { - features.put(PERIOD_OF_DAY, getPeriodOfDay(time.hour)); - features.put(TIME_OF_DAY, getTimeOfDay(time.hour)); - } - - if (mFakeDayOfWeek != null && mFakeDayOfWeek.length() != 0) { - features.put(DAY_OF_WEEK, mFakeDayOfWeek); - if (mFakeDayOfWeek.equals(SUNDAY) || - mFakeDayOfWeek.equals(SATURDAY) || - mFakeDayOfWeek.equals(FRIDAY) && - features.get(PERIOD_OF_DAY).equals(NIGHTTIME)) { - features.put(TIME_OF_WEEK, WEEKEND); - } else { - features.put(TIME_OF_WEEK, WEEKDAY); - } - } - else { - features.put(DAY_OF_WEEK, getDayOfWeek(time.weekDay)); - if (time.weekDay == Time.SUNDAY || time.weekDay == Time.SATURDAY || - (time.weekDay == Time.FRIDAY && - features.get(PERIOD_OF_DAY).equals(NIGHTTIME))) { - features.put(TIME_OF_WEEK, WEEKEND); - } else { - features.put(TIME_OF_WEEK, WEEKDAY); - } - } - - return features; - } - - // get all possible time_of_day values - public static List getTimeOfDayValues() { - return Arrays.asList(TIME_OF_DAY_VALUES); - } - - // get all possible day values - public static List getDayOfWeekValues() { - return Arrays.asList(DAY_OF_WEEK_VALUES); - } - - // set the fake time of day - // set to "" to disable the fake time - public static void setFakeTimeOfDay(String time_of_day) { - mFakeTimeOfDay = time_of_day; - } - - // set the fake day of week - // set to "" to disable the fake day - public static void setFakeDayOfWeek(String day_of_week) { - mFakeDayOfWeek = day_of_week; - } -} -- cgit v1.2.3