blob: e18dcd41d3b655e7f9d2e3c66296832479d956f9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 École Polytechnique de Montréal
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.tracecompass.incubator.internal.xaf.core.statemachine.variable.utils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import org.eclipse.tracecompass.incubator.internal.xaf.core.statemachine.constraint.Direction;
import org.eclipse.tracecompass.incubator.internal.xaf.ui.statemachine.StateMachineUtils.TimestampInterval;
import com.google.common.collect.HashMultimap;
/**
* Set of interruption interval objects
*
* @author Raphaël Beamonte
*/
public class InterruptionIntervalSet implements Cloneable {
private HashMultimap<InterruptionReason, InterruptionInterval> map = HashMultimap.create();
private int counter = 0;
private Direction fDirection = null;
/**
* Constructor
*/
public InterruptionIntervalSet() {
}
/**
* Constructor
*
* @param direction
* The direction of the interval set
*/
public InterruptionIntervalSet(Direction direction) {
this.fDirection = direction;
}
/**
* @return Whether the interval set is empty or not
*/
public boolean isEmpty() {
return map.isEmpty();
}
/**
* @return The direction of the interval set
*/
public Direction getDirection() {
return fDirection;
}
/**
* Add an interval to the interval set
*
* @param ii
* The interval to add to the interval set
*/
public void add(InterruptionInterval ii) {
map.put(ii.reason, ii);
}
/**
* @return The number of duration set put in that interval set
*/
public int getCounter() {
return counter;
}
/**
* Add a duration into the closest interval we can find that matches its
* reason, or create a new interval if we couldn't find any
*
* @param id
* The duration to add
*/
public void addToCloser(InterruptionDuration id) {
List<InterruptionInterval> list = new ArrayList<>(map.get(id.reason));
if (list.isEmpty()) {
// We did not find any corresponding key, create a new interval
map.put(id.reason, new InterruptionInterval(id));
return;
}
double closerDist = Double.MAX_VALUE;
int closerI = 0;
for (int i = 0; i < list.size(); i++) {
InterruptionInterval ii = list.get(i);
// If we encounter one matching interval, the duration is already
// considered, we can leave.
if (ii.isMatching(id)) {
ii.addDuration(id);
return;
}
// Else, calculate the minimum distance with that interval
double dist = Math.min(Math.abs(ii.maxDuration - id.fDuration), Math.abs(ii.minDuration - id.fDuration));
if (dist < closerDist) {
closerDist = dist;
closerI = i;
}
}
// If we didn't add the duration, add it to the closest interval
list.get(closerI).addDuration(id);
}
/**
* Sort a list of durations per duration
*
* @param durationList
* The list of durations to sort
* @return The sorted list of durations
*/
private static List<InterruptionDuration> sortDurationList(List<InterruptionDuration> durationList) {
List<InterruptionDuration> sortedDurationList = new ArrayList<>(durationList);
Collections.sort(sortedDurationList, new Comparator<InterruptionDuration>() {
@Override
public int compare(InterruptionDuration id1, InterruptionDuration id2) {
return -Double.valueOf(id1.getDuration()).compareTo(id2.getDuration());
}
});
return sortedDurationList;
}
/**
* Sort a list of intervals per duration, keeping into account the direction
*
* @param intervalList
* The list of intervals to sort
* @param direction
* The direction to use for the sort
* @return The sorted list of intervals
*/
private static List<InterruptionInterval> sortIntervalList(List<InterruptionInterval> intervalList, final Direction direction) {
List<InterruptionInterval> sortedIntervalList = new ArrayList<>(intervalList);
Collections.sort(sortedIntervalList, new Comparator<InterruptionInterval>() {
@Override
public int compare(InterruptionInterval ii1, InterruptionInterval ii2) {
int result;
if (direction == Direction.VARIABLE_OVER_VALUE) {
result = -Double.valueOf(ii1.getMinDuration()).compareTo(ii2.getMinDuration());
} else {
result = -Double.valueOf(ii1.getMaxDuration()).compareTo(ii2.getMaxDuration());
}
return result;
}
});
return sortedIntervalList;
}
private static List<InterruptionDuration> closestDurationList(List<InterruptionDuration> durationList, List<InterruptionInterval> intervalList, final Direction direction) {
// Organize duration list by decreasing durations
List<InterruptionDuration> sortedDurationList = sortDurationList(durationList);
// Organize interval list by decreasing max or min durations depending
// on direction
List<InterruptionInterval> sortedIntervalList = sortIntervalList(intervalList, direction);
// Now we match them in that order
List<InterruptionDuration> idL = new ArrayList<>();
for (InterruptionInterval ii : intervalList) {
idL.add(sortedDurationList.get(sortedIntervalList.indexOf(ii)));
}
return idL;
}
private static List<InterruptionInterval> closestIntervalList(List<InterruptionDuration> durationList, List<InterruptionInterval> intervalList, final Direction direction) {
// Organize duration list by decreasing durations
List<InterruptionDuration> sortedDurationList = sortDurationList(durationList);
// Organize interval list by decreasing max or min durations depending
// on direction
List<InterruptionInterval> sortedIntervalList = sortIntervalList(intervalList, direction);
// Now we match them in that order
List<InterruptionInterval> iiL = new ArrayList<>();
for (InterruptionDuration id : durationList) {
iiL.add(sortedIntervalList.get(sortedDurationList.indexOf(id)));
}
return iiL;
}
/*
* private static DurationIntervalPair
* closestPermutation(List<InterruptionInterval> intervalList,
* List<InterruptionDuration> durationList, Boolean direction) { if
* (durationList.size() == intervalList.size()) { return new
* DurationIntervalPair(closestDurationList(durationList, intervalList,
* direction), intervalList); }
*
* Iterator<DurationIntervalPair> it;
*
* int durationListSize = durationList.size(); int intervalListSize =
* intervalList.size(); int minSize = Math.min(durationListSize,
* intervalListSize); if (durationListSize > intervalListSize) { it = new
* Iterator<DurationIntervalPair>() {
*
* @SuppressWarnings("null") private Iterator<List<InterruptionDuration>>
* uniqueCombinationsIterator = new
* UniqueCombinationsIterator<>(durationList, intervalListSize);
*
* @Override public boolean hasNext() { return
* uniqueCombinationsIterator.hasNext(); }
*
* @Override public DurationIntervalPair next() { return new
* DurationIntervalPair(closestDurationList(uniqueCombinationsIterator.next(
* ), intervalList, direction), intervalList); } }; } else { it = new
* Iterator<DurationIntervalPair>() {
*
* @SuppressWarnings("null") private Iterator<List<InterruptionInterval>>
* uniqueCombinationsIterator = new
* UniqueCombinationsIterator<>(intervalList, durationListSize);
*
* @Override public boolean hasNext() { return
* uniqueCombinationsIterator.hasNext(); }
*
* @Override public DurationIntervalPair next() { return new
* DurationIntervalPair(durationList, closestIntervalList(durationList,
* uniqueCombinationsIterator.next(), direction)); } }; }
*
* double closestDist = Double.MAX_VALUE; DurationIntervalPair
* closestDistPair = null;
*
* int limit = 1000000; while (it.hasNext() && limit-- > 0) {
* DurationIntervalPair pair = it.next();
*
* double dist = 0; for (int i = 0; i < minSize; i++) { InterruptionInterval
* intvl = pair.interval.get(i); InterruptionDuration dur =
* pair.duration.get(i);
*
* if (direction == null) { dist += intvl.distance(dur); } else if
* (direction) { dist += intvl.distanceSup(dur); } else { dist +=
* intvl.distanceInf(dur); } }
*
* List<InterruptionDuration> copy = null; if (closestList.size() <
* durationList.size()) { copy = new ArrayList<>(durationList);
* copy.removeAll(closestList); for (InterruptionDuration dur : copy) { dist
* += dur.getDuration(); } } List<InterruptionInterval> copy = null; if
* (list.size() < intervalList.size()) { copy = new
* ArrayList<>(intervalList); copy.removeAll(list); for
* (InterruptionInterval intvl : copy) { dist += (intvl.getMaxDuration() -
* intvl.getMinDuration()) / 2.0; } }
*
* if (dist < closestDist) { closestDist = dist; closestDistList = new
* ArrayList<>(closestList); if (copy != null) {
* closestDistList.addAll(copy); }
*
* if (dist == 0) { break; } } }
*
* return closestDistPair; }
*/
private static List<InterruptionDuration> closestPermutationDuration(List<InterruptionInterval> intervalList, List<InterruptionDuration> durationList, Direction direction) {
if (durationList.size() == intervalList.size()) {
return closestDurationList(durationList, intervalList, direction);
}
int minSize = intervalList.size();
@SuppressWarnings("null")
Iterator<List<InterruptionDuration>> uniqueCombinationsIterator = new UniqueCombinationsIteratorSample<>(durationList, minSize);
double closestDist = Double.MAX_VALUE;
List<InterruptionDuration> closestDistList = null;
while (uniqueCombinationsIterator.hasNext()) {
List<InterruptionDuration> list = uniqueCombinationsIterator.next();
List<InterruptionDuration> closestList = closestDurationList(list, intervalList, direction);
double dist = 0;
for (int i = 0; i < minSize; i++) {
InterruptionInterval intvl = intervalList.get(i);
InterruptionDuration dur = closestList.get(i);
dist += intvl.distance(dur, direction);
}
List<InterruptionDuration> copy = null;
if (closestList.size() < durationList.size()) {
copy = new ArrayList<>(durationList);
copy.removeAll(closestList);
for (InterruptionDuration dur : copy) {
dist += dur.getDuration();
}
}
if (dist < closestDist) {
closestDist = dist;
closestDistList = new ArrayList<>(closestList);
if (copy != null) {
closestDistList.addAll(copy);
}
if (dist == 0) {
break;
}
}
}
return closestDistList;
}
private static List<InterruptionInterval> closestPermutationInterval(List<InterruptionInterval> intervalList, List<InterruptionDuration> durationList, Direction direction) {
if (durationList.size() == intervalList.size()) {
return closestIntervalList(durationList, intervalList, direction);
}
int minSize = durationList.size();
@SuppressWarnings("null")
Iterator<List<InterruptionInterval>> uniqueCombinationsIterator = new UniqueCombinationsIteratorSample<>(intervalList, minSize);
double closestDist = Double.MAX_VALUE;
List<InterruptionInterval> closestDistList = null;
while (uniqueCombinationsIterator.hasNext()) {
List<InterruptionInterval> list = uniqueCombinationsIterator.next();
List<InterruptionInterval> closestList = closestIntervalList(durationList, list, direction);
double dist = 0;
for (int i = 0; i < minSize; i++) {
InterruptionInterval intvl = closestList.get(i);
InterruptionDuration dur = durationList.get(i);
dist += intvl.distance(dur, direction);
}
List<InterruptionInterval> copy = null;
if (list.size() < intervalList.size()) {
copy = new ArrayList<>(intervalList);
copy.removeAll(list);
for (InterruptionInterval intvl : copy) {
dist += (intvl.getMaxDuration() - intvl.getMinDuration()) / 2.0;
}
}
if (dist < closestDist) {
closestDist = dist;
closestDistList = new ArrayList<>(closestList);
if (copy != null) {
closestDistList.addAll(copy);
}
if (dist == 0) {
break;
}
}
}
return closestDistList;
}
/**
* Substract a duration set from this interval set
*
* @param idsToSubstract
* The duration set to substract from this interval set
* @param direction
* The direction to use for the substraction
* @return The interval set difference
*/
public InterruptionIntervalSetDiff substract(InterruptionDurationSet idsToSubstract, Direction direction) {
InterruptionIntervalSet iisToSubstract = new InterruptionIntervalSet(direction);
iisToSubstract.addDurationSet(idsToSubstract);
return substract(iisToSubstract);
}
/**
* Substract a interval set from this interval set
*
* @param iisToSubstract
* The interval set to substract from this interval set
* @return The interval set difference
*/
public InterruptionIntervalSetDiff substract(InterruptionIntervalSet iisToSubstract) {
InterruptionIntervalSetDiff iisd = new InterruptionIntervalSetDiff();
// Create a set of all the reasons we need to substract, so we can treat
// the ones we didn't treat if needed
Set<InterruptionReason> substractReasons = new HashSet<>(iisToSubstract.map.keySet());
// For each entry in our local multimap
for (Entry<InterruptionReason, Collection<InterruptionInterval>> entry : map.asMap().entrySet()) {
// Check if there is data to substract
List<InterruptionInterval> substract = new ArrayList<>(iisToSubstract.map.get(entry.getKey()));
// Get the size of the local list (number of intervals for that
// reason)
int thisSize = entry.getValue().size();
// Compute the sum of minimum and maximum durations of these
// intervals
double thisMinTime = 0;
double thisMaxTime = 0;
int thisCounter = 0;
List<TimestampInterval> thisTiList = new LinkedList<>();
for (InterruptionInterval ii : entry.getValue()) {
thisMinTime += ii.getMinDuration();
thisMaxTime += ii.getMaxDuration();
thisCounter += ii.getCounter();
thisTiList.addAll(ii.getTsIntervals());
}
// If there is nothing to substract, just add the previously
// computed durations as the diff
if (substract.isEmpty()) {
if (fDirection == Direction.VARIABLE_EQ_VALUE || fDirection == Direction.VARIABLE_UNDER_VALUE) {
// Create the difference interval that we'll populate with
// the time data
InterruptionInterval iiDiff = new InterruptionInterval(entry.getKey());
iiDiff.setMinDuration(thisMinTime);
iiDiff.setMaxDuration(thisMaxTime);
iiDiff.setCounter(thisCounter);
iiDiff.addTsInterval(thisTiList);
iisd.add(iiDiff, entry.getValue().size());
}
continue;
}
// ... and remove that reason from the set of all the reasons we
// need to substract
substractReasons.remove(entry.getKey());
// Then get the size of the list to substract (number of intervals
// for that reason)
int subsSize = substract.size();
// Compute the sum of minimum and maximum durations of these
// intervals
double subsMinTime = 0;
double subsMaxTime = 0;
int subsCounter = 0;
for (InterruptionInterval ii : substract) {
subsMinTime += ii.getMinDuration();
subsMaxTime += ii.getMaxDuration();
subsCounter += ii.getCounter();
}
// Finally, compute the size, minimum and maximum differences
int sizeCalc = thisSize - subsSize;
double minCalc = thisMinTime - subsMinTime;
double maxCalc = thisMaxTime - subsMaxTime;
int counterCalc = thisCounter - subsCounter;
if (fDirection == Direction.VARIABLE_UNDER_VALUE) {
sizeCalc = Math.max(sizeCalc, 0);
minCalc = Math.max(minCalc, 0);
maxCalc = Math.max(maxCalc, 0);
counterCalc = Math.max(counterCalc, 0);
} else if (fDirection == Direction.VARIABLE_OVER_VALUE) {
sizeCalc = Math.max(-sizeCalc, 0);
minCalc = Math.max(-minCalc, 0);
maxCalc = Math.max(-maxCalc, 0);
counterCalc = Math.max(-counterCalc, 0);
}
// Only create an interval if one of those information is different
// than 0
if (sizeCalc != 0 || minCalc != 0 || maxCalc != 0) {
// Create the difference interval that we'll populate with the
// time data
InterruptionInterval iiDiff = new InterruptionInterval(entry.getKey());
iiDiff.setMinDuration(Math.min(minCalc, maxCalc));
iiDiff.setMaxDuration(Math.max(minCalc, maxCalc));
iiDiff.setCounter(counterCalc);
iiDiff.addTsInterval(thisTiList);
iisd.add(iiDiff, sizeCalc);
}
}
if (fDirection == Direction.VARIABLE_EQ_VALUE || fDirection == Direction.VARIABLE_OVER_VALUE) {
// For each entry left in the set of all the reasons we need to
// substract
for (InterruptionReason ir : substractReasons) {
List<InterruptionInterval> substract = new ArrayList<>(iisToSubstract.map.get(ir));
int subsSize = -substract.size();
double subsMinTime = 0;
double subsMaxTime = 0;
int subsCounter = 0;
List<TimestampInterval> subsTiList = new LinkedList<>();
for (InterruptionInterval ii : substract) {
subsMinTime -= ii.getMinDuration();
subsMaxTime -= ii.getMaxDuration();
subsCounter -= ii.getCounter();
subsTiList.addAll(ii.getTsIntervals());
}
InterruptionInterval iiDiff = new InterruptionInterval(ir);
iiDiff.setMinDuration(subsMaxTime);
iiDiff.setMaxDuration(subsMinTime);
iiDiff.setCounter(subsCounter);
iiDiff.addTsInterval(subsTiList);
iisd.add(iiDiff, subsSize);
}
}
return iisd;
}
/**
* Add a duration set to that interval set, by matching each element to the
* closest.
*
* @param ids
* The duration set to add
*/
public void addDurationSet(InterruptionDurationSet ids) {
/*
* Increment the number of duration set we put in that interval, will
* help to weight it for the number of occurrences
*/
counter++;
/*
* For each interruption reason, treat the list of interruption duration
* to match it in the list of interval for that reason in our interval
* set
*/
for (Entry<InterruptionReason, Collection<InterruptionDuration>> entry : ids.entrySetList()) {
List<InterruptionInterval> intList = new ArrayList<>(map.get(entry.getKey()));
/*
* If no interval correspond to the current reason, create a new
* interval in the multimap for that reason, with that duration.
*/
if (intList.isEmpty()) {
for (InterruptionDuration id : entry.getValue()) {
map.put(entry.getKey(), new InterruptionInterval(id));
}
continue;
}
List<InterruptionInterval> cIiList;
List<InterruptionDuration> cIdList;
List<InterruptionDuration> entryAsList = new ArrayList<>(entry.getValue());
if (intList.size() > entry.getValue().size()) {
// If the list of intervals is bigger, it's the one we want to
// permute
cIiList = closestPermutationInterval(intList, entryAsList, fDirection);
cIdList = entryAsList;
} else {
cIiList = intList;
cIdList = closestPermutationDuration(intList, entryAsList, fDirection);
}
// If cIdList is null, there was a problem
if (cIdList == null) {
throw new RuntimeException("cIdList is null and shouldn't be!"); //$NON-NLS-1$
}
// If cIiList is null, there was a problem
if (cIiList == null) {
throw new RuntimeException("cIiList is null and shouldn't be!"); //$NON-NLS-1$
}
// Add the duration to all existing interval
int minSize = Math.min(cIiList.size(), cIdList.size());
for (int i = 0; i < minSize; i++) {
cIiList.get(i).addDuration(cIdList.get(i));
}
// Add the duration that did not fit in the intervals
for (int i = minSize; i < cIdList.size(); i++) {
map.put(entry.getKey(), new InterruptionInterval(cIdList.get(i)));
}
}
}
/**
* Verify if a duration set fits in the current interval set. For a duration
* set to fit, it needs to be composed of the exact same interruption
* reasons, for the exact same number of times.
*
* @param ids
* The duration set to verify
* @return true if it fits, false else
*/
public boolean fits(InterruptionDurationSet ids) {
Map<InterruptionReason, Integer> iikeymap = StateMachineVariableHelpers.keyMap(map);
Map<InterruptionReason, Integer> idkeymap = StateMachineVariableHelpers.keyMap(ids.map);
if (idkeymap.keySet().size() != iikeymap.keySet().size()) {
return false;
}
for (Entry<InterruptionReason, Integer> entry : idkeymap.entrySet()) {
Integer i = iikeymap.remove(entry.getKey());
if (i == null || i != entry.getValue()) {
return false;
}
}
return true;
}
/**
* Compute the distance between a duration set and the interval set.
*
* @param ids
* The duration set
* @return The distance
*/
public InterruptionDurationSet distance(InterruptionDurationSet ids) {
InterruptionDurationSet diff = new InterruptionDurationSet();
HashMultimap<InterruptionReason, InterruptionInterval> copy = HashMultimap.create(map);
// For all the data that are in the duration set
for (Entry<InterruptionReason, Collection<InterruptionDuration>> entry : ids.map.asMap().entrySet()) {
List<InterruptionInterval> intList = new ArrayList<>(copy.removeAll(entry.getKey()));
if (intList.isEmpty()) {
if (fDirection == Direction.VARIABLE_UNDER_VALUE || fDirection == Direction.VARIABLE_EQ_VALUE) {
for (InterruptionDuration id : entry.getValue()) {
diff.add(new InterruptionDuration(id.getReason(), id.getDuration()));
}
}
continue;
}
List<InterruptionInterval> cIiList;
List<InterruptionDuration> cIdList;
List<InterruptionDuration> entryAsList = new ArrayList<>(entry.getValue());
if (intList.size() > entry.getValue().size()) {
// If the list of intervals is bigger, it's the one we want to
// permute
cIiList = closestPermutationInterval(intList, entryAsList, fDirection);
cIdList = entryAsList;
} else {
cIiList = intList;
cIdList = closestPermutationDuration(intList, entryAsList, fDirection);
}
// If cIdList is null, there was a problem
if (cIdList == null) {
throw new RuntimeException("cIdList is null and shouldn't be!"); //$NON-NLS-1$
}
// If cIiList is null, there was a problem
if (cIiList == null) {
throw new RuntimeException("cIiList is null and shouldn't be!"); //$NON-NLS-1$
}
// Add the differences for those who do not fit in the interval
int minSize = Math.min(cIiList.size(), cIdList.size());
for (int i = 0; i < minSize; i++) {
InterruptionDuration id = cIdList.get(i);
double dist = cIiList.get(i).distance(id, fDirection);
if (dist > 0) {
diff.add(new InterruptionDuration(id.getReason(), dist));
}
}
// Add the differences for the durations who entirely did not fit
if (fDirection == Direction.VARIABLE_UNDER_VALUE || fDirection == Direction.VARIABLE_EQ_VALUE) {
for (int i = minSize; i < cIdList.size(); i++) {
InterruptionDuration id = cIdList.get(i);
diff.add(new InterruptionDuration(id.getReason(), id.getDuration()));
}
}
// Add the differences for the intervals that weren't used
if (fDirection == Direction.VARIABLE_OVER_VALUE || fDirection == Direction.VARIABLE_EQ_VALUE) {
for (int i = minSize; i < cIiList.size(); i++) {
InterruptionInterval ii = cIiList.get(i);
diff.add(new InterruptionDuration(ii.getReason(), ii.getMinDuration()));
}
}
}
// For all the intervals that had reasons not shared with the duration
// set
for (Entry<InterruptionReason, InterruptionInterval> entry : copy.entries()) {
diff.add(new InterruptionDuration(entry.getKey(), entry.getValue().getMinDuration()));
}
return diff;
}
/**
* Verify whether a duration matches in one of the interval of this set
*
* @param id
* The duration to check
* @return Whether or not the duration matches in one of the interval of
* this set
*/
public boolean matches(InterruptionDuration id) {
List<InterruptionInterval> list = new ArrayList<>(map.get(id.reason));
if (list.isEmpty()) {
return false;
}
for (InterruptionInterval ii : list) {
if (ii.isMatching(id)) {
return true;
}
}
return false;
}
/**
* Remove an interval of this set that matches a duration
*
* @param id
* The duration to check
* @return Whether or not the duration matched in one of the interval of
* this set
*/
public boolean removeMatching(InterruptionDuration id) {
List<InterruptionInterval> list = new ArrayList<>(map.get(id.reason));
if (list.isEmpty()) {
return false;
}
for (int i = 0; i < list.size(); i++) {
InterruptionInterval ii = list.get(i);
if (ii.isMatching(id)) {
list.remove(i);
return true;
}
}
return false;
}
@Override
public InterruptionIntervalSet clone() {
InterruptionIntervalSet iis = new InterruptionIntervalSet();
iis.map.putAll(map);
iis.counter = this.counter;
iis.fDirection = this.fDirection;
return iis;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((map == null) ? 0 : map.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
InterruptionIntervalSet other = (InterruptionIntervalSet) obj;
if (map == null) {
if (other.map != null) {
return false;
}
} else if (!map.equals(other.map)) {
return false;
}
return true;
}
@Override
public String toString() {
String str = "IntervalSet(" + counter + "): [\n"; //$NON-NLS-1$ //$NON-NLS-2$
for (Entry<InterruptionReason, Collection<InterruptionInterval>> entry : map.asMap().entrySet()) {
double minTime = 0;
double maxTime = 0;
for (InterruptionInterval ii : entry.getValue()) {
minTime += ii.getMinDuration();
maxTime += ii.getMaxDuration();
}
/*
* double minTime = Collections.min(entry.getValue(), new
* Comparator<InterruptionInterval>() {
*
* @Override public int compare(InterruptionInterval ii1,
* InterruptionInterval ii2) { return
* Double.valueOf(ii1.getMinDuration()).compareTo(ii2.getMinDuration
* ()); } }).getMinDuration(); double maxTime =
* Collections.max(entry.getValue(), new
* Comparator<InterruptionInterval>() {
*
* @Override public int compare(InterruptionInterval ii1,
* InterruptionInterval ii2) { return
* Double.valueOf(ii1.getMaxDuration()).compareTo(ii2.getMaxDuration
* ()); } }).getMinDuration();
*/
str += " [" + entry.getKey() + ", " + entry.getValue().size() + ", [" + minTime + ", " + maxTime + "]]\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
}
str += "]"; //$NON-NLS-1$
return str;
}
/**
* @return A one-line string representation of this interval set
*/
public String toStringOneLine() {
boolean first = true;
String str = "["; //$NON-NLS-1$
for (Entry<InterruptionReason, Collection<InterruptionInterval>> entry : map.asMap().entrySet()) {
double minTime = 0;
double maxTime = 0;
for (InterruptionInterval ii : entry.getValue()) {
minTime += ii.getMinDuration();
maxTime += ii.getMaxDuration();
}
if (first) {
first = false;
} else {
str += ", "; //$NON-NLS-1$
}
str += "[" + entry.getKey() + ", " + entry.getValue().size() + ", [" + minTime + ", " + maxTime + "]]";//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
}
str += "]"; //$NON-NLS-1$
return str;
}
/**
* @return The keymap of this interval set
*/
public Map<InterruptionReason, Integer> keyMap() {
return StateMachineVariableHelpers.keyMap(map);
}
/**
* @return A collection of all the intervals in this set
*/
public Collection<InterruptionInterval> getIntervals() {
return map.values();
}
/**
* @return A collection of all the intervals in this set, merged per reason
*/
public Collection<InterruptionInterval> getMergedIntervals() {
Collection<InterruptionInterval> iiCollection = new ArrayList<>(map.asMap().entrySet().size());
for (Entry<InterruptionReason, Collection<InterruptionInterval>> entry : map.asMap().entrySet()) {
InterruptionInterval newii = new InterruptionInterval(entry.getKey());
double minTime = 0;
double maxTime = 0;
for (InterruptionInterval ii : entry.getValue()) {
minTime += ii.getMinDuration();
maxTime += ii.getMaxDuration();
newii.addTsInterval(ii.getTsIntervals());
}
newii.setMinDuration(minTime);
newii.setMaxDuration(maxTime);
newii.setCounter(entry.getValue().size());
iiCollection.add(newii);
}
return iiCollection;
}
}