导入数学;导入操作系统;进口关税;导入子流程;进口系统;进口再保险;输入随机性;workingDirectory=os.path.jjoin(“.”,“xorTestTemp”);“”“创建临时文件的目录”“”xorTestPredicate=“xorTestPredicate”;“”“用于生成约束的谓词”“”referenceProgramPath=os.path.jjoin(workingDirectory,“reference.lp”);“”“引用程序文件的路径”“”programUnderTestPath=os.path.jjoin(workingDirectory,“test.lp”);“”“测试文件下程序的路径”“”programToSolvePath=os.path.jjoin(workingDirectory,“solve.lp”);“”“要检查SAT的程序的路径”“”settingArgs=[];“”“应传递给钩子的参数”“”settingArgsGringo=[];“”“应该传递给外国佬的参数”“”设置C=1;“”“一次可选择的最大答案集数”“”设置N=1;“”“要计算的答案集数”“”设置Q=0.5;“”“一个原子被包含在异或约束中的概率;参数解析完成后乘以100设置S=-1;“”“约束数”“”设置T=0;“”“解决时间限制”“”settingReferenceFile=“”;“”“引用程序文件的路径”“”settingTestFile=“”;“”“测试程序文件的路径”“”settingCommonFile=“”;“”“公用程序文件的路径”“”settingAddShows=True;“”“指示是否添加show语句”“”xorSampleArguments=[];“”“应使用”“调用xorsample的参数”“”失败运行=[];“”“失败运行的索引和原子列表”“”原子=[];“原子列表”testCaseCounter=0;“”“当前测试用例的编号”“”repeatFailedCasesAtEnd=False;def cleanUp():“”“删除工作目录”“”shutil.rmtree(工作目录,True,无);定义用法():“”“打印用法信息。”“”打印(os.path.basename(sys.argv[0])+“[--帮助][--a=args]*[--g=gArgs]*[--c=c][--n=n][--q=q][--s=s][--t=t][--dontAddShows][--摘要]--cf=p--rf=p--tf=p”);打印(“测试答案集程序的工具”);打印(“用法:”);打印(“--help:\t显示此用法信息”);print(“--a=args:\t应传递给卡扣的参数。”);print(“--g=Gargs:\t应该传递给外国佬的参数。”);print(“--c=c:\t\t每次迭代选取的最大答案集数\n\t\t(默认值:1)”);print(“--n=n:\t\t设置一个正整数n作为要计算的答案集的数目(默认值:1)”);打印(“--q=q:\t\t将q设置为原子被包含在异或约束中的概率(0.01<=q<=0.5,默认值:0.5)”);print(“--s=s:\t\t设置一个正整数s作为约束的初始数目(默认值:log(X),其中X是接地中的原子数)”);print(“--t=t:\t\t设置扣的时间限制(以秒为单位)(仅用于xorsample)\n\t\t(默认值:0,0=无时间限制)”);print(“--dontAddShows:\t不添加#show表达式(如果提供)”);打印(“--summary:\t如果提供,则在末尾重复失败的测试用例”);打印(“--cf=p:\t\t通用asp程序的路径”);打印(“--rf=p:\t\t参考asp程序的路径”);print(“--tf=p:\t\t被测asp程序的路径”);系统退出()定义parseArgs():“”“尝试分析程序启动时使用的参数”“”cSet=假;nSet=假;qSet=False;sSet=False;t设置=假;addShowsSet=False;cf设置=假;rfSet=假;tfSet=假;summarySet=False;全局settingArgs;全局设置ArgsGringo;全球环境C;全局设置N;全局设置Q;全局设置S;全局设置T;全局设置AddShows;全局设置ReferenceFile;全局设置测试文件;全局设置CommonFile;全局repeatFailedCasesAtEnd;全局xorTestPredicate;全局xorSampleArguments;对于sys.argv[1:]中的arg:#跳过程序名如果arg==“--help”:usage();elif arg[0:4]==“--a=”:settingArgs.append(参数[4:]);xorSampleArguments=xorSampleArguments+[arg];elif arg[0:4]==“--g=”:settingArgsGringo.append(参数[4:]);xorSampleArguments=xorSampleArguments+[arg];elif arg[0:4]==“--c=”:如果cSet:usage();cSet=真;settingC=tryParsePositiveInteger(参数[4:]);xorSampleArguments=xorSampleArguments+[arg];elif参数[0:4]==“--n=”:如果设置为:usage();nSet=真;settingN=tryParsePositiveInteger(arg[4:]);elif参数[0:4]==“--q=”:如果qSet:usage();qSet=真;settingQ=tryPraseParameterQ(参数[4:]);xorSampleArguments=xorSampleArguments+[arg];elif arg[0:4]==“--s=”:如果设置:usage();sSet=真;settingS=tryParsePositiveInteger(arg[4:]);xorSampleArguments=xorSampleArguments+[arg];elif参数[0:4]==“--t=”:如果t设置:usage();t设置=真;settingT=tryParseIntegrer(参数[4:]);xorSampleArguments=xorSampleArguments+[arg];elif arg[0:14]==“--dontAddShows”:如果addShowsSet:usage();addShowsSet=True;settingAddShows=False;xorSampleArguments=xorSampleArguments+[arg];elif arg[0:9]==“--摘要”:如果summarySet:usage();summarySet=True;repeatFailedCasesAtEnd=真;elif arg[0:5]==“--cf=”:如果cfSet:使用();cf设置=真;settingCommonFile=arg[5:]elif arg[0:5]==“--rf=”:如果rfSet:usage();rfSet=真;settingReferenceFile=arg[5:]elif参数[0:5]==“--tf=”:如果tfSet:usage();tfSet=真;settingTestFile=参数[5:]其他:使用();if(非rfSet)或(非tfSet)或者(非cfSet):usage();如果不是os.path.isfile(settingCommonFile):打印(“找不到通用文件”);sys.exit();如果不是os.path.isfile(settingReferenceFile):打印(“未找到参考文件”);sys.exit();如果不是os.path.isfile(settingTestFile):打印(“未找到测试文件”);sys.exit();“”“生成编码文件并确定谓词名称”“”xorTestPredicateToUse=xorTestPredicate;completeEncoding=“”;如果cfSet:completeEncoding=completeEncode+concatFiles([settingCommonFile,settingReferenceFile],referenceProgramPath);completeEncoding=completeEncode+concatFiles([settingCommonFile,settingTestFile],programUnderTestPath);其他:completeEncoding=completeEncode+concatFiles([settingReferenceFile],referenceProgramPath);completeEncoding=completeEncode+concatFiles([settingTestFile],programUnderTestPath);谓词索引=1;而xorTestPredicateToUse在completeEncoding中:xorTestPredicateToUse=xorTestRedicate+str(谓词索引);谓词索引=谓词索引+1;xorTestPredicate=xorTestPredicateToUse;def concatFile(inputFiles,outputFile,text=“”):“”“将inputFiles中的所有文件连接到outputFile,并附加给定的可选文本并返回内容:param inputFiles:输入文件列表:param outputFile:输出文件的路径:param text:要追加的文本"""returnValue=“”;打开(outputFile,'w')作为oFile:对于inputFiles中的fname:以open(fname)作为infee:readContent=infile.read();o文件.write(readContent);returnValue=returnValue+readContent;如果不是text==“”:o文件.写入(os.linesep+文本);returnValue=os.linesep+text;return returnValue;定义tryParsePositiveInteger:“”“尝试将s转换为正整数,如果不可能,则调用用法:param s:应分析的字符串"""r=tryParseIntegrer(s);如果r==0:usage();返回r;def-tryParseIntegrer(s):“”“尝试将s转换为整数,如果不可能,则调用用法:param s:应分析的字符串"""如果不是s.isdigit():usage();r=整数;如果r<0:usage();返回r;定义tryPraseParameterQ:“”“尝试将s转换为介于0.01(含0.01)和0.5(含0.5)之间的实数:param s:应分析的字符串"""尝试:fs=浮点数;如果fs<0.01或fs>0.5或math.isnan(fs):usage();返回fs;除ValueError:usage();def callGringo(参数):“”“使用给定参数调用gringo并返回其输出:param parameters:应传递给gringo的参数""" 如果len(settingArgsGringo)>0:流程=子流程。Popen([“gringo”]+settingArgsGringo+参数,stdout=subprocess.PIPE,stderr=subpprocess.PIPE);其他:流程=子流程。Popen([“gringo”]+参数,stdout=subprocess.PIPE,stderr=subpprocess.PIPEL);output,unused_err=process.communicate();return str(输出,“utf-8”);def getAtom(程序文件):“”“尝试读取所提供文件的固定版本的原子”“”regexAtom=重新编译('(?<=[0-9]).*',re.I+re.S)#使用gringo将程序接地接地=callGringo([programFile]).split(os.linesep);#解析接地原子全球原子;atomsBlockStarted=假对于接地线路:如果不是atomsBlockStarted:#跳过包含原子的块之前的所有内容如果行==“0”:atomsBlockStarted=True;继续;如果(atomsBlockStarted==True):如果行==“0”:#到达原子块的末尾断裂;atoms.append(regexAtom.findall(行)[0])定义doTest(测试用例):“”“尝试使用gringo和clasp检查测试文件和参考文件的给定AS是否为SAT。:param testCase测试用例""" testCaseAtoms=testCase.split(“”);testCaseString=“”;对于testCaseAtoms中的testCase原子:如果len(testCaseAtom)>0:testCaseString=测试用例字符串+测试用例原子+“.\n”;concatFile([referenceProgramPath],programToSolvePath,“\n”+testCaseString);结果=getAS(programToSolvePath);如果结果为“无”:return None;answerSet=结果[1];if(结果[0]):#程序一致#创建一个规则,该规则包含头部的xorTestOKAtom和身体中所有原子的连接okRule=xorTestPredicate+“:-”;answerSetAtoms=answerSet.split(“”);对于原子中的原子:如果不是(answerSetAtom中的atom):okRule=okRule+“not”;okRule=okRule+atom+“,”;okRule=okRule[:-1]+“.”;#创建约束containtRule=“:-not”+xorTestPredicate+“.”;#使用测试实现、xorsample中的答案集和公共文件(如果提供)创建一个文件,并检查此程序是否为sat。concatFiles([programUnderTestPath],programToSolvePath,“\n”+testCaseString+“\n”+okRule+os.linesep+containtRule);else:#程序不一致concatFiles([programUnderTestPath],programToSolvePath,“\n”+testCaseString);solverResults=callSolver(1,programToSolvePath);如果解算器结果中的“时间限制:1”:return None;#确定程序是否可满足如果solverResults中的“\nSATISFIABLE\n”:return(结果[0],结果[0]);其他:如果不是(solverResults中的“UNNSATISFIABLE”):引发异常(“意外的解算器结果:”+solverResults);其他:return(非结果[0],结果[0]);def callSolver(n,程序文件):“”“使用给定参数调用gringo和clasp并返回其输出:param programFile:应求解的程序文件:param n:想要的答案集数""" gringoArguments=[“gringo”];如果len(settingArgsGringo)>0:gringoArguments=gringoParguments+settingArgsGringo;gringoArguments=gringoArguments+[programFile];capseArguments=[“capse”];如果len(settingArgs)>0:capseArguments=capseArugments+settingArgs;capseArguments=capseArugments+[“--models=”+str(n)]+[“--时间限制=”+stra(settingT)];gringoProcess=子流程。Popen(gringoArguments,stdout=subprocess.PIPE,stderr=subpprocess.PIPE);clipProcess=子流程。Popen(capseArguments,stdin=gringoProcess.stdout,stdout=subprocess.PIPE,stderr=subpprocess.PIPE)capseOutput,capseUnused_err=capseProcess.communicate();returnValue=str(扣输出,“utf-8”);gringoProcess.stdout.close();return returnValue;def callXorSample(n,程序):“”“调用xorsample生成应答集”“”xorSampleProcess=子流程。Popen([“python3.4”]+[“xorsample.py”]+xorSampleArguments+[“--n=”+str(n)]+[程序],标准输出=子进程。PIPE,stderr=子进程。管道);如果FirstLine=True;returnValue=[];while True:#从xorsample逐行读取line=xorSampleProcess.stdout.readline();line=str(行,“utf-8”);if行!=“”:#EOF?if if第一行:#检查该行是否为“Answer set:n”,如果是,跳过如果FirstLine=False;如果不是,则从第行开始(“答案集”):引发异常(“使用xorsample:”+line无法找到答案集);其他:如果FirstLine=True;returnValue=returnValue+[str(行[:-1])];其他:断裂;return returnValue;def getAS(程序文件):solverOutput=callSolver(1,programFile);#确定程序是否可满足如果解算器输出中的“时间限制:1”:return无;solverOutput中的isSat=“\nSATISFIABLE\n”如果(不是Sat):如果不是(solverOutput中的“UNNSATISFIABLE”):引发异常(“找不到答案集:”+solverOutput);其他:return(False,“”);answerSetRegex=重新编译(r“(?<=答案:1\n)(.*)”,重新I);return(True,answerSetRegex.findall(solverOutput)[0]);def getRandomAS(n,程序文件):return callXorSample(n,programFile);如果__name__==“__main__”:尝试:如果os.path.isdir(工作目录):打印(“工作目录”+工作目录+“已存在。正在中止…”);sys.exit();其他:os.makedirs(工作目录);例外情况e除外:打印(“准备工作目录失败”+工作目录+“:”+e.message);尝试:parseArgs();getAtom(程序UnderTestPath);testcases=getRandomAS(settingN,settingCommonFile);testCaseCounter=0;consistentFailedCounter=0;不一致的失败计数器=0;consistentPassedCounter=0;不一致的PassedCounter=0;不确定性计数器=0;对于测试用例中的测试用例:testCaseCounter=测试用例计数器+1;testResult=doTest(测试用例);如果testResult为None:打印(“测试用例”+str(testCaseCounter)+“:INDEFINITE”);不确定计数器=不确定计数器+1;其他:如果testResult[0]:如果testResult[1]:打印(“测试用例”+str(testCaseCounter)+“:通过(一致)”);consistentPassedCounter=consistent通过计数器+1;其他:打印(“测试用例”+str(testCaseCounter)+“:通过(不一致)”);不一致tPassedCounter=不一致tPassedCounter+1;其他:如果testResult[1]:打印(“测试用例”+str(testCaseCounter)+“:失败(一致)”);consistentFailedCounter=consistent失败计数器+1;其他:打印(“测试用例”+str(testCaseCounter)+“:失败(不一致)”);inconsistentFailedCounter=不一致失败计数器+1;打印(“答案集:”+测试用例);failedRuns.append((testCaseCounter,testcase));print(“Failed testcases:”+str(len(failedRuns));print(“Failed consistent testcases:”+str(consistentFailedCounter));print(“失败的不一致测试用例:”+str(不一致的失败计数器));print(“通过一致性测试用例:”+str(consistentPassedCounter));print(“通过的不一致测试用例:”+str(不一致通过计数器));print(“不确定测试用例:”+str(不确定计数器));#打印摘要(如果提供了参数--summary)如果repeatFailedCasesAtEnd和len(failedRuns)>0:print(“以下测试用例失败:”);i=0;当i<len(失败运行)时:(runNumber,answerSet)=失败运行[i];打印(“测试用例”+str(runNumber));打印(answerSet);i=i+1;print(“Failed testcases:”+str(len(failedRuns));例外情况e除外:print(“发生意外异常:”+str(e));最后:清理()