package de.ugoe.cs.eventbench.coverage; import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import de.ugoe.cs.eventbench.data.Event; import de.ugoe.cs.eventbench.models.IStochasticProcess; public class CoverageCalculator { private final IStochasticProcess process; private final List>> sequences; private final int length; private Set>> containedSubSeqs = null; private Set>> allPossibleSubSeqs = null; private Map>, Double> subSeqWeights = null; public CoverageCalculator(IStochasticProcess process, List>> sequences, int length) { this.process = process; this.sequences = sequences; this.length = length; } public double getCoverageAllNoWeight() { if( containedSubSeqs==null ) { containedSubSeqs = containedSubSequences(sequences, length); } return((double) containedSubSeqs.size())/numSequences(process, length); } public double getCoveragePossibleNoWeight() { if( containedSubSeqs==null ) { containedSubSeqs = containedSubSequences(sequences, length); } if( allPossibleSubSeqs==null ) { allPossibleSubSeqs = generateSubSequences(process, length); } return((double) containedSubSeqs.size())/allPossibleSubSeqs.size(); } public double getCoveragePossibleWeight() { if( containedSubSeqs==null ) { containedSubSeqs = containedSubSequences(sequences, length); } if( allPossibleSubSeqs==null ) { allPossibleSubSeqs = generateSubSequences(process, length); } if( subSeqWeights==null ) { subSeqWeights = generateWeights(process, allPossibleSubSeqs); } double weight = 0.0; for( List> subSeq : containedSubSeqs ) { weight += subSeqWeights.get(subSeq); } return weight; } private Map>, Double> generateWeights(IStochasticProcess process, Set>> sequences) { Map>, Double> subSeqWeights = new LinkedHashMap>, Double>(); double sum = 0.0; for( List> sequence : sequences ) { double prob = 1.0; List> context = new LinkedList>(); for( Event event : sequence ) { prob *= process.getProbability(context, event); context.add(event); } subSeqWeights.put(sequence, prob); sum += prob; } if( sum<1.0 ) { for( Map.Entry>, Double> entry : subSeqWeights.entrySet() ) { entry.setValue(entry.getValue()/sum); } } return subSeqWeights; } private long numSequences(IStochasticProcess process, int length) { return (long) Math.pow(process.getNumStates(), length); } // O(symbols^length) private Set>> generateSubSequences(IStochasticProcess process, int length) { Set>> subSequenceSet = new LinkedHashSet>>();; if( length<1 ) { throw new InvalidParameterException(); // TODO comment } if( length==1 ) { for( Event event : process.getEvents() ) { List> subSeq = new LinkedList>(); subSeq.add(event); subSequenceSet.add(subSeq); } return subSequenceSet; } Set> events = process.getEvents(); Set>> subSeqsShorter = generateSubSequences(process, length-1); for( Event event : events ) { for( List> subSequence : subSeqsShorter ) { Event lastEvent = event; if( process.getProbability(subSequence, lastEvent)>0.0 ) { List> subSeq = new ArrayList>(subSequence); subSeq.add(lastEvent); subSequenceSet.add(subSeq); } } } return subSequenceSet; } // O(numSeq*lenSeq) private Set>> containedSubSequences(List>> sequences, int length) { Set>> containedSubSeqs = new LinkedHashSet>>(); List> subSeq = new LinkedList>(); boolean minLengthReached = false; for( List> sequence : sequences ) { for( Event event : sequence ) { subSeq.add(event); if( !minLengthReached ) { if( subSeq.size()==length ) { minLengthReached=true; } } else { subSeq.remove(0); } if( minLengthReached ) { if( !containedSubSeqs.contains(subSeq) ) { containedSubSeqs.add(new LinkedList>(subSeq)); } } } } return containedSubSeqs; } }