scyther/test/compareheuristics.py

258 lines
7.0 KiB
Python
Raw Normal View History

#!/usr/bin/python
#
# Compare heuristics
#
import sys
from optparse import OptionParser
import scythertest
2006-02-23 16:10:52 +00:00
hurry = False # True then branch and bound
# Parse
def parse(scout):
"""Parse Scyther output for heuristics tests
in:
A single Scyther output string (including newlines)
out:
ra: number of failed claims
rb: number of bounded proofs of claims
rp: number of complete proofs of claims
nc: number of processed claims (should be the sum of the previous)
st: number of states traversed
"""
ra = 0
rb = 0
rp = 0
nc = 0
st = 0
to = 0
for l in scout.splitlines():
data = l.split()
if len(data) > 4 and data[0] == 'claim':
# Determine timeout, count states
nc += 1
timeout = False
2006-02-28 15:06:21 +00:00
localstates = 0
for d in data:
if d.startswith("states="):
2006-02-28 15:06:21 +00:00
localstates += int(d[7:])
2006-02-23 16:10:52 +00:00
if d.startswith("time="):
timeout = True
2006-02-28 15:06:21 +00:00
# Only count the states if no timeout (otherwise not
# dependable)
2006-03-16 13:58:45 +00:00
##if not timeout:
## st += localstates
st += localstates
2006-02-28 15:06:21 +00:00
# Determine claim status
tag = data[4]
if tag == 'Fail':
ra += 1
2006-02-28 15:06:21 +00:00
else:
if not timeout:
if tag == 'Ok':
if l.rfind("proof of correctness") != -1:
rp += 1
else:
rb += 1
else:
2006-02-28 15:06:21 +00:00
print "Weird tag [%s] in line [%s]." % (tag, l)
else:
2006-02-28 15:06:21 +00:00
to += 1
return (ra,rb,rp,nc,st,to)
2006-02-23 09:39:02 +00:00
def test_goal_selector(goalselector, options,branchbound):
"""Test with a given goal selector
in:
goalselector: as in Scyther docs.
options: options record (formatted as in optparse module)
out:
(attacks,bounds,proofs,claims,np,states)
attacks: number of failed claims
bounds: number of bounded proofs
proofs: number of complete proofs
np: number of protocols tested
states: total number of states explored.
"""
import protocollist
2006-02-23 16:10:52 +00:00
global hurry
2006-02-28 15:06:21 +00:00
scythertest.add_extra_parameters("--count-states --heuristic=" + str(goalselector))
result = str(goalselector)
2006-03-16 13:58:45 +00:00
# Selection of protocols
##plist = protocollist.from_literature()
##plist = protocollist.from_literature_no_problems()
plist = protocollist.from_all()
np = len(plist)
attacks = 0
bounds = 0
proofs = 0
claims = 0
states = 0
2006-02-23 16:10:52 +00:00
timeouts = 0
2006-02-28 15:06:21 +00:00
undecidedprotocols = []
for p in plist:
(status,scout) = scythertest.default_test([p], \
int(options.match), \
int(options.bounds))
(ra,rb,rp,nc,st,to) = parse(scout)
claims += nc
states += st
timeouts += to
attacks += ra
bounds += rb
proofs += rp
2006-02-28 15:06:21 +00:00
# is something undecided for this protocol?
if (rb > 0) or (to > 0):
undecidedprotocols += [p]
2006-02-23 16:10:52 +00:00
if hurry and (bounds * states) > branchbound:
2006-02-23 09:39:02 +00:00
return (-1,0,0,0,0,0)
2006-02-28 15:06:21 +00:00
return (attacks,bounds,proofs,claims,np,states,timeouts,undecidedprotocols)
2005-03-11 20:31:24 +00:00
# Max
class maxor:
"""Class for a dynamic maximum determination and corresponding formatting
"""
def __init__(self,dir=0,mymin=9999999999, mymax=-9999999999):
"""Init
in:
dir: bit 0 is set : notify of increase
bit 1 is set : notify of decrease
mymin: initial minimum
mymax: initial maximum
"""
self.dir = dir
self.min = mymin
self.max = mymax
2006-02-23 09:39:02 +00:00
if dir & 1:
self.data = mymax
else:
self.data = mymin
2006-02-23 09:39:02 +00:00
def get(self):
return self.data
def reg(self,d):
"""Store a new data element
in:
element to be stored
out:
formatted element, plus increase/decrease
notifications according to initial settings.
"""
2006-02-23 09:39:02 +00:00
self.data = d
res = ""
2006-02-23 09:39:02 +00:00
if self.min >= d:
if (self.dir & 2):
res = res + "-"
2006-02-23 09:39:02 +00:00
self.min = d
if self.max <= d:
if (self.dir & 1):
res = res + "+"
2006-02-23 09:39:02 +00:00
self.max = d
if res == "":
return res
else:
return "[" + res + "]"
2006-02-23 09:39:02 +00:00
# Main code
def main():
parser = OptionParser()
scythertest.default_options(parser)
(options, args) = parser.parse_args()
scythertest.process_default_options(options)
print "G-sel\tDecide\tAttack\tProof\tBound\tTOuts\tClaims\tProts\tStates\tBndTo*Sts"
print
ramax = maxor(1)
rbmax = maxor(2)
rpmax = maxor(1)
statesmax = maxor(2)
boundstatesmax = maxor(2)
2006-02-23 16:10:52 +00:00
timeoutsmax = maxor(2)
decidemax = maxor(1)
2006-02-28 15:06:21 +00:00
problems = {}
sharedproblems = []
firstproblem = True
2006-07-01 10:34:37 +01:00
for g in range(-1,512):
if (g != 0) and ((g == -1) or ((g & (64+16+8+4+1)) == 0)):
2006-02-28 15:06:21 +00:00
(ra,rb,rp,nc,np,st,timeouts,prot_undec) = test_goal_selector(g, options,
2006-02-23 09:39:02 +00:00
boundstatesmax.get())
res = str(g)
2006-02-23 09:39:02 +00:00
if ra < 0:
# Error: not well bounded
res += "\tWent over bound, stopped investigation."
else:
undecided = rb + timeouts
boundstates = undecided * undecided * st
2006-02-23 09:39:02 +00:00
def shows (res, mx, data):
return res + "\t" + str(data) + mx.reg(data)
decide = (100 * (ra + rp)) / nc
res = shows (res, decidemax, decide)
res += "%"
2006-02-23 09:39:02 +00:00
res = shows (res, ramax, ra)
res = shows (res, rpmax, rp)
res = shows (res, rbmax, rb)
2006-02-23 16:10:52 +00:00
res = shows (res, timeoutsmax, timeouts)
res = res + "\t%i" % nc
res += "\t%i" % np
2006-02-23 09:39:02 +00:00
res = shows (res, statesmax, st)
res = shows (res, boundstatesmax, boundstates)
2006-02-28 15:06:21 +00:00
problems[g] = prot_undec
if firstproblem:
firstproblem = False
sharedproblems = prot_undec
else:
nl = []
for p in sharedproblems:
if p in prot_undec:
nl += [p]
sharedproblems = nl
print res
print
print "Goal selector scan completed."
2006-02-28 15:06:21 +00:00
print
print "%i shared problem protocols:" % len(sharedproblems)
print sharedproblems
print
for g in problems.keys():
print g,
print " has %i extra problems: " % (len(problems[g]) - len(sharedproblems)),
print [ p for p in problems[g] if p not in sharedproblems ]
print
print
# Only if main stuff
if __name__ == '__main__':
main()