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
|
||||
"""
|
||||
import argparse
|
||||
import re
|
||||
import sys
|
||||
from typing import TextIO, List, Optional, Tuple, Set, Dict
|
||||
|
||||
|
@ -72,7 +73,7 @@ class ModelBuilder:
|
|||
self.mimplication: Optional[ModelFunction] = None
|
||||
self.num_necessitation: int = 0
|
||||
self.mnecessitation: Optional[ModelFunction] = None
|
||||
self.custom_model_functions: List[Tuple[int, ModelFunction]]
|
||||
self.custom_model_functions: Dict[str, ModelFunction] = {}
|
||||
|
||||
class Stage:
|
||||
def __init__(self, name: str):
|
||||
|
@ -89,10 +90,13 @@ class Stages:
|
|||
def add(self, name: str):
|
||||
stage = Stage(name)
|
||||
stage.next = stage
|
||||
|
||||
if self.last_stage is not None:
|
||||
stage.previous = self.last_stage
|
||||
self.last_stage.next = stage
|
||||
else:
|
||||
# The previous of the first stage
|
||||
# is the end
|
||||
stage.previous = Stage("end")
|
||||
|
||||
self.stages[name] = stage
|
||||
|
@ -114,9 +118,8 @@ def derive_stages(header: UglyHeader) -> Stages:
|
|||
stages.add("implication")
|
||||
if header.necessitation:
|
||||
stages.add("necessitation")
|
||||
# TODO: Can't use -- as that can be a custom symbol
|
||||
# for (acidity, symbol) in header.custom_model_functions:
|
||||
# stages.add(f"custom--{acidity}--{symbol}")
|
||||
for (adicity, symbol) in header.custom_model_functions:
|
||||
stages.add(f"custom--{adicity}--{symbol}")
|
||||
stages.add("process_model")
|
||||
|
||||
# After processing the model, go to the previous stage
|
||||
|
@ -124,7 +127,6 @@ def derive_stages(header: UglyHeader) -> Stages:
|
|||
|
||||
return stages
|
||||
|
||||
|
||||
def parse_matrices(infile: SourceFile) -> List[Tuple[Model, Dict]]:
|
||||
solutions = [] # Reset
|
||||
header = parse_header(infile)
|
||||
|
@ -160,7 +162,23 @@ def parse_matrices(infile: SourceFile) -> List[Tuple[Model, Dict]]:
|
|||
processed = process_necessitations(infile, current_model_parts)
|
||||
stage = stage.next if processed else stage.previous
|
||||
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
|
||||
|
||||
|
@ -259,10 +277,25 @@ def process_necessitations(infile: SourceFile, current_model_parts: ModelBuilder
|
|||
|
||||
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]]):
|
||||
"""Create Model"""
|
||||
assert mp.mimplication is not None
|
||||
assert len(mp.carrier_set) > 0
|
||||
assert mp.size + 1 == len(mp.carrier_set)
|
||||
|
||||
logical_operations = { mp.mimplication }
|
||||
|
@ -284,6 +317,12 @@ def process_model(mp: ModelBuilder, solutions: List[Tuple[Model, Dict]]):
|
|||
logical_operations.add(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))
|
||||
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.
|
||||
"""
|
||||
line = infile.next_line()
|
||||
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, "¬")
|
||||
return parse_single_monadic_connective(infile, "¬", size)
|
||||
|
||||
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]:
|
||||
"""
|
||||
Take the current string, parse an implication table from it,
|
||||
and return along with it the remainder of the string
|
||||
Take the current string, parse an implication table from it.
|
||||
"""
|
||||
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:
|
||||
first_token = next(infile)
|
||||
if first_token == "-1":
|
||||
|
@ -502,7 +551,7 @@ def parse_single_implication(infile: SourceFile, size: int) -> Tuple[ModelFuncti
|
|||
except StopIteration:
|
||||
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 = {}
|
||||
table_i = 0
|
||||
|
@ -516,37 +565,7 @@ def parse_single_implication(infile: SourceFile, size: int) -> Tuple[ModelFuncti
|
|||
|
||||
mapping[(x, y)] = r
|
||||
|
||||
mimplication = ModelFunction(2, mapping, "→")
|
||||
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
|
||||
return ModelFunction(2, mapping, symbol)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
Loading…
Reference in a new issue