Mercurial > hg > Members > kono > jpf-core
view src/tests/gov/nasa/jpf/test/mc/data/CrossingTest.java @ 0:61d41facf527
initial v8 import (history reset)
author | Peter Mehlitz <Peter.C.Mehlitz@nasa.gov> |
---|---|
date | Fri, 23 Jan 2015 10:14:01 -0800 |
parents | |
children |
line wrap: on
line source
/* * Copyright (C) 2014, United States Government, as represented by the * Administrator of the National Aeronautics and Space Administration. * All rights reserved. * * The Java Pathfinder core (jpf-core) platform is 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. */ /** * This is the famous Bridge-crossing puzzle. The aim is to see what the minimum * amount of time is for 4 people to cross with flash-light (torch): 10.5.2.1. * The answer is 17 for the given configuration. * * One can find this solution with JPF in BFS search mode - DFS will not * work since this is an infinite-state program (time keeps increasing). * * If one uses the ignoreIf(cond) call the branches that will lead to * solutions worst than the current will be cut-off and this will allow * DFS also to complete - and BFS to terminate faster. * * When setting the native flag in main one can also save information * from one run to the next using JPF's native peer methods - * see JPF_Crossing.java for the code of getTotal() and setTotal(int). */ package gov.nasa.jpf.test.mc.data; import gov.nasa.jpf.util.test.TestJPF; import gov.nasa.jpf.vm.Verify; import org.junit.Test; public class CrossingTest extends TestJPF { static class Constants { public static final boolean east = true; public static final boolean west = false; } static class Torch { public static boolean side = Constants.east; @Override public String toString() { if (side == Constants.east) { return "east"; } else { return "west"; } } } static class Bridge { static Person[] onBridge = new Person[2]; static int numOnBridge = 0; public static boolean isFull() { return numOnBridge != 0; } public static int Cross() { int time = 0; Torch.side = !Torch.side; if (numOnBridge == 1) { onBridge[0].side = Torch.side; time = onBridge[0].time; //System.out.println("Person " + onBridge[0] + // " moved to " + Torch.side + // " in time " + time); } else { assert onBridge[0] != null : "Argh, null " + numOnBridge; assert onBridge[1] != null; onBridge[0].side = Torch.side; onBridge[1].side = Torch.side; if (onBridge[0].time > onBridge[1].time) { time = onBridge[0].time; } else { time = onBridge[1].time; } //System.out.println("Person " + onBridge[0] + // " and Person " + onBridge[1] + // " moved to " + Torch.side + // " in time " + time); } return time; } public static void clearBridge() { if (numOnBridge == 0) { return; } else if (numOnBridge == 1) { onBridge[0] = null; numOnBridge = 0; } else { onBridge[0] = null; onBridge[1] = null; numOnBridge = 0; } } public static void initBridge() { onBridge[0] = null; onBridge[1] = null; numOnBridge = 0; } public static boolean tryToCross(Person th) { if ((numOnBridge < 2) && (onBridge[0] != th) && (onBridge[1] != th)) { onBridge[numOnBridge++] = th; return true; } else { return false; } } } static class Person { // person to cross the bridge int id; public int time; public boolean side; public Person(int i, int t) { time = t; side = Constants.east; id = i; } public void move() { if (side == Torch.side) { if (!Verify.randomBool()) { Bridge.tryToCross(this); } } } @Override public String toString() { return "" + id; } } public static native void setTotal(int time); // due to these natives the code only runs in JPF public static native int getTotal(); public void run() { //Verify.beginAtomic(); // when natives are used one can record the minimal value found so // far to get a better one on the next execution - this // requires the -mulitple-errors option and then the last error // found must be replayed boolean isNative = false; if (isNative) { setTotal(30); // set to value larger than solution (17) } int total = 0; boolean finished = false; Bridge.initBridge(); Person p1 = new Person(1, 1); Person p2 = new Person(2, 2); Person p3 = new Person(3, 5); Person p4 = new Person(4, 10); //Verify.endAtomic(); while (!finished) { //Verify.beginAtomic(); p1.move(); p2.move(); p3.move(); p4.move(); if (Bridge.isFull()) { total += Bridge.Cross(); if (isNative) { Verify.ignoreIf(total > getTotal()); } else { Verify.ignoreIf(total > 17); //with this DFS will also find error } Bridge.clearBridge(); //printConfig(p1,p2,p3,p4,total); finished = !(p1.side || p2.side || p3.side || p4.side); } //Verify.endAtomic(); } //Verify.beginAtomic(); if (isNative) { if (total < getTotal()) { System.out.println("new total " + total); setTotal(total); assert (total > getTotal()); } } else { System.out.println("total time = " + total); assert (total > 17) : "total > 17 | total = " + total; } //Verify.endAtomic(); } static void printConfig(Person p1, Person p2, Person p3, Person p4, int total) { if (p1.side == Constants.east) { System.out.print("p1(" + p1.time + ")"); } if (p2.side == Constants.east) { System.out.print("p2(" + p2.time + ")"); } if (p3.side == Constants.east) { System.out.print("p3(" + p3.time + ")"); } if (p4.side == Constants.east) { System.out.print("p4(" + p4.time + ")"); } System.out.print(" - " + total + " -> "); if (p1.side == Constants.west) { System.out.print("p1(" + p1.time + ")"); } if (p2.side == Constants.west) { System.out.print("p2(" + p2.time + ")"); } if (p3.side == Constants.west) { System.out.print("p3(" + p3.time + ")"); } if (p4.side == Constants.west) { System.out.print("p4(" + p4.time + ")"); } System.out.println(); } @Test public void testNoHeuristic () { if (verifyAssertionError()){ run(); } } @Test public void testBFSHeuristic() { if (verifyAssertionError("+search.class=gov.nasa.jpf.search.heuristic.BFSHeuristic")){ run(); } } }