Commit 241ed158 authored by Paul Maier's avatar Paul Maier
Browse files

toolbarTest.py is a simple python script running some tests on the BEDA...

toolbarTest.py is a simple python script running some tests on the BEDA algorithm implemented in toolbar. result.py contains some helper functions and classes used by toolbarTest.py.
parents
#-----------------------------------------------------------------------------
# Purpose: Provides classes and functions for parsing algorithm output and
# accumulating them in a result object. Various helper classes are
# also provided.
#
# Author: Paul Maier
#
# Created: 05.03.2008
# RCS-ID: $Id$
# SVN-ID: $Id$
# Copyright:
# Licence: <your licence>
#-----------------------------------------------------------------------------
"""
Provides classes and functions for parsing algorithm output and
accumulating them in a result object. Various helper classes are
also provided.
"""
import time
class TimeSpanSecond:
"""
Class representing time spans in seconds. This is simply to make sure a
time delta is given in seconds and nothing else.
"""
def __init__(self):
self.__seconds = 0.0
self.__start = time.time()
def getSeconds(self):
return self.__seconds
seconds = property(getSeconds, None, None,
"time elapsed since creation of the object or"
" last call to self.time()")
def time(self):
"""
Set this TimeSpanSecond to the time span
elapsed since the last call to method time() or the creation of this
TimeSpanSecond.
"""
stop = time.time()
self.seconds = stop - self.__start
self.__start = stop
class TimeSpanSecondFixed(TimeSpanSecond):
"""
This class is like TimeSpanSecond with the only difference that it represents
a fixed duration. Calls to time() will be ignored.
"""
def __init__(self, duration = 0.0):
self._TimeSpanSecond__seconds = duration
self.__start = 0.0
def time(self):
pass
class Result:
"""
Result instances store a result for a single program run, e.g. like
/path/to/program/toolbar -v -C -i -w15 16wqueens.wcsp
"""
def __init__(self, duration = TimeSpanSecond(),
durSearch = TimeSpanSecond(),
durInference = TimeSpanSecond(),
spaceQSize = 1, spaceBytes = 0, spaceSearch = 0,
spaceInference = 0, spaceNTuples = 1, MBEmsgSizes = None,
BEDAmsgSizes = None, BEmsgSizes = None, solution = None):
assert isinstance(duration, TimeSpanSecond)
assert isinstance(durSearch, TimeSpanSecond)
assert isinstance(durInference, TimeSpanSecond)
self.duration = duration
self.durSearch = durSearch
self.durInference = durInference
self.spaceQSize = spaceQSize
self.spaceBytes = spaceBytes
self.spaceSearch = spaceSearch
self.spaceInference = spaceInference
self.spaceNTuples = spaceNTuples
self.MBEmsgSizes = MBEmsgSizes
self.BEDAmsgSizes = BEDAmsgSizes
self.BEmsgSizes = BEmsgSizes
self.solution = solution
class OutputParser:
"""
Instances of this class or its subclasses are parsers for algorithm outputs.
E.G. you have some algorithm (might be encapsulated in a cmd line tool)
which produces some kind of output which you want to analyse. Then you
simply pass a list with parseElement*(output, result) functions to the
constructor, each of them parsing single elements from the output.
You may also subclass this class and override parse() to account for specific
output of parsing requirements for your algorithm.
"""
def __init__(self, filePath, parseElements):
self.__result = None
self.output = None
self.__filePath = filePath
self.__parseElements = parseElements
def getResult(self):
if self.__result == None:
self.parse()
return self.__result
result = property(getResult, None,
"The parse result is stored here. If nothing has been "
"parsed yet the parser will automatically try to parse "
"the file which was given to the constructor.")
def parse(self, tmpFilePath = None):
"""Parse the given file (or, if None, the one presented to the
constructor of this parser) and store the results in a Result object.
Also, the result object will be returned.
"""
if tmpFilePath != None:
self.__filePath = tmpFilePath
self.output = ""
tmpFile = file(self.__filePath)
try:
self.output = tmpFile.read()
finally:
tmpFile.close()
# first check whether the toolbar run was ok or hit the search queue size
# bound
if self.output.find("Queue hit the hard size bound") != -1:
print "Queue hit the hard size bound"
result = Result(spaceQSize = -1,
durInference = TimeSpanSecondFixed(-1.0),
durSearch = TimeSpanSecondFixed(-1.0))
return result
result = Result()
self.__result = result
for parseElement in self.__parseElements:
parseElement(self.output, self.__result)
return result
def stringToIntList(s):
"""
Convert a string of space separated integers to a list of ints.
"""
return map(int, s.strip().split(" "))
def parseElementTimes(output, result):
start = output.index("inference:") + len("inference:")
end = output.index("sec", start)
inferenceTime = float(output[start:end])
inferenceTime = TimeSpanSecondFixed(float(output[start:end]))
start = output.index("search:") + len("search:")
end = output.index("sec", start)
searchTime = TimeSpanSecondFixed(float(output[start:end]))
result.durInference = inferenceTime
result.durSearch = searchTime
return result
def parseElementAStarQueueSize(output, result):
start = output.index("queue size:") + len("queue size:")
end = output.index("elements", start)
queueSize = int(output[start:end])
result.spaceQSize = queueSize
return result
def parseElementToolbarSolution(output, result):
variables = []
solutionStart = output.find("solution:\n")
start = output.find("variable",solutionStart)
end = output.find("\n", start)
while start != -1:
start += len("variable")
var, val = map(int, output[start:end].strip().split(":"))
variables.append((var, val))
start = output.find("variable", end)
end = output.find("\n", start)
variables.sort()
result.solution = [val for _, val in variables]
return result
def parseElementToolbarMBE(output, result):
"""The message sizes as output by MBE in toolbar are read into an array and
stored in the result object.
"""
start = output.index("accum. mini-message sizes:") + \
len("accum. mini-message sizes:")
end = output.index("\n", start)
result.MBEmsgSizes = stringToIntList(output[start:end])
return result
def parseElementToolbarBEDA(output, result):
"""Parse the message sizes as output by BEDA in toolbar and read them into
an array.
"""
start = output.index("BE message sizes:") + \
len("BE message sizes:")
end = output.index("\n", start)
result.BEmsgSizes = stringToIntList(output[start:end])
start = output.index("abstract message sizes:") + \
len("abstract message sizes:")
end = output.index("\n", start)
result.BEDAmsgSizes = stringToIntList(output[start:end])
return result
class OutputParserToolbarSolution(OutputParser):
"""
Output parser which only parses the solution output either by MBE or BEDA.
"""
def __init__(self, filePath):
OutputParser.__init__(self, filePath, [parseElementToolbarSolution])
class OutputParserToolbarMBE(OutputParser):
"""
Output parser for the MBE algorithm implemented in toolbar.
"""
def __init__(self, filePath):
OutputParser.__init__(self, filePath, [parseElementTimes,
parseElementAStarQueueSize,
parseElementToolbarMBE])
class OutputParserToolbarBEDA(OutputParser):
"""
Output parser for the BEDA algorithm implemented in toolbar.
"""
def __init__(self, filePath):
OutputParser.__init__(self, filePath, [parseElementTimes,
parseElementAStarQueueSize,
parseElementToolbarBEDA])
#!/usr/bin/python
#-----------------------------------------------------------------------------
# Purpose: Run several tests on toolbar, error checking BEDA.
#
# Author: Paul Maier
#
# Created: 27.03.2008
# RCS-ID: $Id$
# SVN-ID: $Id$
# Copyright:
# Licence: <your licence>
#-----------------------------------------------------------------------------
"""Run several tests on toolbar, error checking BEDA.
"""
from result import *
import unittest, os
TOOLBAR_EXE = "../toolbar-mulcyber/toolbar"
TEST_FILES = ["../benchs/academics/8wqueens.wcsp",
"../benchs/academics/16wqueens.wcsp",
"../benchs/academics/zebra.wcsp"]
# reference solutions computed with toulbar2, option s for computing all solutions
# or computed with toolbar -C -v
CORRECTNESS_TEST_FILES = [
("../benchs/academics/4wqueens.wcsp", [[2, 0, 3, 1]]),
("../benchs/academics/8wqueens.wcsp", [[1, 4, 6, 3, 0, 7, 5, 2]]),
("../benchs/academics/zebra.wcsp", [[0, 2, 4, 3, 1, 0, 4, 2, 1, 3, 0, 2, 1, 3, 4, 4,
1, 0, 3, 2, 3, 2, 4, 0, 1]]),
("../benchs/academics/16wqueens.wcsp", [[3, 12, 8, 4, 2, 15, 5, 14, 10, 0, 6, 1, 7, 13, 11, 9],
[3, 12, 8, 4, 2, 15, 5, 11, 13, 0, 6, 1, 7, 10, 14, 9]]),
("../benchs/academics/langford_2_4.wcsp", [[4, 0, 1, 2, 6, 3, 5, 7],
[1, 4, 2, 0, 3, 7, 6, 5]]),
("../benchs/academics/donald.wcsp", [[4, 2, 6, 4, 8, 0, 9, 6, 3, 0, 1, 1, 0, 1, 1]])
]
TMP_OUTPUT = "tmpOut.txt"
class ToolbarTest(unittest.TestCase):
def setUp(self):
unittest.TestCase.setUp(self)
def tearDown(self):
unittest.TestCase.tearDown(self)
def testDomainSizeReduction(self):
for testFile in TEST_FILES:
os.system(TOOLBAR_EXE + " -C -v -j -M256 " + testFile + " > "+
TMP_OUTPUT)
parser = OutputParser(TMP_OUTPUT, [parseElementToolbarBEDA])
result = parser.parse()
for msgSize, abstractMsgSize in zip(result.BEmsgSizes,
result.BEDAmsgSizes):
self.assert_(msgSize >= abstractMsgSize)
def testCoreToolbarTests(self):
"""
Test cases embedded in toolbar.
"""
print
print "----------------------------------------------------------------"
print "toolbar integrated tests: >>>"
os.system(TOOLBAR_EXE + " --test")
print "toolbar integrated tests end <<<"
print "----------------------------------------------------------------"
def testBEDACorrectness(self):
for testFile, optima in CORRECTNESS_TEST_FILES:
print "testing problem " + testFile + " ... "
os.system(TOOLBAR_EXE + " -C -v -j -M256 " + testFile + " > " +
TMP_OUTPUT)
parser = OutputParserToolbarSolution(TMP_OUTPUT)
result = parser.parse()
self.assert_(result.solution in optima)
if __name__ == '__main__':
unittest.main()
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment