Skip to content

Commit

Permalink
Added witness generation for kind and imc
Browse files Browse the repository at this point in the history
  • Loading branch information
leventeBajczi committed Nov 16, 2023
1 parent 9db1fda commit 2a9e8c1
Show file tree
Hide file tree
Showing 12 changed files with 181 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -243,13 +243,13 @@ private void run() {
sw.stop();
} else if (algorithm == Algorithm.KINDUCTION) {
var transFunc = CfaToMonoliticTransFunc.create(cfa);
var checker = new KIndChecker<>(transFunc, Integer.MAX_VALUE, 0, 1, Z3SolverFactory.getInstance().createSolver(), Z3SolverFactory.getInstance().createSolver(), ExplState::of, cfa.getVars());
var checker = new KIndChecker<>(transFunc, Integer.MAX_VALUE, 0, 1, Z3SolverFactory.getInstance().createSolver(), Z3SolverFactory.getInstance().createSolver(), ExplState::of, null, cfa.getVars());
status = checker.check(null);
logger.write(Logger.Level.RESULT, "%s%n", status);
sw.stop();
} else if (algorithm == Algorithm.IMC) {
var transFunc = CfaToMonoliticTransFunc.create(cfa);
var checker = new ImcChecker<>(transFunc, Integer.MAX_VALUE, Z3SolverFactory.getInstance().createItpSolver(), ExplState::of, cfa.getVars());
var checker = new ImcChecker<>(transFunc, Integer.MAX_VALUE, Z3SolverFactory.getInstance().createItpSolver(), ExplState::of, cfa.getVars(), null);
status = checker.check(null);
logger.write(Logger.Level.RESULT, "%s%n", status);
sw.stop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.BiFunction;
import java.util.function.Function;

import static hu.bme.mit.theta.core.type.booltype.SmartBoolExprs.And;
Expand All @@ -52,25 +54,28 @@ public class ImcChecker<S extends ExprState, A extends StmtAction> implements Sa
private final Expr<BoolType> init;
private final Expr<BoolType> prop;
private final int upperBound;
private ItpSolver solver;
private final ItpSolver solver;
private final VarIndexing firstIndexing;
private final VarIndexing offset;
private final Function<Valuation, S> valToState;
private final BiFunction<Valuation, Valuation, A> valsToAction;
private final Collection<VarDecl<?>> vars;
private final int timeout;

public ImcChecker(MonolithicTransFunc transFunc,
int upperBound,
ItpSolver solver,
Function<Valuation, S> valToState,
Collection<VarDecl<?>> vars) {
this(transFunc, upperBound, solver, valToState, vars, 0);
Collection<VarDecl<?>> vars,
BiFunction<Valuation, Valuation, A> valsToAction) {
this(transFunc, upperBound, solver, valToState, valsToAction, vars, 0);
}

public ImcChecker(MonolithicTransFunc transFunc,
int upperBound,
ItpSolver solver,
Function<Valuation, S> valToState,
BiFunction<Valuation, Valuation, A> valsToAction,
Collection<VarDecl<?>> vars,
int timeout) {
this.trans = transFunc.getTransExpr();
Expand All @@ -81,6 +86,7 @@ public ImcChecker(MonolithicTransFunc transFunc,
this.firstIndexing = transFunc.getInitIndexing();
this.offset = transFunc.getOffsetIndexing();
this.valToState = valToState;
this.valsToAction = valsToAction;
this.vars = vars;
this.timeout = timeout;
}
Expand Down Expand Up @@ -121,15 +127,21 @@ public SafetyResult<S, A> check(UnitPrec prec) {
}

if (status.isSat()) {
S initial = null;
for (int j = 0; j < listOfIndexes.size(); j++) {
var valuation = PathUtils.extractValuation(solver.getModel(), listOfIndexes.get(j), vars);

S st = valToState.apply(valuation);
if (initial == null)
initial = st;
var stateList = new LinkedList<S>();
var actionList = new LinkedList<A>();
if (valToState != null && valsToAction != null) {
Valuation lastValuation = null;
for (int j = 0; j < listOfIndexes.size(); j++) {
VarIndexing listOfIndex = listOfIndexes.get(j);
var valuation = PathUtils.extractValuation(solver.getModel(), listOfIndex, vars);
stateList.add(valToState.apply(valuation));
if (j > 0) {
actionList.add(valsToAction.apply(lastValuation, valuation));
}
lastValuation = valuation;
}
}
Trace<S, A> trace = Trace.of(List.of(initial), List.of());
Trace<S, A> trace = Trace.of(stateList, actionList);
return SafetyResult.unsafe(trace, ARG.create(null));
}
// reached fixed point
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.LinkedList;
import java.util.function.BiFunction;
import java.util.function.Function;

import static hu.bme.mit.theta.core.type.abstracttype.AbstractExprs.Eq;
Expand All @@ -51,11 +52,12 @@ public class KIndChecker<S extends ExprState, A extends ExprAction> implements S
private final int upperBound;
private final int inductionStartBound;
private final int inductionFrequency;
private Solver solver1;
private Solver solver2;
private final Solver solver1;
private final Solver solver2;
private final VarIndexing firstIndexing;
private final VarIndexing offset;
private final Function<Valuation, S> valToState;
private final BiFunction<Valuation, Valuation, A> valsToAction;
private final Collection<VarDecl<?>> vars;


Expand All @@ -66,6 +68,7 @@ public KIndChecker(MonolithicTransFunc transFunc,
Solver solver1,
Solver solver2,
Function<Valuation, S> valToState,
BiFunction<Valuation, Valuation, A> valsToAction,
Collection<VarDecl<?>> vars) {
this.trans = transFunc.getTransExpr();
this.init = transFunc.getInitExpr();
Expand All @@ -78,6 +81,7 @@ public KIndChecker(MonolithicTransFunc transFunc,
this.firstIndexing = transFunc.getInitIndexing();
this.offset = transFunc.getOffsetIndexing();
this.valToState = valToState;
this.valsToAction = valsToAction;
this.vars = vars;
}

Expand Down Expand Up @@ -109,6 +113,8 @@ public SafetyResult<S, A> check(UnitPrec prec) {
eqList.addAll(finalList);
listOfIndexes.add(currIndex);

var lastIndex = currIndex;

currIndex = currIndex.add(offset);

// Checking loop free path of length i
Expand All @@ -131,15 +137,23 @@ public SafetyResult<S, A> check(UnitPrec prec) {
solver1.add(PathUtils.unfold(Not(prop), currIndex));

if (solver1.check().isSat()) {
S initial = null;
for (int j = 0; j < listOfIndexes.size(); j++) {
var valuation = PathUtils.extractValuation(solver1.getModel(), listOfIndexes.get(j), vars);

S st = valToState.apply(valuation);
if (initial == null)
initial = st;
// otherwise trace is cut off before last action
listOfIndexes.add(currIndex);
var stateList = new LinkedList<S>();
var actionList = new LinkedList<A>();
if (valToState != null && valsToAction != null) {
Valuation lastValuation = null;
for (int j = 0; j < listOfIndexes.size(); j++) {
VarIndexing listOfIndex = listOfIndexes.get(j);
var valuation = PathUtils.extractValuation(solver1.getModel(), listOfIndex, vars);
stateList.add(valToState.apply(valuation));
if (j > 0) {
actionList.add(valsToAction.apply(lastValuation, valuation));
}
lastValuation = valuation;
}
}
Trace<S, A> trace = Trace.of(List.of(initial), List.of());
Trace<S, A> trace = Trace.of(stateList, actionList);
return SafetyResult.unsafe(trace, ARG.create(null));
}
solver1.pop();
Expand All @@ -148,8 +162,8 @@ public SafetyResult<S, A> check(UnitPrec prec) {

// P1 and T1-2 and P2 and ... and Tk-k+1

solver2.add(PathUtils.unfold(prop, currIndex.sub(firstIndexing)));
solver2.add(PathUtils.unfold(trans, currIndex.sub(firstIndexing)));
solver2.add(PathUtils.unfold(prop, lastIndex.sub(firstIndexing)));
solver2.add(PathUtils.unfold(trans, lastIndex.sub(firstIndexing)));

// Not Pk+1
if (i >= inductionStartBound && (i - inductionStartBound) % inductionFrequency == 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,20 @@
*/
package hu.bme.mit.theta.core.model;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

import java.util.Collection;
import java.util.Map;
import java.util.Optional;

import com.google.common.collect.ImmutableMap;

import hu.bme.mit.theta.core.decl.Decl;
import hu.bme.mit.theta.core.type.Expr;
import hu.bme.mit.theta.core.type.LitExpr;
import hu.bme.mit.theta.core.type.Type;
import hu.bme.mit.theta.core.type.booltype.BoolType;

import java.util.Collection;
import java.util.Map;
import java.util.Optional;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

/**
* Basic, immutable implementation of a valuation. The inner builder class can be used to create a
* new instance.
Expand Down Expand Up @@ -60,6 +59,14 @@ public static ImmutableValuation copyOf(final Valuation val) {
}
}

public static ImmutableValuation from(final Map<Decl<?>, LitExpr<?>> map) {
final Builder builder = builder();
for (final Decl<?> decl : map.keySet()) {
builder.put(decl, map.get(decl));
}
return builder.build();
}

public static ImmutableValuation empty() {
return LazyHolder.EMPTY;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ private VarPoolUtil() {

public static VarDecl<IntType> requestInt() {
if (intPool.isEmpty()) {
return Decls.Var("temp" + counter++, Int());
return Decls.Var("__temp_" + counter++, Int());
} else {
return intPool.remove();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,11 @@ private void run() {
status = check(configuration);
} else if (algorithm.equals(Algorithm.KINDUCTION)) {
var transFunc = StsToMonoliticTransFunc.create(sts);
var checker = new KIndChecker<>(transFunc, Integer.MAX_VALUE, 0, 1, Z3SolverFactory.getInstance().createSolver(), Z3SolverFactory.getInstance().createSolver(), ExplState::of, sts.getVars());
var checker = new KIndChecker<>(transFunc, Integer.MAX_VALUE, 0, 1, Z3SolverFactory.getInstance().createSolver(), Z3SolverFactory.getInstance().createSolver(), ExplState::of, null, sts.getVars());
status = checker.check(null);
} else if (algorithm.equals(Algorithm.IMC)) {
var transFunc = StsToMonoliticTransFunc.create(sts);
var checker = new ImcChecker<>(transFunc, Integer.MAX_VALUE, Z3SolverFactory.getInstance().createItpSolver(), ExplState::of, sts.getVars());
var checker = new ImcChecker<>(transFunc, Integer.MAX_VALUE, Z3SolverFactory.getInstance().createItpSolver(), ExplState::of, sts.getVars(), null);
status = checker.check(null);
}
sw.stop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ package hu.bme.mit.theta.xcfa.cli
import com.beust.jcommander.Parameter
import hu.bme.mit.theta.analysis.algorithm.imc.ImcChecker
import hu.bme.mit.theta.analysis.expl.ExplState
import hu.bme.mit.theta.analysis.expr.ExprState
import hu.bme.mit.theta.analysis.expr.StmtAction
import hu.bme.mit.theta.core.utils.ExprUtils
import hu.bme.mit.theta.xcfa.analysis.XcfaAction
import hu.bme.mit.theta.xcfa.analysis.XcfaMonolithicTransFunc
import hu.bme.mit.theta.xcfa.analysis.XcfaState
import hu.bme.mit.theta.xcfa.cli.utils.valToAction
import hu.bme.mit.theta.xcfa.cli.utils.valToState
import hu.bme.mit.theta.xcfa.model.XCFA

data class XcfaImcConfig(
Expand All @@ -38,13 +40,14 @@ data class XcfaImcConfig(
var remainingFlags: MutableList<String> = ArrayList()
) {

fun getIMCChecker(xcfa: XCFA, timeout: Int = 0): ImcChecker<ExprState, StmtAction> {
fun getIMCChecker(xcfa: XCFA, timeout: Int = 0): ImcChecker<XcfaState<ExplState>, XcfaAction> {
val transFunc = XcfaMonolithicTransFunc.create(xcfa)
return ImcChecker<ExprState, StmtAction>(
return ImcChecker<XcfaState<ExplState>, XcfaAction>(
transFunc,
maxBound,
getSolver(imcSolver, validateIMCSolver).createItpSolver(),
ExplState::of,
{ val1 -> valToState(xcfa, val1) },
{ val1, val2 -> valToAction(xcfa, val1, val2) },
ExprUtils.getVars(transFunc.transExpr),
timeout)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ package hu.bme.mit.theta.xcfa.cli
import com.beust.jcommander.Parameter
import hu.bme.mit.theta.analysis.algorithm.kind.KIndChecker
import hu.bme.mit.theta.analysis.expl.ExplState
import hu.bme.mit.theta.analysis.expr.ExprAction
import hu.bme.mit.theta.analysis.expr.ExprState
import hu.bme.mit.theta.core.utils.ExprUtils
import hu.bme.mit.theta.xcfa.analysis.XcfaAction
import hu.bme.mit.theta.xcfa.analysis.XcfaMonolithicTransFunc
import hu.bme.mit.theta.xcfa.analysis.XcfaState
import hu.bme.mit.theta.xcfa.cli.utils.valToAction
import hu.bme.mit.theta.xcfa.cli.utils.valToState
import hu.bme.mit.theta.xcfa.model.XCFA

data class XcfaKindConfig(
Expand All @@ -49,16 +51,17 @@ data class XcfaKindConfig(
var remainingFlags: MutableList<String> = ArrayList()
) {

fun getKindChecker(xcfa: XCFA): KIndChecker<ExprState, ExprAction> {
fun getKindChecker(xcfa: XCFA): KIndChecker<XcfaState<ExplState>, XcfaAction> {
val transFunc = XcfaMonolithicTransFunc.create(xcfa)
return KIndChecker<ExprState, ExprAction>(
return KIndChecker<XcfaState<ExplState>, XcfaAction>(
transFunc,
maxBound,
indMinBound,
indFreq,
getSolver(bmcSolver, validateBMCSolver).createSolver(),
getSolver(indSolver, validateIndSolver).createSolver(),
ExplState::of,
{ val1 -> valToState(xcfa, val1) },
{ val1, val2 -> valToAction(xcfa, val1, val2) },
ExprUtils.getVars(transFunc.transExpr))
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright 2023 Budapest University of Technology and Economics
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package hu.bme.mit.theta.xcfa.cli.utils

import hu.bme.mit.theta.analysis.expl.ExplState
import hu.bme.mit.theta.core.decl.Decls.Var
import hu.bme.mit.theta.core.model.ImmutableValuation
import hu.bme.mit.theta.core.model.Valuation
import hu.bme.mit.theta.core.type.inttype.IntLitExpr
import hu.bme.mit.theta.xcfa.analysis.XcfaAction
import hu.bme.mit.theta.xcfa.analysis.XcfaProcessState
import hu.bme.mit.theta.xcfa.analysis.XcfaState
import hu.bme.mit.theta.xcfa.model.XCFA
import hu.bme.mit.theta.xcfa.model.XcfaLocation
import java.util.*

fun valToAction(xcfa: XCFA, val1: Valuation, val2: Valuation): XcfaAction {
val val1Map = val1.toMap()
val val2Map = val2.toMap()
var i = 0
val map: MutableMap<XcfaLocation, Int> = HashMap()
for (x in xcfa.procedures.first().locs) {
map[x] = i++
}
return XcfaAction(
pid = 0,
edge = xcfa.procedures.first().edges.first { edge ->
map[edge.source] == (val1Map[val1Map.keys.first { it.name == "__loc_" }] as IntLitExpr).value.toInt() &&
map[edge.target] == (val2Map[val2Map.keys.first { it.name == "__loc_" }] as IntLitExpr).value.toInt()
})
}

fun valToState(xcfa: XCFA, val1: Valuation): XcfaState<ExplState> {
val valMap = val1.toMap()
var i = 0
val map: MutableMap<Int, XcfaLocation> = HashMap()
for (x in xcfa.procedures.first().locs) {
map[i++] = x
}
return XcfaState(
xcfa=xcfa,
processes = mapOf(Pair(0, XcfaProcessState(
locs = LinkedList(listOf(map[(valMap[valMap.keys.first { it.name == "__loc_" }] as IntLitExpr).value.toInt()])),
varLookup = LinkedList(),
))),
ExplState.of(
ImmutableValuation.from(
val1.toMap()
.filter { it.key.name != "__loc_" && !it.key.name.startsWith("__temp_") }
.map { Pair(Var("_" + "_" + it.key.name, it.key.type), it.value) }.toMap())),
mutexes = emptyMap(),
threadLookup = emptyMap(),
bottom = false
)
}
Loading

0 comments on commit 2a9e8c1

Please sign in to comment.