Skip to content

Commit

Permalink
Merge branch 'master' into highprecision
Browse files Browse the repository at this point in the history
  • Loading branch information
nickbattle committed Dec 16, 2023
2 parents 1698dd8 + fa491ce commit 85dfd56
Show file tree
Hide file tree
Showing 17 changed files with 290 additions and 196 deletions.
22 changes: 20 additions & 2 deletions quickcheck/src/main/java/quickcheck/QuickCheck.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
import quickcheck.strategies.QCStrategy;
import quickcheck.strategies.StrategyResults;
import quickcheck.visitors.FixedRangeCreator;
import quickcheck.visitors.MaybeFinder;
import quickcheck.visitors.TypeBindFinder;

public class QuickCheck
Expand Down Expand Up @@ -399,7 +400,7 @@ else if (results.provedBy != null)
if (values != null)
{
verbose("PO #%d, setting %s, %d values\n", po.number, mbind.toString(), values.size());
mbind.setBindValues(values, timeout);
mbind.setBindValues(values, timeout, results.hasAllValues);
}
else
{
Expand Down Expand Up @@ -428,6 +429,7 @@ else if (results.provedBy != null)
Value execResult = new BooleanValue(false);
ContextException execException = null;
boolean execCompleted = false;
boolean hasMaybe = false;
long before = System.currentTimeMillis();

try
Expand All @@ -442,6 +444,10 @@ else if (results.provedBy != null)
{
ictxt.next();
execResult = poexp.eval(ictxt);

MaybeFinder finder = new MaybeFinder();
poexp.apply(finder, null);
hasMaybe = finder.hasMaybe();
}
while (ictxt.hasNext() && execResult.boolValue(ctxt));

Expand Down Expand Up @@ -502,6 +508,10 @@ else if (execResult instanceof BooleanValue)
{
outcome = POStatus.TIMEOUT;
}
else if (hasMaybe)
{
outcome = POStatus.MAYBE;
}
else if (po.isExistential())
{
outcome = POStatus.PROVED; // An "exists" PO is PROVED, if true.
Expand Down Expand Up @@ -540,6 +550,14 @@ else if (results.hasAllValues && execCompleted)
po.setMessage(null);
po.setWitness(null);
}
else if (hasMaybe)
{
infof(POStatus.MAYBE, "PO #%d, MAYBE %s\n", po.number, duration(before, after));
po.setStatus(POStatus.MAYBE);
po.setCounterexample(null);
po.setMessage(null);
po.setWitness(null);
}
else if (po.isExistential()) // Principal exp is "exists..."
{
if (results.hasAllValues)
Expand Down Expand Up @@ -615,7 +633,7 @@ else if (po.isExistential()) // Principal exp is "exists..."
{
for (INBindingSetter mbind: bindings)
{
mbind.setBindValues(null, 0); // Clears everything
mbind.setBindValues(null, 0, false); // Clears everything
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public StrategyResults getValues(ProofObligation po, INExpression exp, List<INBi

if (po.isCheckable && po.getCheckedExpression() != null)
{
boolean exists = po.kind.isExistential();
boolean exists = po.isExistential();
NameValuePairList nvps = po.getCheckedExpression().apply(new SearchQCVisitor(exists), null);

for (NameValuePair pair: nvps)
Expand Down
88 changes: 88 additions & 0 deletions quickcheck/src/main/java/quickcheck/visitors/MaybeFinder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*******************************************************************************
*
* Copyright (c) 2023 Nick Battle.
*
* Author: Nick Battle
*
* This file is part of VDMJ.
*
* VDMJ is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* VDMJ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with VDMJ. If not, see <http://www.gnu.org/licenses/>.
* SPDX-License-Identifier: GPL-3.0-or-later
*
******************************************************************************/
package quickcheck.visitors;

import java.util.List;
import java.util.Vector;

import com.fujitsu.vdmj.in.expressions.INExistsExpression;
import com.fujitsu.vdmj.in.expressions.INExpression;
import com.fujitsu.vdmj.in.expressions.INForAllExpression;
import com.fujitsu.vdmj.in.expressions.visitors.INLeafExpressionVisitor;

/**
* Search an expression tree after a QuickCheck execution to decide the outcome.
* This is affected by the forall/exists subexpressions, whether they have
* type bindings set and whether the binds have all type values.
*/
public class MaybeFinder extends INLeafExpressionVisitor<Object, List<Object>, Object>
{
private int maybeCount = 0;

public MaybeFinder()
{
super(false);
}

public boolean hasMaybe()
{
return maybeCount > 0;
}

@Override
protected List<Object> newCollection()
{
return new Vector<Object>();
}

@Override
public List<Object> caseExpression(INExpression node, Object arg)
{
return newCollection();
}

@Override
public List<Object> caseForAllExpression(INForAllExpression node, Object arg)
{
if (node.maybe)
{
maybeCount++;
node.maybe = false;
}

return super.caseForAllExpression(node, arg);
}

@Override
public List<Object> caseExistsExpression(INExistsExpression node, Object arg)
{
if (node.maybe)
{
maybeCount++;
node.maybe = false;
}

return super.caseExistsExpression(node, arg);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
package com.fujitsu.vdmj.in.expressions;

import com.fujitsu.vdmj.in.expressions.visitors.INExpressionVisitor;
import com.fujitsu.vdmj.in.patterns.INBindingSetter;
import com.fujitsu.vdmj.in.patterns.INMultipleBind;
import com.fujitsu.vdmj.in.patterns.INMultipleBindList;
import com.fujitsu.vdmj.in.patterns.INPattern;
Expand All @@ -44,6 +43,9 @@ public class INExistsExpression extends INExpression
private static final long serialVersionUID = 1L;
public final INMultipleBindList bindList;
public final INExpression predicate;

/** True if the execution did not have all bind values on exit */
public boolean maybe = false;

public INExistsExpression(LexLocation location, INMultipleBindList bindList, INExpression predicate)
{
Expand All @@ -63,7 +65,7 @@ public Value eval(Context ctxt)
{
breakpoint.check(location, ctxt);
long start = System.currentTimeMillis();
long timeout = getTimeout();
long timeout = bindList.getTimeout();

try
{
Expand All @@ -88,7 +90,8 @@ public Value eval(Context ctxt)
{
if (System.currentTimeMillis() - start > timeout)
{
setCounterexample(null, true);
bindList.setCounterexample(null, true);
maybe = true;
return new BooleanValue(true);
}
}
Expand All @@ -109,7 +112,6 @@ public Value eval(Context ctxt)
{
if (!v.equals(nvp.value))
{
setWitness(evalContext);
matches = false;
break; // This quantifier set does not match
}
Expand All @@ -120,7 +122,8 @@ public Value eval(Context ctxt)
{
if (matches && predicate.eval(evalContext).boolValue(ctxt))
{
setWitness(evalContext);
bindList.setWitness(evalContext);
maybe = false;
return new BooleanValue(true);
}
}
Expand All @@ -135,71 +138,10 @@ public Value eval(Context ctxt)
abort(e);
}

maybe = !bindList.hasAllValues();
return new BooleanValue(false);
}

/**
* This is used by the QuickCheck plugin to limit PO execution times.
*/
private long getTimeout()
{
for (INMultipleBind bind: bindList)
{
if (bind instanceof INBindingSetter) // Type and multitype binds
{
INBindingSetter setter = (INBindingSetter)bind;
long timeout = setter.getTimeout();

if (timeout > 0)
{
return timeout;
}
}
}

return 0;
}

/**
* This is used by the QuickCheck plugin to report which values failed.
*/
private void setCounterexample(Context ctxt, boolean didTimeout)
{
for (INMultipleBind bind: bindList)
{
if (bind instanceof INBindingSetter) // Type and multitype binds
{
INBindingSetter setter = (INBindingSetter)bind;

if (setter.getBindValues() != null) // One we care about (set QC values for)
{
setter.setCounterexample(ctxt, didTimeout);
break; // Just one will do - see QC printFailPath
}
}
}
}

/**
* This is used by the QuickCheck plugin to report which values succeeded.
*/
private void setWitness(Context ctxt)
{
for (INMultipleBind bind: bindList)
{
if (bind instanceof INBindingSetter) // Type and multitype binds
{
INBindingSetter setter = (INBindingSetter)bind;

if (setter.getBindValues() != null) // One we care about (set QC values for)
{
setter.setWitness(ctxt);
break; // Just one will do - see QC printFailPath
}
}
}
}


@Override
public <R, S> R apply(INExpressionVisitor<R, S> visitor, S arg)
{
Expand Down
Loading

0 comments on commit 85dfd56

Please sign in to comment.