diff options
author | Ruei-sung Lin <rslin@google.com> | 2012-08-29 10:30:03 -0700 |
---|---|---|
committer | Ruei-sung Lin <rslin@google.com> | 2012-08-29 18:38:06 -0700 |
commit | 78a66d98346a69f65e9d38bb0c96a5418c007197 (patch) | |
tree | d32650d24d64d2dcc843d179661a7747a5db943d | |
parent | 9c3a7dc466e2f8de02e15030b2b7f4096ba97e5a (diff) | |
download | ml-78a66d98346a69f65e9d38bb0c96a5418c007197.tar.gz |
reduce cluster consoliation interval
Change-Id: If9d60f3fb88e20ecfc855cc20ce92a78c364deec
6 files changed, 184 insertions, 182 deletions
diff --git a/bordeaux/learning/predictor_histogram/java/android/bordeaux/learning/HistogramPredictor.java b/bordeaux/learning/predictor_histogram/java/android/bordeaux/learning/HistogramPredictor.java index cb962de21..c4e7e28f0 100644 --- a/bordeaux/learning/predictor_histogram/java/android/bordeaux/learning/HistogramPredictor.java +++ b/bordeaux/learning/predictor_histogram/java/android/bordeaux/learning/HistogramPredictor.java @@ -36,7 +36,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; - /** * 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. @@ -54,7 +53,7 @@ public class HistogramPredictor { new HashMap<String, HistogramCounter>(); private static final double FEATURE_INACTIVE_LIKELIHOOD = 0.00000001; - private final double logInactive = Math.log(FEATURE_INACTIVE_LIKELIHOOD); + private static final double LOG_INACTIVE = Math.log(FEATURE_INACTIVE_LIKELIHOOD); /* * This class keeps the histogram counts for each feature and provide the @@ -121,6 +120,17 @@ public class HistogramPredictor { } } + private double getDefaultLikelihood(Map<String, String> features) { + int featureCount = 0; + + for(String featureName : features.keySet()) { + if (mPredictor.containsKey(featureName)) { + featureCount++; + } + } + return LOG_INACTIVE * featureCount; + } + /* * Given a map of feature name -value pairs returns the mostly likely apps to * be launched with corresponding likelihoods. @@ -128,7 +138,7 @@ public class HistogramPredictor { public List<Map.Entry<String, Double> > findTopClasses(Map<String, String> features, int topK) { // Most sophisticated function in this class HashMap<String, Double> appScores = new HashMap<String, Double>(); - double defaultLikelihood = mPredictor.size() * logInactive; + double defaultLikelihood = getDefaultLikelihood(features); // compute all app scores for (Map.Entry<String, HistogramCounter> entry : mPredictor.entrySet()) { @@ -145,7 +155,7 @@ public class HistogramPredictor { double score = (appScores.containsKey(appName)) ? appScores.get(appName) : defaultLikelihood; - score += appScore - logInactive; + score += appScore - LOG_INACTIVE; appScores.put(appName, score); } diff --git a/bordeaux/service/src/android/bordeaux/services/BaseCluster.java b/bordeaux/service/src/android/bordeaux/services/BaseCluster.java index 37c2930ff..d00e5f015 100644 --- a/bordeaux/service/src/android/bordeaux/services/BaseCluster.java +++ b/bordeaux/service/src/android/bordeaux/services/BaseCluster.java @@ -33,21 +33,20 @@ public class BaseCluster { // Histogram illustrates the pattern of visit during time of day, protected HashMap<String, Long> mHistogram = new HashMap<String, Long>(); - protected long mAvgInterval; protected long mDuration; protected String mSemanticId; protected static final double EARTH_RADIUS = 6378100f; - public BaseCluster(Location location, long avgInterval) { - mAvgInterval = avgInterval; + public BaseCluster(Location location) { mCenter = getLocationVector(location); mDuration = 0; } public BaseCluster() { + mCenter = new double[] {0f, 0f, 0f}; } public String getSemanticId() { @@ -116,17 +115,12 @@ public class BaseCluster { } public void absorbCluster(BaseCluster cluster) { - if (cluster.mAvgInterval != mAvgInterval) { - throw new RuntimeException( - "aborbing cluster failed: inconsistent average invergal "); - } - // the new cluster center is the average of the two clusters. - double currWeight = ((double) mDuration) / (mDuration + cluster.mDuration); - double newWeight = 1f - currWeight; + double weight = ((double) mDuration) / (mDuration + cluster.mDuration); + double clusterWeight = 1f - weight; double norm = 0; for (int i = 0; i < 3; ++i) { - mCenter[i] = currWeight * mCenter[i] + newWeight * cluster.mCenter[i]; + mCenter[i] = weight * mCenter[i] + clusterWeight * cluster.mCenter[i]; norm += mCenter[i] * mCenter[i]; } // normalize the center to be unit vector diff --git a/bordeaux/service/src/android/bordeaux/services/ClusterManager.java b/bordeaux/service/src/android/bordeaux/services/ClusterManager.java index b5d0b1a20..4bc036995 100644 --- a/bordeaux/service/src/android/bordeaux/services/ClusterManager.java +++ b/bordeaux/service/src/android/bordeaux/services/ClusterManager.java @@ -42,15 +42,19 @@ public class ClusterManager { private static float SEMANTIC_CLUSTER_RADIUS = 100; // meter - private static long CONSOLIDATE_INTERVAL = 60000; // - // private static long CONSOLIDATE_INTERVAL = 21600000; // + // Consoliate location clusters (and check for new semantic clusters) + // every 30 minutes (1800 seconds). + private static final long CONSOLIDATE_INTERVAL = 1800; + // Prune away clusters that are stayed for less than 3 minutes (180 seconds) + private static long LOCATION_CLUSTER_THRESHOLD = 180; - private static long LOCATION_CLUSTER_THRESHOLD = 10000; // in milliseconds - // private static long LOCATION_CLUSTER_THRESHOLD = 180000; // in milliseconds + // 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 - private static long SEMANTIC_CLUSTER_THRESHOLD = 30000; // in milliseconds - // private static long SEMANTIC_CLUSTER_THRESHOLD = 1800000; // in milliseconds + // Reset location cluters every 6 hours (21600 seconds). + private static final long LOCATION_REFRESH_PERIOD = 21600; // seconds private static String UNKNOWN_LOCATION = "Unknown Location"; @@ -60,11 +64,13 @@ public class ClusterManager { private Location mLastLocation = null; + private long mClusterDuration; + private long mTimeRef = 0; private long mSemanticClusterCount = 0; - private ArrayList<LocationCluster> mLocClusters = new ArrayList<LocationCluster>(); + private ArrayList<LocationCluster> mLocationClusters = new ArrayList<LocationCluster>(); private ArrayList<SemanticCluster> mSemanticClusters = new ArrayList<SemanticCluster>(); @@ -108,14 +114,16 @@ public class ClusterManager { if (mLastLocation != null) { // get the duration spent in the last location - long duration = location.getTime() - mLastLocation.getTime(); + long duration = (location.getTime() - mLastLocation.getTime()) / 1000; + mClusterDuration += duration; + Log.v(TAG, "sample duration: " + duration + - ", number of clusters: " + mLocClusters.size()); + ", number of clusters: " + mLocationClusters.size()); // add the last location to cluster. // first find the cluster it belongs to. - for (int i = 0; i < mLocClusters.size(); ++i) { - float distance = mLocClusters.get(i).distanceToCenter(mLastLocation); + 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; @@ -125,24 +133,25 @@ public class ClusterManager { // add the location to the selected cluster if (bestClusterDistance < LOCATION_CLUSTER_RADIUS) { - Log.v(TAG, "add sample to cluster: " + bestClusterIndex + ",( " + - location.getLongitude() + ", " + location.getLatitude() + ")"); - mLocClusters.get(bestClusterIndex).addSample(mLastLocation, duration); + 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, CONSOLIDATE_INTERVAL); + LocationCluster cluster = new LocationCluster(mLastLocation, duration); // move the center of the new cluster if its covering region overlaps // with an existing cluster. if (bestClusterDistance < 2 * LOCATION_CLUSTER_RADIUS) { - Log.e(TAG, "move away activated"); - cluster.moveAwayCluster(mLocClusters.get(bestClusterIndex), + Log.v(TAG, "move away activated"); + cluster.moveAwayCluster(mLocationClusters.get(bestClusterIndex), ((float) 2 * LOCATION_CLUSTER_RADIUS)); } - mLocClusters.add(cluster); + mLocationClusters.add(cluster); } } else { mTimeRef = currentTime; + + if (mLocationClusters.isEmpty()) { + mClusterDuration = 0; + } } long collectDuration = currentTime - mTimeRef; @@ -157,33 +166,125 @@ public class ClusterManager { private void consolidateClusters(long duration) { LocationCluster cluster; - - for (int i = mLocClusters.size() - 1; i >= 0; --i) { - cluster = mLocClusters.get(i); + for (int i = mLocationClusters.size() - 1; i >= 0; --i) { + cluster = mLocationClusters.get(i); cluster.consolidate(duration); - // TODO: currently set threshold to 1 sec so almost none of the location - // clusters will be removed. + // remove transit clusters if (!cluster.passThreshold(LOCATION_CLUSTER_THRESHOLD)) { - mLocClusters.remove(cluster); + mLocationClusters.remove(cluster); } } // merge clusters whose regions are overlapped. note that after merge // cluster center changes but cluster size remains unchanged. - for (int i = mLocClusters.size() - 1; i >= 0; --i) { - cluster = mLocClusters.get(i); + for (int i = mLocationClusters.size() - 1; i >= 0; --i) { + cluster = mLocationClusters.get(i); for (int j = i - 1; j >= 0; --j) { - float distance = mLocClusters.get(j).distanceToCluster(cluster); + float distance = mLocationClusters.get(j).distanceToCluster(cluster); if (distance < LOCATION_CLUSTER_RADIUS) { - mLocClusters.get(j).absorbCluster(cluster); - mLocClusters.remove(cluster); + mLocationClusters.get(j).absorbCluster(cluster); + mLocationClusters.remove(cluster); } } } - updateSemanticClusters(); + // check if new semantic clusters are found + if (findNewSemanticClusters() && + mClusterDuration < LOCATION_REFRESH_PERIOD) { + saveSemanticClusters(); + } + + if (mClusterDuration > LOCATION_REFRESH_PERIOD) { + updateSemanticClusters(); + mClusterDuration = 0; + } + } + + private boolean findNewSemanticClusters() { + // select candidate location clusters + ArrayList<LocationCluster> candidates = new ArrayList<LocationCluster>(); + for (LocationCluster cluster : mLocationClusters) { + if (!cluster.hasSemanticId() && + cluster.passThreshold(SEMANTIC_CLUSTER_THRESHOLD)) { + candidates.add(cluster); + } + } + + // assign each candidate to a semantic cluster + boolean foundNewClusters = false; + for (LocationCluster candidate : candidates) { + // find the closest semantic cluster + float bestClusterDistance = Float.MAX_VALUE; + SemanticCluster bestCluster = null; + for (SemanticCluster cluster : mSemanticClusters) { + float distance = cluster.distanceToCluster(candidate); + Log.v(TAG, "distance to semantic cluster: " + cluster.getSemanticId()); + + if (distance < bestClusterDistance) { + bestClusterDistance = distance; + bestCluster = cluster; + } + } + // if candidate doesn't belong to any semantic cluster, create a new + // semantic cluster + if (bestClusterDistance > SEMANTIC_CLUSTER_RADIUS) { + // if it is far away from all existing clusters, create a new cluster. + bestCluster = new SemanticCluster(candidate, mSemanticClusterCount++); + String id = bestCluster.getSemanticId(); + + // Add new semantic cluster to the list. + mSemanticClusters.add(bestCluster); + + foundNewClusters = true; + } + candidate.setSemanticId(bestCluster.getSemanticId()); + } + candidates.clear(); + return foundNewClusters; + } + + private void updateSemanticClusters() { + synchronized (mSemanticClusters) { + // initialize semanticMap + HashMap<String, ArrayList<BaseCluster> > semanticMap = + new HashMap<String, ArrayList<BaseCluster> >(); + for (SemanticCluster cluster : mSemanticClusters) { + String semanticId = cluster.getSemanticId(); + semanticMap.put(cluster.getSemanticId(), new ArrayList<BaseCluster>()); + semanticMap.get(semanticId).add(cluster); + } + + // assign each candidate to a semantic cluster + for (LocationCluster cluster : mLocationClusters) { + if (cluster.hasSemanticId()) { + semanticMap.get(cluster.getSemanticId()).add(cluster); + } + } + // reset location clusters. + mLocationClusters.clear(); + mLastLocation = null; + mTimeRef = 0; + + // use candidates semantic cluster + BaseCluster newCluster = new BaseCluster(); + for (ArrayList<BaseCluster> clusterList : semanticMap.values()) { + SemanticCluster semanticCluster = (SemanticCluster) clusterList.get(0); + + if (clusterList.size() > 1) { + newCluster.setCluster(clusterList.get(1)); + for (int i = 2; i < clusterList.size(); i++) { + newCluster.absorbCluster(clusterList.get(i)); + } + semanticCluster.absorbCluster(newCluster); + } else { + // cluster with no new candidate + Log.e(TAG, "semantic cluster with no new location clusters: " + + semanticCluster); + } + } + } saveSemanticClusters(); } @@ -197,125 +298,48 @@ public class ClusterManager { String semanticId = map.get(SEMANTIC_ID); double longitude = Double.valueOf(map.get(SEMANTIC_LONGITUDE)); double latitude = Double.valueOf(map.get(SEMANTIC_LATITUDE)); - SemanticCluster cluster = new SemanticCluster( - semanticId, longitude, latitude, CONSOLIDATE_INTERVAL); + SemanticCluster cluster = + new SemanticCluster(semanticId, longitude, latitude); 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))); + histogram.put(featureValue, Long.valueOf(map.get(featureValue))); } } cluster.setHistogram(histogram); - mSemanticClusters.add(cluster); } - mSemanticClusterCount = mSemanticClusters.size(); + Log.e(TAG, "load " + mSemanticClusterCount + " semantic clusters."); } - Log.e(TAG, "load " + mSemanticClusterCount + " semantic clusters."); } private void saveSemanticClusters() { HashMap<String, String> rowFeatures = new HashMap<String, String>(); - Log.e(TAG, "save " + mSemanticClusters.size() + " semantic clusters."); + mStorage.removeAllData(); synchronized (mSemanticClusters) { - mStorage.removeAllData(); for (SemanticCluster cluster : mSemanticClusters) { rowFeatures.clear(); rowFeatures.put(SEMANTIC_ID, cluster.getSemanticId()); rowFeatures.put(SEMANTIC_LONGITUDE, - String.valueOf(cluster.getCenterLongitude())); + String.valueOf(cluster.getCenterLongitude())); rowFeatures.put(SEMANTIC_LATITUDE, - String.valueOf(cluster.getCenterLatitude())); + String.valueOf(cluster.getCenterLatitude())); HashMap<String, Long> histogram = cluster.getHistogram(); for (Map.Entry<String, Long> entry : histogram.entrySet()) { rowFeatures.put(entry.getKey(), String.valueOf(entry.getValue())); } mStorage.addData(rowFeatures); + Log.e(TAG, "saving semantic cluster: " + rowFeatures); } } } - private void updateSemanticClusters() { - HashMap<String, ArrayList<BaseCluster> > semanticMap = - new HashMap<String, ArrayList<BaseCluster> >(); - synchronized (mSemanticClusters) { - for (SemanticCluster cluster : mSemanticClusters) { - String semanticId = cluster.getSemanticId(); - semanticMap.put(cluster.getSemanticId(), new ArrayList<BaseCluster>()); - semanticMap.get(semanticId).add(cluster); - } - - // select candidate location clusters - ArrayList<LocationCluster> candidates = new ArrayList<LocationCluster>(); - for (LocationCluster cluster : mLocClusters) { - if (cluster.passThreshold(SEMANTIC_CLUSTER_THRESHOLD)) { - candidates.add(cluster); - } - } - - // assign each candidate to a semantic cluster - for (LocationCluster candidate : candidates) { - if (candidate.hasSemanticId()) { - // candidate has been assigned to a semantic cluster - continue; - } - - // find the closest semantic cluster - float bestClusterDistance = Float.MAX_VALUE; - SemanticCluster bestCluster = null; - for (SemanticCluster cluster : mSemanticClusters) { - float distance = cluster.distanceToCluster(candidate); - Log.e(TAG, "distance to semantic cluster: " + cluster.getSemanticId()); - - if (distance < bestClusterDistance) { - bestClusterDistance = distance; - bestCluster = cluster; - } - } - - // add the location to the selected cluster - SemanticCluster semanticCluster; - if (bestClusterDistance > SEMANTIC_CLUSTER_RADIUS) { - // if it is far away from all existing clusters, create a new cluster. - bestCluster = new SemanticCluster(candidate, CONSOLIDATE_INTERVAL, - mSemanticClusterCount++); - String id = bestCluster.getSemanticId(); - semanticMap.put(id, new ArrayList<BaseCluster>()); - semanticMap.get(id).add(bestCluster); - } - String semanticId = bestCluster.getSemanticId(); - candidate.setSemanticId(semanticId); - semanticMap.get(semanticId).add(candidate); - } - candidates.clear(); - } - Log.e(TAG, "number of semantic clusters: " + semanticMap.size()); - - // use candidates semantic cluster - mSemanticClusters.clear(); - for (ArrayList<BaseCluster> clusterList : semanticMap.values()) { - SemanticCluster semanticCluster = (SemanticCluster) clusterList.get(0); - - Log.e(TAG, "id: " + semanticCluster.getSemanticId() + ", list size: " + - clusterList.size()); - - if (clusterList.size() > 1) { - // cluster with no new candidate - semanticCluster.setCluster(clusterList.get(1)); - for (int i = 2; i < clusterList.size(); i++) { - semanticCluster.absorbCluster(clusterList.get(i)); - } - } - mSemanticClusters.add(semanticCluster); - } - } - public String getSemanticLocation() { String label = LocationStatsAggregator.UNKNOWN_LOCATION; diff --git a/bordeaux/service/src/android/bordeaux/services/LocationCluster.java b/bordeaux/service/src/android/bordeaux/services/LocationCluster.java index 2d25cf1fe..078e64396 100644 --- a/bordeaux/service/src/android/bordeaux/services/LocationCluster.java +++ b/bordeaux/service/src/android/bordeaux/services/LocationCluster.java @@ -27,16 +27,14 @@ import java.util.Map; public class LocationCluster extends BaseCluster { public static String TAG = "LocationCluster"; - private static double FORGETTING_FACTOR = 0.1; - private boolean mIsNewCluster; private ArrayList<Location> mLocations = new ArrayList<Location>(); private HashMap<String, Long> mNewHistogram = new HashMap<String, Long>(); // TODO: make it a singleton class - public LocationCluster(Location location, long duration, long avgInterval) { - super(location, avgInterval); + public LocationCluster(Location location, long duration) { + super(location); mIsNewCluster = true; addSample(location, duration); } @@ -78,14 +76,11 @@ public class LocationCluster extends BaseCluster { mDuration = newDuration; mHistogram.clear(); mHistogram.putAll(mNewHistogram); - mNewHistogram.clear(); - mIsNewCluster = false; } else { // the new center is weight average over latest and existing centers. // fine tune the weight of new center double newWeight = ((double) newDuration) / (newDuration + mDuration); - newWeight *= FORGETTING_FACTOR; double currWeight = 1f - newWeight; double norm = 0; for (int i = 0; i < 3; ++i) { @@ -96,9 +91,18 @@ public class LocationCluster extends BaseCluster { for (int i = 0; i < 3; ++i) { mCenter[i] /= norm; } - consolidateHistogram(newWeight, newDuration); - mNewHistogram.clear(); + // update histogram + for (Map.Entry<String, Long> 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(); } /* @@ -139,30 +143,4 @@ public class LocationCluster extends BaseCluster { mNewHistogram.get(timeOfDay) + duration : duration; mNewHistogram.put(timeOfDay, totalDuration); } - - private void consolidateHistogram(double weight, long newDuration) { - long base = 1000; - long newWeight = (long) (weight * base); - long currWeight = base - newWeight; - - for (Map.Entry<String, Long> entry : mHistogram.entrySet()) { - String timeLabel = entry.getKey(); - long duration = entry.getValue() * currWeight; - if (mNewHistogram.containsKey(timeLabel)) { - duration += mNewHistogram.get(timeLabel) * newWeight; - } - duration /= base; - mHistogram.put(timeLabel, duration); - } - - for (Map.Entry<String, Long> entry : mNewHistogram.entrySet()) { - String timeLabel = entry.getKey(); - if (!mHistogram.containsKey(timeLabel)) { - long duration = newWeight * entry.getValue(); - duration /= base; - mHistogram.put(timeLabel, duration); - } - } - mDuration = (mDuration * currWeight + newDuration * newWeight) / base; - } } diff --git a/bordeaux/service/src/android/bordeaux/services/LocationStatsAggregator.java b/bordeaux/service/src/android/bordeaux/services/LocationStatsAggregator.java index 0c05157c2..0390b7fbf 100644 --- a/bordeaux/service/src/android/bordeaux/services/LocationStatsAggregator.java +++ b/bordeaux/service/src/android/bordeaux/services/LocationStatsAggregator.java @@ -40,11 +40,11 @@ public class LocationStatsAggregator extends Aggregator { public static final String CURRENT_SPEED = "Current Speed"; public static final String UNKNOWN_LOCATION = "Unknown Location"; - // TODO: Collect location on every minute - private static final long MINIMUM_TIME = 30000; // milliseconds + // TODO: Collect location on every minute (60000 milliseconds) + private static final long MINIMUM_TIME = 60000; - // reset best location provider on every 5 minutes - private static final int BEST_PROVIDER_DURATION = 300000; + // reset best location provider on every 10 minutes (300000 milliseconds) + private static final int BEST_PROVIDER_DURATION = 600000; private static final float MINIMUM_DISTANCE = 0f; // meter @@ -77,13 +77,11 @@ public class LocationStatsAggregator extends Aggregator { HashMap<String,String> feature = new HashMap<String,String>(); if (featureName.equals(CURRENT_LOCATION)) { - - // TODO: check last known location first before sending out location request. - /* - Location location = - mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); - */ - + // 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) { diff --git a/bordeaux/service/src/android/bordeaux/services/SemanticCluster.java b/bordeaux/service/src/android/bordeaux/services/SemanticCluster.java index 222111d3a..b0d42ab22 100644 --- a/bordeaux/service/src/android/bordeaux/services/SemanticCluster.java +++ b/bordeaux/service/src/android/bordeaux/services/SemanticCluster.java @@ -21,24 +21,22 @@ import android.util.Log; import java.lang.Math; import java.util.ArrayList; +import java.util.Map; public class SemanticCluster extends BaseCluster { public static String TAG = "SemanticCluster"; - public SemanticCluster(LocationCluster cluster, long avgInterval, long semanticIndex) { + public SemanticCluster(LocationCluster cluster, long semanticIndex) { mCenter = new double[3]; for (int i = 0; i < 3; ++i) { mCenter[i] = cluster.mCenter[i]; } - mAvgInterval = avgInterval; generateSemanticId(semanticIndex); } - public SemanticCluster(String semanticId, double longitude, double latitude, - long avgInterval) { + public SemanticCluster(String semanticId, double longitude, double latitude) { setSemanticId(semanticId); - mAvgInterval = avgInterval; mCenter = getLocationVector(longitude, latitude); } |