main.io.github.moonlightsuite.moonlight.online.algorithms.BooleanOp Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of moonlight-engine Show documentation
Show all versions of moonlight-engine Show documentation
MoonLight is a light-weight Java-tool for monitoring temporal, spatial and spatio-temporal properties of distributed complex systems, such as Cyber-Physical Systems and Collective Adaptive Systems.
The newest version!
package io.github.moonlightsuite.moonlight.online.algorithms;
import io.github.moonlightsuite.moonlight.core.signal.Sample;
import io.github.moonlightsuite.moonlight.online.signal.*;
import java.util.*;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
/**
*
*/
public class BooleanOp {
private BooleanOp() {} // hidden constructor
/**
*
* @param u update of the input signal
* @param op operation to be performed
* @param Time domain, usually expressed as a {@link Number}
* @param Input signal domain
* @param Output robustness domain
* @return an update of the robustness signal in input
*/
public static
, V, R>
Update atom(Update u, Function op)
{
return new Update<>(u.getStart(), u.getEnd(),
op.apply(u.getValue()));
}
/**
*
* @param us update of the input signal
* @param op operation to be performed
* @param Time domain, usually expressed as a {@link Number}
* @param Input signal domain
* @param Output robustness domain
* @return an update of the robustness signal in input
*/
public static
,
V,
R>
TimeChain atomSequence(TimeChain us, Function op)
{
List> ls =
us.stream()
.map(s -> new TimeSegment<>(s.getStart(), op.apply(s.getValue())))
.collect(Collectors.toList());
return new TimeChain<>(ls, us.getEnd());
}
public static
, V, R>
TimeChain atomSequence(Update u, Function op)
{
List> ups = new ArrayList<>();
ups.add(atom(u, op));
return Update.asTimeChain(ups);
}
/**
*
* @param u update of the operand
* @param op operation to be performed
* @param Time domain, usually expressed as a {@link Number}
* @param Output robustness domain
* @return an update of the robustness signal in input
*/
public static
, R>
List> unary(Update u, UnaryOperator op)
{
Update result = new Update<>(u.getStart(), u.getEnd(),
op.apply(u.getValue()));
List> results = new ArrayList<>();
results.add(result);
return results;
}
/**
*
* @param us chain of updates of the operand
* @param op operation to be performed
* @param Time domain, usually expressed as a {@link Number}
* @param Output robustness domain
* @return an update of the robustness signal in input
*/
public static
, R>
TimeChain unarySequence(TimeChain us, UnaryOperator op)
{
List> ls =
us.stream()
.map(s -> new TimeSegment<>(s.getStart(), op.apply(s.getValue())))
.collect(Collectors.toList());
return new TimeChain<>(ls, us.getEnd());
}
/**
* TODO: this should be different for left and right operands
* @param c1 input signal of first argument
* @param us updates of second argument
* @param op operation to be performed (e.g. and/or)
* @param time domain of the signals
* @param evaluation domain of the semantics
* @return a chain of sequential updates
*/
public static
, R>
TimeChain binarySequence(TimeChain c1,
TimeChain us,
BinaryOperator op)
{
List> updates = new ArrayList<>(us.size());
ChainsCombinator itr = new ChainsCombinator<>(c1, us);
itr.forEach((segment, update) -> binaryOp(segment, update, updates, op));
return new TimeChain<>(updates, us.getEnd());
}
public static
, R>
List> binary(TimeChain c1,
Update u,
BinaryOperator op)
{
List> updates;
updates = rightApply(c1, op, u); // TODO: this should be different for
// left and right operands
return updates;
}
private static
, R>
List> rightApply(TimeChain s,
BinaryOperator op, Update u)
{
List> updates = new ArrayList<>();
ChainIterator> itr = s.chainIterator();
Sample curr;
T nextTime;
while(itr.hasNext()) {
curr = itr.next();
nextTime = tryPeekNextStart(itr, s.getEnd());
exec(curr, u, nextTime, op, updates);
}
return updates;
}
private static , R>
void exec(Sample curr, Update u, T nextTime,
BinaryOperator op, List> updates)
{
if(curr.getStart().compareTo(u.getEnd()) < 0
&& nextTime.compareTo(u.getStart()) >= 0)
{
T end = min(nextTime, u.getEnd());
T start = max(curr.getStart(), u.getStart());
if(!start.equals(end)) {
Update r = new Update<>(start, end,
op.apply(u.getValue(), curr.getValue()));
updates.add(r);
}
}
}
private static , R>
void binaryOp(Sample left,
Sample right,
List> output,
BinaryOperator op)
{
T start = max(left, right).getStart();
R value = op.apply(right.getValue(), left.getValue());
Sample r = new TimeSegment<>(start, value);
int last = output.size() - 1;
if(output.isEmpty() || !output.get(last).getValue().equals(value))
output.add(r);
}
private static > R max(R a, R b) {
return a.compareTo(b) >= 0 ? a : b;
}
private static > R min(R a, R b) {
return a.compareTo(b) <= 0 ? a : b;
}
/**
* Fail-safe method for fetching data from next element (if exists).
*
* @param itr iterator to use for looking forward
* @param defaultValue value to return in case of failure
* @param time domain of interest, usually a Number
* @param domain of the returned value
* @return the next time value if present, otherwise the default one.
*/
static , V>
T tryPeekNextStart(ChainIterator> itr, T defaultValue)
{
if(itr.hasNext())
return itr.peekNext().getStart();
else
return defaultValue;
}
}