All Downloads are FREE. Search and download functionalities are using the official Maven repository.

main.io.github.moonlightsuite.moonlight.offline.algorithms.BooleanOp Maven / Gradle / Ivy

Go to download

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.offline.algorithms;

import io.github.moonlightsuite.moonlight.offline.signal.Signal;
import io.github.moonlightsuite.moonlight.offline.signal.SignalCursor;

import java.util.Arrays;
import java.util.List;
import java.util.function.*;
import java.util.stream.Stream;

import static io.github.moonlightsuite.moonlight.offline.signal.SignalCursor.isNotCompleted;

public class BooleanOp {
    private static final String
            ERROR = "signal data structure failed irreparably";
    private final boolean forward;
    private Signal output;
    private double time;

    public BooleanOp() {
        forward = true;
    }

    public BooleanOp(boolean isForward) {
        forward = isForward;
    }

    private static  T error() {
        throw new UnsupportedOperationException(ERROR);
    }

    public Signal applyUnary(Signal s, Function op) {
        return applyOp(cursors ->
                op.apply(cursors.get(0).getCurrentValue()), s);
    }

    public Signal applyUnaryWithBound(Signal s, BiFunction op, R init) {
        return applyOpWith1StepMemory(
                (cursors, prev) -> op.apply(cursors.get(0).getCurrentValue(), prev),
                init, s);
    }

    public Signal applyBinary(Signal s1,
                                 BiFunction op,
                                 Signal s2) {
        return applyOp(cursors -> op.apply(cursors.get(0).getCurrentValue(),
                        cursors.get(1).getCurrentValue()),
                s1, s2);
    }

    @SafeVarargs
    private Signal applyOp(
            Function>, R> op,
            Signal... signals) {
        output = new Signal<>();
        setStartingTime(signals);
        List> cs = prepareCursors(signals);
        apply(cs, () -> op.apply(cs));
        setEndingTime(signals);
        return output;
    }

    @SafeVarargs
    private Signal applyOpWith1StepMemory(
            BiFunction>, R, R> op,
            R init,
            Signal... signals) {
        output = new Signal<>();
        setStartingTime(signals);
        List> cs = prepareCursors(signals);
        applyWithOneStepMemory(cs, prev -> op.apply(cs, prev), init);
        setEndingTime(signals);
        return output;
    }



    public Signal filterUnary(Signal s, Predicate p) {
        return filterOp(cursors -> cursors.get(0).getCurrentValue(), p, s);
    }

    @SafeVarargs
    private Signal filterOp(
            Function>, R> op,
            Predicate p,
            Signal... signals) {
        output = new Signal<>();
        setStartingTime(signals);
        List> cs = prepareCursors(signals);

        applyFilter(cs, p, () -> op.apply(cs));

        setEndingTime(signals);
        return output;
    }

    private void applyFilter(List> cursors,
                                 Predicate p,
                                 Supplier value) {
        while (isNotCompleted(cursors)) {
            addResult(p.test(value.get()) ? value.get() : null);
            moveCursorsForward(cursors);
        }
    }

    @SafeVarargs
    private  void setStartingTime(Signal... signals) {
        if (forward)
            time = maxStart(Arrays.stream(signals));
        else
            time = minEnd(Arrays.stream(signals));
    }

    private  double maxStart(Stream> stream) {
        return stream.map(Signal::getStart)
                .reduce(Math::max)
                .orElseGet(BooleanOp::error);
    }

    private  double minEnd(Stream> stream) {
        return stream.map(Signal::getEnd)
                .reduce(Math::min)
                .orElseGet(BooleanOp::error);
    }

    @SafeVarargs
    private  void setEndingTime(Signal... signals) {
        if (!output.isEmpty()) {
            double end = minEnd(Arrays.stream(signals));
            output.endAt(end);
        }
    }

    private  void apply(List> cursors,
                           Supplier value) {
        while (isNotCompleted(cursors)) {
            addResult(value.get());
            moveCursorsForward(cursors);
        }
    }

    private  void applyWithOneStepMemory(List> cursors,
                                            UnaryOperator value, R init) {
        R prev = init;
        while (isNotCompleted(cursors)) {
            prev = value.apply(prev);
            addResult(prev);
            moveCursorsForward(cursors);
        }
    }

    @SafeVarargs
    private  List> prepareCursors(
            Signal... signals) {
        return Arrays.stream(signals).map(s -> {
            var c = s.getIterator(forward);
            c.move(time);
            return c;
        }).toList();
    }

    private void addResult(R value) {
        if (forward) {
            output.add(time, value);
        } else {
            output.addBefore(time, value);
        }
    }

    private  void moveCursorsForward(List> cursors) {
        time = cursors.stream()
                .map(this::moveTime)
                .reduce(rightEndingTime())
                .orElseGet(BooleanOp::error);
        cursors.forEach(c -> c.move(time));
    }

    private BinaryOperator rightEndingTime() {
        if (forward)
            return Math::min;
        return Math::max;
    }

    private  double moveTime(SignalCursor cursor) {
        if (forward)
            return cursor.nextTime();
        return cursor.previousTime();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy