Skip to content

Commit

Permalink
Add MddStateSpaceInfo implementation that works with lower and upper …
Browse files Browse the repository at this point in the history
…bounds
  • Loading branch information
mondokm committed Sep 8, 2023
1 parent df6aadb commit 8e55033
Showing 1 changed file with 190 additions and 64 deletions.
Original file line number Diff line number Diff line change
@@ -1,73 +1,199 @@
package hu.bme.mit.theta.analysis.algorithm.symbolic.fixpoint;

import com.google.common.base.Preconditions;
import com.koloboke.collect.map.ObjIntMap;
import com.koloboke.collect.map.hash.HashObjIntMaps;
import com.koloboke.collect.set.ObjSet;
import com.koloboke.collect.set.hash.HashObjSets;
import hu.bme.mit.delta.collections.IntObjCursor;
import hu.bme.mit.delta.collections.IntObjMapView;
import hu.bme.mit.delta.collections.IntSetView;
import hu.bme.mit.delta.collections.IntStatistics;
import hu.bme.mit.delta.collections.impl.IntObjMapViews;
import hu.bme.mit.delta.java.mdd.MddGraph;
import hu.bme.mit.delta.java.mdd.MddNode;
import hu.bme.mit.delta.java.mdd.MddVariable;
import hu.bme.mit.delta.java.mdd.impl.MddStructuralTemplate;
import hu.bme.mit.theta.analysis.algorithm.symbolic.model.StateSpaceInfo;
import hu.bme.mit.theta.common.container.Containers;
import hu.bme.mit.delta.Pair;
import hu.bme.mit.theta.core.type.Expr;
import hu.bme.mit.theta.core.type.booltype.BoolType;

import java.util.Objects;
import java.util.Optional;

import java.util.Set;

import static hu.bme.mit.theta.core.type.booltype.BoolExprs.True;

public final class MddStateSpaceInfo implements StateSpaceInfo {
private final MddVariable variable;
private final MddNode mddNode;

public MddStateSpaceInfo(final MddVariable variable, final MddNode mddNode) {
this.variable = variable;
this.mddNode = mddNode;
}

@Override
public Object getTraceInfo() {
return variable.getTraceInfo();
}

// @Override
// public ElementChain<Object> getComponentChain() {
// class TraceInfoChain implements ElementChain<Object> {
// private final MddVariableHandle mddVariableHandle;
//
// TraceInfoChain(MddVariableHandle mddVariableHandle) {
// Preconditions.checkArgument(mddVariableHandle.getVariable().isPresent());
// this.mddVariableHandle = mddVariableHandle;
// }
//
// @Override
// public Object getElement() {
// return mddVariableHandle.getVariable().orElseThrow(AssertionError::new).getTraceInfo();
// }
//
// @Override
// public ElementChain<Object> next() {
// if (mddVariableHandle.getLower().isPresent()) {
// return new TraceInfoChain(mddVariableHandle.getLower().orElseThrow(AssertionError::new));
// } else {
// return null;
// }
// }
// }
//
// return new TraceInfoChain(variableHandle);
// }

// TODO: else nodes are problematic, better not use them for now
@Override
public boolean hasInfiniteStates() {
if (mddNode.isTerminal()) {
return true;
} else if (mddNode.isBelow(variable)) {
return true;
} else {
return !variable.isNullOrZero(mddNode.defaultValue());
}
}

@Override
public IntSetView getLocalStateSpace() {
return mddNode.keySet();
}

// @Override
// public StateSpaceInfo getLocalStateSpace(final Object someLowerComponent) {
// // TODO: Auto-generated method stub.
// throw new UnsupportedOperationException("Not (yet) implemented.");
// //return null;
// }
private final MddVariable variable;
private final MddNode mddNode;

private MddNode structuralRepresentation = null;

public MddStateSpaceInfo(final MddVariable variable, final MddNode mddNode) {
this.variable = variable;
this.mddNode = mddNode;

for(var c = mddNode.cursor(); c.moveNext();){} // TODO delete later
}

@Override
public Object getTraceInfo() {
return variable.getTraceInfo();
}

// @Override
// public ElementChain<Object> getComponentChain() {
// class TraceInfoChain implements ElementChain<Object> {
// private final MddVariableHandle mddVariableHandle;
//
// TraceInfoChain(MddVariableHandle mddVariableHandle) {
// Preconditions.checkArgument(mddVariableHandle.getVariable().isPresent());
// this.mddVariableHandle = mddVariableHandle;
// }
//
// @Override
// public Object getElement() {
// return mddVariableHandle.getVariable().orElseThrow(AssertionError::new).getTraceInfo();
// }
//
// @Override
// public ElementChain<Object> next() {
// if (mddVariableHandle.getLower().isPresent()) {
// return new TraceInfoChain(mddVariableHandle.getLower().orElseThrow(AssertionError::new));
// } else {
// return null;
// }
// }
// }
//
// return new TraceInfoChain(variableHandle);
// }

// TODO: else nodes are problematic, better not use them for now
@Override
public boolean hasInfiniteStates() {
if (mddNode.isTerminal()) {
return true;
} else if (mddNode.isBelow(variable)) {
return true;
} else {
return !variable.isNullOrZero(mddNode.defaultValue());
}
}

@Override
public IntSetView getLocalStateSpace() {
return mddNode.keySet();
}

@Override
public StateSpaceInfo getLocalStateSpace(final Object someLowerComponent) {
// TODO: Auto-generated method stub.
throw new UnsupportedOperationException("Not (yet) implemented.");
//return null;
}

@Override
public MddNode toStructuralRepresentation() {
if(structuralRepresentation == null){
final BoundsCollector boundsCollector = new BoundsCollector(mddNode, variable);
structuralRepresentation = representBounds(variable, boundsCollector);
}
return structuralRepresentation;

}

private MddNode representBounds(MddVariable variable, BoundsCollector boundsCollector) {
final MddNode continuation;
if(variable.getLower().isPresent()) {
continuation = representBounds(variable.getLower().get(), boundsCollector);
} else {
final MddGraph<Expr<BoolType>> mddGraph = (MddGraph<Expr<BoolType>>) variable.getMddGraph();
continuation = mddGraph.getNodeFor(True());
}
final var bounds = boundsCollector.getBoundsFor(variable);
final IntObjMapView<MddNode> template;
if(bounds.isPresent()){
if(Objects.equals(bounds.get().first, bounds.get().second)){
template = IntObjMapView.singleton(bounds.get().first, continuation);
} else {
// TODO: canonization of trimmed intobjmapviews could be improved
template = new IntObjMapViews.Trimmed<>(
IntObjMapView.empty(continuation),
IntSetView.range(bounds.get().first,bounds.get().second + 1)
);
}
} else {
template = IntObjMapView.empty(continuation);
}

return variable.checkInNode(MddStructuralTemplate.of(template));

}
// private MddNode collapseEdges(MddNode parent) {
//
// IntSetView setView = IntSetView.empty();
// for (var c = parent.cursor(); c.moveNext(); ) {
// setView = setView.union(c.value().keySet());
// }
//
// }

private class BoundsCollector {

private final ObjIntMap<MddVariable> lowerBounds;
private final ObjIntMap<MddVariable> upperBounds;
private final ObjSet<MddVariable> hasDefaultValue;

public BoundsCollector(MddNode rootNode, MddVariable variable) {
Preconditions.checkNotNull(rootNode);
this.lowerBounds = HashObjIntMaps.newUpdatableMap();
this.upperBounds = HashObjIntMaps.newUpdatableMap();
this.hasDefaultValue = HashObjSets.newUpdatableSet();

final Set<MddNode> traversed = Containers.createSet();
traverse(rootNode, variable, traversed);
}

private void traverse(final MddNode node, final MddVariable variable,
final Set<MddNode> traversed) {
if (traversed.contains(node) || node.isTerminal()) {
return;
} else {
traversed.add(node);
}

for(var c = node.cursor(); c.moveNext();){} // TODO delete later

if (node.defaultValue() != null) {
final MddNode defaultValue = node.defaultValue();
traverse(defaultValue, variable.getLower().orElse(null), traversed);
hasDefaultValue.add(variable);
} else {
final IntStatistics statistics = node.statistics();
if (variable != null) {
lowerBounds.put(variable, Math.min(lowerBounds.getOrDefault(variable, Integer.MAX_VALUE), statistics.lowestValue()));
upperBounds.put(variable, Math.max(upperBounds.getOrDefault(variable, Integer.MIN_VALUE), statistics.highestValue()));
}

for (var cur = node.cursor(); cur.moveNext(); ) {
if (cur.value() != null) {
traverse(cur.value(), variable.getLower().orElse(null), traversed);
}
}
}
}


public Optional<Pair<Integer, Integer>> getBoundsFor(MddVariable variable) {
if (hasDefaultValue.contains(variable)) return Optional.empty();
if (!lowerBounds.containsKey(variable) || !upperBounds.containsKey(variable)) return Optional.empty();
return Optional.of(new Pair<>(lowerBounds.getInt(variable), upperBounds.getInt(variable)));
}
}

}

0 comments on commit 8e55033

Please sign in to comment.