Commit ·
3ef0762
1
Parent(s): 2106e26
minimal circuit.
Browse files
app.py
CHANGED
|
@@ -1,11 +1,12 @@
|
|
| 1 |
import os
|
| 2 |
import glob
|
| 3 |
from pathlib import Path
|
| 4 |
-
import traceback
|
| 5 |
|
| 6 |
import gradio as gr
|
| 7 |
import jpype
|
| 8 |
import jpype.imports
|
|
|
|
|
|
|
| 9 |
from jpype import JClass, getDefaultJVMPath
|
| 10 |
|
| 11 |
def _find_psl_jars() -> list[str]:
|
|
@@ -20,7 +21,6 @@ def _find_psl_jars() -> list[str]:
|
|
| 20 |
# 2) Local ./jars
|
| 21 |
this_dir = Path(__file__).resolve().parent
|
| 22 |
jars_dir = f"{this_dir}/.jars"
|
| 23 |
-
print(f"Jars dir is {jars_dir}")
|
| 24 |
jars.extend(glob.glob(f"{jars_dir}/*.jar"))
|
| 25 |
|
| 26 |
# Deduplicate while preserving order
|
|
@@ -171,30 +171,43 @@ def _pred_name(lit: str) -> str:
|
|
| 171 |
def _is_negated(lit: str) -> bool:
|
| 172 |
return lit.strip().startswith('!')
|
| 173 |
|
| 174 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
| 175 |
g = Digraph(name="CircuitMinimality", format="png", engine="dot")
|
| 176 |
g.attr(rankdir="LR", fontname="Helvetica")
|
| 177 |
g.node_attr.update(shape="box", style="rounded,filled", fillcolor="#f8f8f8", fontname="Helvetica")
|
| 178 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
# Nodes
|
| 180 |
preds = set()
|
| 181 |
for r in rules:
|
| 182 |
-
preds.update(
|
| 183 |
for p in sorted(preds):
|
| 184 |
g.node(p)
|
| 185 |
|
| 186 |
# Edges
|
| 187 |
for r in rules:
|
| 188 |
head_lit = r["head"]
|
| 189 |
-
head_pred =
|
| 190 |
-
neg_head =
|
| 191 |
color = "#2ca02c" if not neg_head else "#d62728"
|
| 192 |
style = "solid" if not neg_head else "dashed"
|
| 193 |
label = f"{r['name']} ({'HARD' if r.get('hard', False) else r.get('weight', '')})".strip()
|
| 194 |
for b in r["body"]:
|
| 195 |
-
g.edge(
|
| 196 |
|
| 197 |
-
|
|
|
|
|
|
|
|
|
|
| 198 |
|
| 199 |
def _rules_commentary_md(rules=RULES) -> str:
|
| 200 |
lines = ["### Rule Commentary", ""]
|
|
@@ -227,14 +240,13 @@ add_rules(model, RULES)
|
|
| 227 |
|
| 228 |
# 3) Build commentary and graph image
|
| 229 |
COMMENTARY_MD = _rules_commentary_md(RULES)
|
| 230 |
-
|
| 231 |
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
gr.Markdown("## PSL Minimal-Circuit • Overview")
|
| 235 |
gr.Markdown(f"**JVM status:**\n\n{JVM_STATUS}")
|
| 236 |
gr.Markdown(COMMENTARY_MD)
|
| 237 |
-
gr.Image(value=
|
| 238 |
|
| 239 |
if __name__ == "__main__":
|
| 240 |
demo.launch()
|
|
|
|
| 1 |
import os
|
| 2 |
import glob
|
| 3 |
from pathlib import Path
|
|
|
|
| 4 |
|
| 5 |
import gradio as gr
|
| 6 |
import jpype
|
| 7 |
import jpype.imports
|
| 8 |
+
|
| 9 |
+
from graphviz import Digraph
|
| 10 |
from jpype import JClass, getDefaultJVMPath
|
| 11 |
|
| 12 |
def _find_psl_jars() -> list[str]:
|
|
|
|
| 21 |
# 2) Local ./jars
|
| 22 |
this_dir = Path(__file__).resolve().parent
|
| 23 |
jars_dir = f"{this_dir}/.jars"
|
|
|
|
| 24 |
jars.extend(glob.glob(f"{jars_dir}/*.jar"))
|
| 25 |
|
| 26 |
# Deduplicate while preserving order
|
|
|
|
| 171 |
def _is_negated(lit: str) -> bool:
|
| 172 |
return lit.strip().startswith('!')
|
| 173 |
|
| 174 |
+
def rules_to_graphviz_file(rules=RULES, basename: str = "rules_graph") -> str:
|
| 175 |
+
"""
|
| 176 |
+
Render Graphviz to a PNG on disk and return the filepath.
|
| 177 |
+
Produces 'basename.png' next to your app.
|
| 178 |
+
"""
|
| 179 |
g = Digraph(name="CircuitMinimality", format="png", engine="dot")
|
| 180 |
g.attr(rankdir="LR", fontname="Helvetica")
|
| 181 |
g.node_attr.update(shape="box", style="rounded,filled", fillcolor="#f8f8f8", fontname="Helvetica")
|
| 182 |
|
| 183 |
+
def pred_name(lit: str) -> str:
|
| 184 |
+
return lit.lstrip('!').split('(')[0].strip()
|
| 185 |
+
|
| 186 |
+
def is_negated(lit: str) -> bool:
|
| 187 |
+
return lit.strip().startswith('!')
|
| 188 |
+
|
| 189 |
# Nodes
|
| 190 |
preds = set()
|
| 191 |
for r in rules:
|
| 192 |
+
preds.update(pred_name(x) for x in (r["body"] + [r["head"]]))
|
| 193 |
for p in sorted(preds):
|
| 194 |
g.node(p)
|
| 195 |
|
| 196 |
# Edges
|
| 197 |
for r in rules:
|
| 198 |
head_lit = r["head"]
|
| 199 |
+
head_pred = pred_name(head_lit)
|
| 200 |
+
neg_head = is_negated(head_lit)
|
| 201 |
color = "#2ca02c" if not neg_head else "#d62728"
|
| 202 |
style = "solid" if not neg_head else "dashed"
|
| 203 |
label = f"{r['name']} ({'HARD' if r.get('hard', False) else r.get('weight', '')})".strip()
|
| 204 |
for b in r["body"]:
|
| 205 |
+
g.edge(pred_name(b), head_pred, color=color, fontcolor=color, style=style, penwidth="2", label=label)
|
| 206 |
|
| 207 |
+
# Render to file: returns full path without extension; add '.png'
|
| 208 |
+
out = g.render(filename=basename, cleanup=True) # writes basename.png
|
| 209 |
+
png_path = out if out.endswith(".png") else f"{out}.png"
|
| 210 |
+
return png_path
|
| 211 |
|
| 212 |
def _rules_commentary_md(rules=RULES) -> str:
|
| 213 |
lines = ["### Rule Commentary", ""]
|
|
|
|
| 240 |
|
| 241 |
# 3) Build commentary and graph image
|
| 242 |
COMMENTARY_MD = _rules_commentary_md(RULES)
|
| 243 |
+
GRAPH_PATH = rules_to_graphviz_file(RULES, basename="rules_graph")
|
| 244 |
|
| 245 |
+
with gr.Blocks(title="PSL Minimal-Circuit Rules (Static)") as demo:
|
| 246 |
+
gr.Markdown("## PSL Minimal-Circuit • Static Overview")
|
|
|
|
| 247 |
gr.Markdown(f"**JVM status:**\n\n{JVM_STATUS}")
|
| 248 |
gr.Markdown(COMMENTARY_MD)
|
| 249 |
+
gr.Image(value=GRAPH_PATH, label="Rule Graph (green = positive head, red dashed = negated head)")
|
| 250 |
|
| 251 |
if __name__ == "__main__":
|
| 252 |
demo.launch()
|