mirror of
https://github.com/Brandon-Rozek/matmod.git
synced 2024-11-20 21:56:29 -05:00
Progress on handling custom connectives
TODO: Fix matrix numbering
This commit is contained in:
parent
e293e5ac3e
commit
17fb542bd0
1 changed files with 74 additions and 55 deletions
129
parse_magic.py
129
parse_magic.py
|
@ -4,6 +4,7 @@ Parses the Magic Ugly Data File Format
|
||||||
Assumes the base logic is R with no extra connectives
|
Assumes the base logic is R with no extra connectives
|
||||||
"""
|
"""
|
||||||
import argparse
|
import argparse
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
from typing import TextIO, List, Optional, Tuple, Set, Dict
|
from typing import TextIO, List, Optional, Tuple, Set, Dict
|
||||||
|
|
||||||
|
@ -72,7 +73,7 @@ class ModelBuilder:
|
||||||
self.mimplication: Optional[ModelFunction] = None
|
self.mimplication: Optional[ModelFunction] = None
|
||||||
self.num_necessitation: int = 0
|
self.num_necessitation: int = 0
|
||||||
self.mnecessitation: Optional[ModelFunction] = None
|
self.mnecessitation: Optional[ModelFunction] = None
|
||||||
self.custom_model_functions: List[Tuple[int, ModelFunction]]
|
self.custom_model_functions: Dict[str, ModelFunction] = {}
|
||||||
|
|
||||||
class Stage:
|
class Stage:
|
||||||
def __init__(self, name: str):
|
def __init__(self, name: str):
|
||||||
|
@ -89,10 +90,13 @@ class Stages:
|
||||||
def add(self, name: str):
|
def add(self, name: str):
|
||||||
stage = Stage(name)
|
stage = Stage(name)
|
||||||
stage.next = stage
|
stage.next = stage
|
||||||
|
|
||||||
if self.last_stage is not None:
|
if self.last_stage is not None:
|
||||||
stage.previous = self.last_stage
|
stage.previous = self.last_stage
|
||||||
self.last_stage.next = stage
|
self.last_stage.next = stage
|
||||||
else:
|
else:
|
||||||
|
# The previous of the first stage
|
||||||
|
# is the end
|
||||||
stage.previous = Stage("end")
|
stage.previous = Stage("end")
|
||||||
|
|
||||||
self.stages[name] = stage
|
self.stages[name] = stage
|
||||||
|
@ -114,9 +118,8 @@ def derive_stages(header: UglyHeader) -> Stages:
|
||||||
stages.add("implication")
|
stages.add("implication")
|
||||||
if header.necessitation:
|
if header.necessitation:
|
||||||
stages.add("necessitation")
|
stages.add("necessitation")
|
||||||
# TODO: Can't use -- as that can be a custom symbol
|
for (adicity, symbol) in header.custom_model_functions:
|
||||||
# for (acidity, symbol) in header.custom_model_functions:
|
stages.add(f"custom--{adicity}--{symbol}")
|
||||||
# stages.add(f"custom--{acidity}--{symbol}")
|
|
||||||
stages.add("process_model")
|
stages.add("process_model")
|
||||||
|
|
||||||
# After processing the model, go to the previous stage
|
# After processing the model, go to the previous stage
|
||||||
|
@ -124,7 +127,6 @@ def derive_stages(header: UglyHeader) -> Stages:
|
||||||
|
|
||||||
return stages
|
return stages
|
||||||
|
|
||||||
|
|
||||||
def parse_matrices(infile: SourceFile) -> List[Tuple[Model, Dict]]:
|
def parse_matrices(infile: SourceFile) -> List[Tuple[Model, Dict]]:
|
||||||
solutions = [] # Reset
|
solutions = [] # Reset
|
||||||
header = parse_header(infile)
|
header = parse_header(infile)
|
||||||
|
@ -160,7 +162,23 @@ def parse_matrices(infile: SourceFile) -> List[Tuple[Model, Dict]]:
|
||||||
processed = process_necessitations(infile, current_model_parts)
|
processed = process_necessitations(infile, current_model_parts)
|
||||||
stage = stage.next if processed else stage.previous
|
stage = stage.next if processed else stage.previous
|
||||||
case _:
|
case _:
|
||||||
raise NotImplementedError("Custom Connectives are not yet supported")
|
custom_stage = re.search(r"custom--(\d+)--(\S+)", stage.name)
|
||||||
|
if custom_stage is None or len(custom_stage.groups()) != 2:
|
||||||
|
raise NotImplementedError(f"Unrecognized Stage: {stage.name}")
|
||||||
|
adicity, symbol = custom_stage.groups()
|
||||||
|
adicity = int(adicity)
|
||||||
|
if adicity == 0:
|
||||||
|
# We don't need to do anything here
|
||||||
|
stage = stage.next
|
||||||
|
elif adicity == 1:
|
||||||
|
processed = process_monadic_connective(infile, symbol, current_model_parts)
|
||||||
|
stage = stage.next if processed else stage.previous
|
||||||
|
elif adicity == 2:
|
||||||
|
processed = process_dyadic_connective(infile, symbol, current_model_parts)
|
||||||
|
stage = stage.next if processed else stage.previous
|
||||||
|
else:
|
||||||
|
raise NotImplementedError("Unable to process connectives of adicity greater than 2")
|
||||||
|
|
||||||
|
|
||||||
return solutions
|
return solutions
|
||||||
|
|
||||||
|
@ -259,10 +277,25 @@ def process_necessitations(infile: SourceFile, current_model_parts: ModelBuilder
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def process_monadic_connective(infile: SourceFile, symbol: str, current_model_parts: ModelBuilder) -> bool:
|
||||||
|
mfunction = parse_single_monadic_connective(infile, symbol, current_model_parts.size)
|
||||||
|
if mfunction is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
current_model_parts.custom_model_functions[symbol] = mfunction
|
||||||
|
return True
|
||||||
|
|
||||||
|
def process_dyadic_connective(infile: SourceFile, symbol: str, current_model_parts: ModelBuilder) -> bool:
|
||||||
|
mfunction = parse_single_dyadic_connective(infile, symbol, current_model_parts.size)
|
||||||
|
if mfunction is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
current_model_parts.custom_model_functions[symbol] = mfunction
|
||||||
|
return True
|
||||||
|
|
||||||
def process_model(mp: ModelBuilder, solutions: List[Tuple[Model, Dict]]):
|
def process_model(mp: ModelBuilder, solutions: List[Tuple[Model, Dict]]):
|
||||||
"""Create Model"""
|
"""Create Model"""
|
||||||
assert mp.mimplication is not None
|
assert mp.mimplication is not None
|
||||||
assert len(mp.carrier_set) > 0
|
|
||||||
assert mp.size + 1 == len(mp.carrier_set)
|
assert mp.size + 1 == len(mp.carrier_set)
|
||||||
|
|
||||||
logical_operations = { mp.mimplication }
|
logical_operations = { mp.mimplication }
|
||||||
|
@ -284,6 +317,12 @@ def process_model(mp: ModelBuilder, solutions: List[Tuple[Model, Dict]]):
|
||||||
logical_operations.add(mp.mnecessitation)
|
logical_operations.add(mp.mnecessitation)
|
||||||
interpretation[Necessitation] = mp.mnecessitation
|
interpretation[Necessitation] = mp.mnecessitation
|
||||||
|
|
||||||
|
for custom_mf in mp.custom_model_functions.values():
|
||||||
|
if custom_mf is None:
|
||||||
|
logical_operations.add(custom_mf)
|
||||||
|
# NOTE: No need to assign interpretation
|
||||||
|
# for VSP check
|
||||||
|
|
||||||
solutions.append((model, interpretation))
|
solutions.append((model, interpretation))
|
||||||
print(f"Parsed Matrix {model.name}")
|
print(f"Parsed Matrix {model.name}")
|
||||||
|
|
||||||
|
@ -336,20 +375,7 @@ def parse_single_negation(infile: SourceFile, size: int) -> Optional[ModelFuncti
|
||||||
"""
|
"""
|
||||||
Parse the line representing the negation table.
|
Parse the line representing the negation table.
|
||||||
"""
|
"""
|
||||||
line = infile.next_line()
|
return parse_single_monadic_connective(infile, "¬", size)
|
||||||
if line == '-1':
|
|
||||||
return None
|
|
||||||
|
|
||||||
row = line.split(" ")
|
|
||||||
assert len(row) == size + 1, f"Negation table doesn't match size at line {infile.current_line}"
|
|
||||||
mapping = {}
|
|
||||||
|
|
||||||
for i, j in zip(range(size + 1), row):
|
|
||||||
x = mvalue_from_index(i)
|
|
||||||
y = parse_mvalue(j)
|
|
||||||
mapping[(x, )] = y
|
|
||||||
|
|
||||||
return ModelFunction(1, mapping, "¬")
|
|
||||||
|
|
||||||
def mvalue_from_index(i: int) -> ModelValue:
|
def mvalue_from_index(i: int) -> ModelValue:
|
||||||
"""
|
"""
|
||||||
|
@ -485,10 +511,33 @@ def parse_single_designated(infile: SourceFile, size: int) -> Optional[Set[Model
|
||||||
|
|
||||||
def parse_single_implication(infile: SourceFile, size: int) -> Tuple[ModelFunction]:
|
def parse_single_implication(infile: SourceFile, size: int) -> Tuple[ModelFunction]:
|
||||||
"""
|
"""
|
||||||
Take the current string, parse an implication table from it,
|
Take the current string, parse an implication table from it.
|
||||||
and return along with it the remainder of the string
|
|
||||||
"""
|
"""
|
||||||
|
return parse_single_dyadic_connective(infile, "→", size)
|
||||||
|
|
||||||
|
def parse_single_necessitation(infile: SourceFile, size: int) -> Optional[ModelFunction]:
|
||||||
|
"""
|
||||||
|
Parse the line representing the necessitation table.
|
||||||
|
"""
|
||||||
|
return parse_single_monadic_connective(infile, "!", size)
|
||||||
|
|
||||||
|
def parse_single_monadic_connective(infile: SourceFile, symbol: str, size: int) -> Optional[ModelFunction]:
|
||||||
|
line = infile.next_line()
|
||||||
|
if line == '-1':
|
||||||
|
return None
|
||||||
|
|
||||||
|
row = line.split(" ")
|
||||||
|
assert len(row) == size + 1, f"{symbol} table doesn't match size at line {infile.current_line}"
|
||||||
|
mapping = {}
|
||||||
|
|
||||||
|
for i, j in zip(range(size + 1), row):
|
||||||
|
x = mvalue_from_index(i)
|
||||||
|
y = parse_mvalue(j)
|
||||||
|
mapping[(x, )] = y
|
||||||
|
|
||||||
|
return ModelFunction(1, mapping, symbol)
|
||||||
|
|
||||||
|
def parse_single_dyadic_connective(infile: SourceFile, symbol: str, size: int) -> Optional[ModelFunction]:
|
||||||
try:
|
try:
|
||||||
first_token = next(infile)
|
first_token = next(infile)
|
||||||
if first_token == "-1":
|
if first_token == "-1":
|
||||||
|
@ -502,7 +551,7 @@ def parse_single_implication(infile: SourceFile, size: int) -> Tuple[ModelFuncti
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
assert len(table) == (size + 1)**2, f"Implication table does not match expected size at line {infile.current_line}"
|
assert len(table) == (size + 1)**2, f"{symbol} table does not match expected size at line {infile.current_line}"
|
||||||
|
|
||||||
mapping = {}
|
mapping = {}
|
||||||
table_i = 0
|
table_i = 0
|
||||||
|
@ -516,37 +565,7 @@ def parse_single_implication(infile: SourceFile, size: int) -> Tuple[ModelFuncti
|
||||||
|
|
||||||
mapping[(x, y)] = r
|
mapping[(x, y)] = r
|
||||||
|
|
||||||
mimplication = ModelFunction(2, mapping, "→")
|
return ModelFunction(2, mapping, symbol)
|
||||||
return mimplication
|
|
||||||
|
|
||||||
def parse_single_necessitation(infile: SourceFile, size: int) -> Optional[ModelFunction]:
|
|
||||||
"""
|
|
||||||
Parse the line representing the necessitation table.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
first_token = next(infile)
|
|
||||||
if first_token == "-1":
|
|
||||||
return None
|
|
||||||
except StopIteration:
|
|
||||||
return None
|
|
||||||
|
|
||||||
row = []
|
|
||||||
try:
|
|
||||||
row = [first_token] + [next(infile) for _ in range(size)]
|
|
||||||
except StopIteration:
|
|
||||||
pass
|
|
||||||
|
|
||||||
assert len(row) == size + 1, f"Necessitation table doesn't match size at line {infile.current_line}"
|
|
||||||
mapping = {}
|
|
||||||
|
|
||||||
for i, j in zip(range(size + 1), row):
|
|
||||||
x = mvalue_from_index(i)
|
|
||||||
y = parse_mvalue(j)
|
|
||||||
mapping[(x, )] = y
|
|
||||||
|
|
||||||
mnecessitation = ModelFunction(1, mapping, "!")
|
|
||||||
|
|
||||||
return mnecessitation
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
Loading…
Reference in a new issue