package com.PP.IntelliSeg.LBDM; import java.util.ArrayList; import java.util.List; import com.PP.IntelliSeg.Abstract.Segment; public class LBDM { /** * Segment method * @param P List of Parametric Profiles * @param weights How Profiles should be weighted * @return */ public static List<Segment> segment(List<List<Double>> P, double[] weights) { //compute strengths of boundaries for each parametric profile and normalize. List<List<Double>> S = new ArrayList<List<Double>>(); for(List<Double> P_k : P) { List<Double> r = computeDegreesOfChange(P_k); List<Double> S_k = computeStrengthsOfBoundaries(P_k,r); S_k = normalizeBoundaryStrengths(S_k); } //compute weighted boundary List<Double> weightedBoundary = weightBoundaries(S,weights); //segment according to local peaks List<Segment> rtn = localPeakSeg(weightedBoundary); //return return rtn; } /** * Segment sequences by local peaks * @param seq The time series * @return */ protected static List<Segment> localPeakSeg(List<Double> seq) { //init rtn List<Segment> rtn = new ArrayList<Segment>(); //loop int lastStart = 0; for(int x=1; x < (seq.size()-1); x++) { double lastVal = seq.get(x-1); double cVal = seq.get(x); double nextVal = seq.get(x+1); if(cVal > lastVal && cVal > nextVal) { int end = x; Segment seg = new LBDMSegment(lastStart,end); rtn.add(seg); lastStart = (x+1); } } //handle last segment if(lastStart < (seq.size()-1)) { Segment seg = new LBDMSegment(lastStart,seq.size()-1); rtn.add(seg); } //return return rtn; } /** * Computes Weighted Boundary * @param S List of Boundary Sequences S_k * @param weights List of how to weight each boundary * @return */ protected static List<Double> weightBoundaries(List<List<Double>> S, double[] weights) { //init rtn List<Double> rtn = new ArrayList<Double>(); //easy exist -- nothing to do if(S.size()==0 || S.get(0).size()==0) { return rtn; } //compute weighted boundary int seqLength = S.get(0).size(); for(int x=0; x < seqLength; x++) { double newBoundary=0.0; for(int y=0; y < S.size(); y++) { newBoundary = newBoundary + weights[y] * S.get(y).get(x); } rtn.add(newBoundary); } //return return rtn; } /** * Normalizes boundary strengths * @param s_k * @return */ protected static List<Double> normalizeBoundaryStrengths(List<Double> s_k) { double sum=0.0; for(double s : s_k) { sum = sum + s; } List<Double> rtn = new ArrayList<Double>(); for(double s : s_k) { if(sum!=0) { rtn.add(s / sum); } else { rtn.add(s); } } return rtn; } /** * Computes Strengths of boundaries function * @param P_k Parametric Profile * @param r Degrees of Change * @return Strengths of Boundaries */ protected static List<Double> computeStrengthsOfBoundaries(List<Double> P_k, List<Double> r) { List<Double> rtn = new ArrayList<Double>(); for(int x=0; x < r.size(); x++) { double r_im1_i = 0.0; if(x!=0) { r_im1_i = r.get(x-1); } double r_i_ip1 = r.get(x); double val = P_k.get(x) * (r_im1_i + r_i_ip1); rtn.add(val); } return rtn; } /** * Strength of Boundary formula * @param r_im1_i * @param r_i_ip1 * @param x_i * @return s_i */ protected static double stengthOfBoundary(double r_im1_i, double r_i_ip1, double x_i) { return x_i * (r_im1_i + r_i_ip1); } /** * Compute degree of changes for parametric profile * @param P_k Parameteric Profile * @return r_i,i+1 degree of change function */ protected static List<Double> computeDegreesOfChange(List<Double> P_k) { List<Double> rtn = new ArrayList<Double>(); for(int x=1; x < P_k.size(); x++) { double r = 0.0; double x_ip1 = P_k.get(x); double x_i = P_k.get(x-1); r = degreeOfChange(x_i,x_ip1); rtn.add(r); } rtn.add(P_k.get(P_k.size()-1)); //last element return rtn; } /** * Degree of change formula * @param x_i * @param x_ip1 * @return r_i,ip1 */ protected static double degreeOfChange(double x_i, double x_ip1) { if(x_i==0 && x_ip1==0) { return 0.0; } else { return Math.abs(x_i - x_ip1) / (x_i + x_ip1); } } }