Skip to content

Commit 24679f3

Browse files
Chipe1norvig
authored andcommitted
Added canvas_fol_bc_ask() (aimacode#558)
1 parent ba301e7 commit 24679f3

File tree

2 files changed

+288
-65
lines changed

2 files changed

+288
-65
lines changed

canvas.py

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from IPython.display import HTML, display
22
from utils import argmax, argmin
33
from games import TicTacToe, alphabeta_player, random_player, Fig52Extended, infinity
4+
from logic import parse_definite_clause, standardize_variables, unify, subst
45

56
_canvas = """
67
<script type="text/javascript" src="./js/canvas.js"></script>
@@ -526,3 +527,126 @@ def draw_graph(self):
526527
self.text_n(alpha, x - self.l/2, y - self.l/10)
527528
self.text_n(beta, x + self.l, y - self.l/10)
528529
self.update()
530+
531+
532+
class Canvas_fol_bc_ask(Canvas):
533+
"""fol_bc_ask() on HTML canvas
534+
"""
535+
def __init__(self, varname, kb, query, width=800, height=600, cid=None):
536+
Canvas.__init__(self, varname, width, height, cid)
537+
self.kb = kb
538+
self.query = query
539+
self.l = 1/20
540+
self.b = 3*self.l
541+
bc_out = list(self.fol_bc_ask())
542+
if len(bc_out) is 0:
543+
self.valid = False
544+
else:
545+
self.valid = True
546+
graph = bc_out[0][0][0]
547+
s = bc_out[0][1]
548+
while True:
549+
new_graph = subst(s, graph)
550+
if graph == new_graph:
551+
break
552+
graph = new_graph
553+
self.make_table(graph)
554+
self.context = None
555+
self.draw_table()
556+
557+
def fol_bc_ask(self):
558+
KB = self.kb
559+
query = self.query
560+
def fol_bc_or(KB, goal, theta):
561+
for rule in KB.fetch_rules_for_goal(goal):
562+
lhs, rhs = parse_definite_clause(standardize_variables(rule))
563+
for theta1 in fol_bc_and(KB, lhs, unify(rhs, goal, theta)):
564+
yield ([(goal, theta1[0])], theta1[1])
565+
566+
def fol_bc_and(KB, goals, theta):
567+
if theta is None:
568+
pass
569+
elif not goals:
570+
yield ([], theta)
571+
else:
572+
first, rest = goals[0], goals[1:]
573+
for theta1 in fol_bc_or(KB, subst(theta, first), theta):
574+
for theta2 in fol_bc_and(KB, rest, theta1[1]):
575+
yield (theta1[0] + theta2[0], theta2[1])
576+
577+
return fol_bc_or(KB, query, {})
578+
579+
def make_table(self, graph):
580+
table = []
581+
pos = {}
582+
links = set()
583+
edges = set()
584+
585+
def dfs(node, depth):
586+
if len(table) <= depth:
587+
table.append([])
588+
pos = len(table[depth])
589+
table[depth].append(node[0])
590+
for child in node[1]:
591+
child_id = dfs(child, depth + 1)
592+
links.add(((depth, pos), child_id))
593+
return (depth, pos)
594+
595+
dfs(graph, 0)
596+
y_off = 0.85/len(table)
597+
for i, row in enumerate(table):
598+
x_off = 0.95/len(row)
599+
for j, node in enumerate(row):
600+
pos[(i, j)] = (0.025 + j*x_off + (x_off - self.b)/2, 0.025 + i*y_off + (y_off - self.l)/2)
601+
for p, c in links:
602+
x1, y1 = pos[p]
603+
x2, y2 = pos[c]
604+
edges.add((x1 + self.b/2, y1 + self.l, x2 + self.b/2, y2))
605+
606+
self.table = table
607+
self.pos = pos
608+
self.edges = edges
609+
610+
def mouse_click(self, x, y):
611+
x, y = x/self.width, y/self.height
612+
for node in self.pos:
613+
xs, ys = self.pos[node]
614+
xe, ye = xs + self.b, ys + self.l
615+
if xs <= x <= xe and ys <= y <= ye:
616+
self.context = node
617+
break
618+
self.draw_table()
619+
620+
def draw_table(self):
621+
self.clear()
622+
self.strokeWidth(3)
623+
self.stroke(0, 0, 0)
624+
self.font("12px Arial")
625+
if self.valid:
626+
# draw nodes
627+
for i, j in self.pos:
628+
x, y = self.pos[(i, j)]
629+
self.fill(200, 200, 200)
630+
self.rect_n(x, y, self.b, self.l)
631+
self.line_n(x, y, x + self.b, y)
632+
self.line_n(x, y, x, y + self.l)
633+
self.line_n(x + self.b, y, x + self.b, y + self.l)
634+
self.line_n(x, y + self.l, x + self.b, y + self.l)
635+
self.fill(0, 0, 0)
636+
self.text_n(self.table[i][j], x + 0.01, y + self.l - 0.01)
637+
#draw edges
638+
for x1, y1, x2, y2 in self.edges:
639+
self.line_n(x1, y1, x2, y2)
640+
else:
641+
self.fill(255, 0, 0)
642+
self.rect_n(0, 0, 1, 1)
643+
# text area
644+
self.fill(255, 255, 255)
645+
self.rect_n(0, 0.9, 1, 0.1)
646+
self.strokeWidth(5)
647+
self.stroke(0, 0, 0)
648+
self.line_n(0, 0.9, 1, 0.9)
649+
self.font("22px Arial")
650+
self.fill(0, 0, 0)
651+
self.text_n(self.table[self.context[0]][self.context[1]] if self.context else "Click for text", 0.025, 0.975)
652+
self.update()

0 commit comments

Comments
 (0)