summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimotej Lazar <timotej.lazar@araneo.org>2015-09-17 18:01:08 +0200
committerTimotej Lazar <timotej.lazar@araneo.org>2015-09-17 18:01:08 +0200
commitdcdfe0563ab269807f66304107f9123cfc2dd37e (patch)
tree4a48ec76ce68af9c34b0a9f7d3c4338a84932b7e
parent404e1123d5ab743435b2736f94c4e2a055526c73 (diff)
Replace prolog.engine.ask_all with check_answers
When testing a program we can stop searching for new solutions after we have received a wrong one.
-rw-r--r--prolog/engine.py43
1 files changed, 20 insertions, 23 deletions
diff --git a/prolog/engine.py b/prolog/engine.py
index 50582c8..eca0826 100644
--- a/prolog/engine.py
+++ b/prolog/engine.py
@@ -6,7 +6,6 @@ import http.client
import json
from operator import itemgetter
import re
-import socket
import time
import urllib
@@ -112,46 +111,45 @@ def pretty_vars(data):
result += [strip_html(b) for b in data['residuals']]
return ',\n'.join(result) if result else 'true'
-# Run [query] in the pengine with id [engine] and return the list of answers
-# found within [timeout] seconds. If a timeout occurs before the query is done,
-# 'timed out' is appended as the last answer.
-def ask_all(engine, query, timeout=10):
- # Returns a tuple ((bindings, constraints), error, more?) for one answer.
+# Run [query] in pengine with ID [engine] and check whether all solutions
+# specified by [answers] (a list of binding dictionaries) are returned. This
+# function succeeds if [query] finds each solution in [answers] at least once
+# within [timeout] seconds, and fails when it finds any other solution.
+def check_answers(engine, query, answers, timeout=10):
+ seen = []
start = time.monotonic()
- answers, messages = [], []
try:
# Run the query.
reply, output = ask(engine, query, timeout)
- messages += output
- if 'error' in map(itemgetter(0), output):
- return answers, messages
answer, error, more = process_answer(reply)
if answer:
- answers.append(answer)
- if error:
- messages.append(error)
+ bindings, constraints = answer
+ if bindings not in answers:
+ return False
+ if bindings not in seen:
+ seen.append(bindings)
# Continue while there are more potential answers and time remaining.
while more:
real_timeout = timeout - (time.monotonic()-start)
if real_timeout <= 0:
- raise socket.timeout()
+ break
reply, output = next(engine, timeout=real_timeout)
- messages += output
answer, error, more = process_answer(reply)
if answer:
- answers.append(answer)
- if error:
- messages.append(error)
- except socket.timeout as ex:
- answers.append('timed out')
- return answers, messages
+ bindings, constraints = answer
+ if bindings not in answers:
+ return False
+ if bindings not in seen:
+ seen.append(bindings)
+ except:
+ pass
+ return len(seen) == len(answers)
# Run [query] in the pengine with id [engine] and return the first answer only
# found within [timeout] seconds.
# used for quick hint debugging by Sasha
def ask_one(engine, query, timeout=1):
- # quicker than ask_all as there could be many hint-triggering tests
# Returns either an error message, true, false, timeout (see below), or bindings
# Timeout is "returned" as an unhandled exception -- deliberately so
@@ -175,7 +173,6 @@ def ask_one(engine, query, timeout=1):
return 'false'
def ask_truth(engine, query, timeout=1):
- # quicker than ask_all as there could be many hint-triggering tests
# Returns either True or False
# (Runtime) error is False!
# Timeout is an unhandled exception -- deliberately so