mirror of
https://github.com/Brandon-Rozek/matmod.git
synced 2024-12-04 13:45:56 -05:00
Code cleanup
This commit is contained in:
parent
6b4d5828c8
commit
6bb863da97
3 changed files with 57 additions and 33 deletions
|
@ -1,9 +1,13 @@
|
||||||
"""
|
"""
|
||||||
File which generates all the models
|
Generate all the models for a given logic
|
||||||
|
with a specified number of elements.
|
||||||
"""
|
"""
|
||||||
from common import set_to_str
|
from common import set_to_str
|
||||||
from logic import Logic, Operation, Rule, get_operations_from_term
|
from logic import Logic, Operation, Rule, get_operations_from_term
|
||||||
from model import ModelValue, Model, satisfiable, ModelFunction, ModelOrderConstraint
|
from model import (
|
||||||
|
Interpretation, ModelValue, Model,
|
||||||
|
satisfiable, ModelFunction
|
||||||
|
)
|
||||||
from itertools import combinations, chain, product
|
from itertools import combinations, chain, product
|
||||||
from typing import Set, List, Dict, Tuple
|
from typing import Set, List, Dict, Tuple
|
||||||
|
|
||||||
|
@ -13,6 +17,11 @@ def possible_designations(iterable):
|
||||||
return chain.from_iterable(combinations(s, r) for r in range(1, len(s)))
|
return chain.from_iterable(combinations(s, r) for r in range(1, len(s)))
|
||||||
|
|
||||||
def possible_functions(operation, carrier_set):
|
def possible_functions(operation, carrier_set):
|
||||||
|
"""
|
||||||
|
Create every possible input, output pair
|
||||||
|
for a given model function based on an
|
||||||
|
operation and a carrier set.
|
||||||
|
"""
|
||||||
arity = operation.arity
|
arity = operation.arity
|
||||||
|
|
||||||
inputs = list(product(carrier_set, repeat=arity))
|
inputs = list(product(carrier_set, repeat=arity))
|
||||||
|
@ -26,12 +35,19 @@ def possible_functions(operation, carrier_set):
|
||||||
yield ModelFunction(arity, new_function, operation.symbol)
|
yield ModelFunction(arity, new_function, operation.symbol)
|
||||||
|
|
||||||
|
|
||||||
def only_rules_with(rules: Set[Rule], operation: Operation) -> Set[Rule]:
|
def only_rules_with(rules: Set[Rule], operation: Operation) -> List[Rule]:
|
||||||
result_rules = []
|
"""
|
||||||
|
Filter the list of rules in a logic to those
|
||||||
|
that only contain the logical operation specified.
|
||||||
|
"""
|
||||||
|
result_rules: List[Rule] = []
|
||||||
for rule in rules:
|
for rule in rules:
|
||||||
is_valid = True
|
is_valid = True
|
||||||
|
# Go through every term in the premises and conclusion
|
||||||
for t in (rule.premises | {rule.conclusion,}):
|
for t in (rule.premises | {rule.conclusion,}):
|
||||||
t_operations = get_operations_from_term(t)
|
t_operations = get_operations_from_term(t)
|
||||||
|
# Make sure there's only one operation
|
||||||
|
# and that it matches the operation specified
|
||||||
if len(t_operations) > 1:
|
if len(t_operations) > 1:
|
||||||
is_valid = False
|
is_valid = False
|
||||||
break
|
break
|
||||||
|
@ -48,23 +64,32 @@ def only_rules_with(rules: Set[Rule], operation: Operation) -> Set[Rule]:
|
||||||
|
|
||||||
def possible_interpretations(
|
def possible_interpretations(
|
||||||
logic: Logic, carrier_set: Set[ModelValue],
|
logic: Logic, carrier_set: Set[ModelValue],
|
||||||
designated_values: Set[ModelValue], ordering: Set[ModelOrderConstraint]):
|
designated_values: Set[ModelValue]):
|
||||||
operations = []
|
"""
|
||||||
model_functions = []
|
Consider every possible interpretation of operations
|
||||||
|
within the specified logic given the carrier set of
|
||||||
|
model values, and the set of designated values.
|
||||||
|
"""
|
||||||
|
operations: List[Operation] = []
|
||||||
|
model_functions: List[List[ModelFunction]] = []
|
||||||
|
|
||||||
for operation in logic.operations:
|
for operation in logic.operations:
|
||||||
operations.append(operation)
|
operations.append(operation)
|
||||||
candidate_functions = list(possible_functions(operation, carrier_set))
|
candidate_functions = list(possible_functions(operation, carrier_set))
|
||||||
passed_functions = []
|
passed_functions: List[ModelFunction] = []
|
||||||
"""
|
"""
|
||||||
Only consider functions that at least pass
|
Discard candidate functions that don't pass
|
||||||
in the rules with the operation by itself.
|
the rules that only contain the given
|
||||||
|
logical operation.
|
||||||
"""
|
"""
|
||||||
restricted_rules = only_rules_with(logic.rules, operation)
|
restricted_rules = only_rules_with(logic.rules, operation)
|
||||||
if len(restricted_rules) > 0:
|
if len(restricted_rules) > 0:
|
||||||
small_logic = Logic({operation,}, restricted_rules)
|
small_logic = Logic({operation,}, restricted_rules)
|
||||||
|
# Add candidate functions whose small model
|
||||||
|
# and logic are satisfied given the restricted
|
||||||
|
# rule set.
|
||||||
for f in candidate_functions:
|
for f in candidate_functions:
|
||||||
small_model = Model(carrier_set, {f,}, designated_values, ordering)
|
small_model = Model(carrier_set, {f,}, designated_values)
|
||||||
interp = {operation: f}
|
interp = {operation: f}
|
||||||
if satisfiable(small_logic, small_model, interp):
|
if satisfiable(small_logic, small_model, interp):
|
||||||
passed_functions.append(f)
|
passed_functions.append(f)
|
||||||
|
@ -78,45 +103,42 @@ def possible_interpretations(
|
||||||
)
|
)
|
||||||
model_functions.append(passed_functions)
|
model_functions.append(passed_functions)
|
||||||
|
|
||||||
|
# The model_functions variables contains
|
||||||
|
# the candidate functions for each operation.
|
||||||
|
|
||||||
functions_choice = product(*model_functions)
|
functions_choice = product(*model_functions)
|
||||||
|
# Assign a function to each operation
|
||||||
for functions in functions_choice:
|
for functions in functions_choice:
|
||||||
assert len(operations) == len(functions)
|
assert len(operations) == len(functions)
|
||||||
interpretation = dict()
|
interpretation: Interpretation = dict()
|
||||||
for operation, function in zip(operations, functions):
|
for operation, function in zip(operations, functions):
|
||||||
interpretation[operation] = function
|
interpretation[operation] = function
|
||||||
yield interpretation
|
yield interpretation
|
||||||
|
|
||||||
def generate_model(logic: Logic, number_elements: int, num_solutions: int = -1, print_model=False) -> List[Tuple[Model, Dict[Operation, ModelFunction]]]:
|
def generate_model(
|
||||||
|
logic: Logic, number_elements: int, num_solutions: int = -1,
|
||||||
|
print_model=False) -> List[Tuple[Model, Interpretation]]:
|
||||||
|
"""
|
||||||
|
Generate the specified number of models that
|
||||||
|
satisfy a logic of a certain size.
|
||||||
|
"""
|
||||||
assert number_elements > 0
|
assert number_elements > 0
|
||||||
carrier_set = {
|
carrier_set = {
|
||||||
ModelValue("a" + str(i)) for i in range(number_elements)
|
ModelValue("a" + str(i)) for i in range(number_elements)
|
||||||
}
|
}
|
||||||
|
|
||||||
ordering = set()
|
|
||||||
|
|
||||||
# a(0) is less than all other elements
|
|
||||||
a0 = ModelValue("a0")
|
|
||||||
for v in carrier_set:
|
|
||||||
if v != a0:
|
|
||||||
ordering.add(a0 < v)
|
|
||||||
|
|
||||||
# Every other element is less than a(n - 1)
|
|
||||||
an = ModelValue(f"a{number_elements-1}")
|
|
||||||
for v in carrier_set:
|
|
||||||
if an != v:
|
|
||||||
ordering.add(v < an)
|
|
||||||
|
|
||||||
possible_designated_values = possible_designations(carrier_set)
|
possible_designated_values = possible_designations(carrier_set)
|
||||||
|
|
||||||
solutions: List[Tuple[Model, Dict[Operation, ModelFunction]]] = []
|
solutions: List[Tuple[Model, Interpretation]] = []
|
||||||
|
|
||||||
for designated_values in possible_designated_values:
|
for designated_values in possible_designated_values:
|
||||||
designated_values = set(designated_values)
|
designated_values = set(designated_values)
|
||||||
print("Considering models for designated values", set_to_str(designated_values))
|
print("Considering models for designated values", set_to_str(designated_values))
|
||||||
possible_interps = possible_interpretations(logic, carrier_set, designated_values, ordering)
|
|
||||||
|
|
||||||
|
possible_interps = possible_interpretations(logic, carrier_set, designated_values)
|
||||||
for interpretation in possible_interps:
|
for interpretation in possible_interps:
|
||||||
is_valid = True
|
is_valid = True
|
||||||
model = Model(carrier_set, set(interpretation.values()), designated_values, ordering)
|
model = Model(carrier_set, set(interpretation.values()), designated_values)
|
||||||
# Iteratively test possible interpretations
|
# Iteratively test possible interpretations
|
||||||
# by adding one axiom at a time
|
# by adding one axiom at a time
|
||||||
for rule in logic.rules:
|
for rule in logic.rules:
|
||||||
|
@ -127,7 +149,6 @@ def generate_model(logic: Logic, number_elements: int, num_solutions: int = -1,
|
||||||
|
|
||||||
if is_valid:
|
if is_valid:
|
||||||
solutions.append((model, interpretation))
|
solutions.append((model, interpretation))
|
||||||
# satisfied_models.append(model)
|
|
||||||
if print_model:
|
if print_model:
|
||||||
print(model, flush=True)
|
print(model, flush=True)
|
||||||
|
|
||||||
|
|
2
logic.py
2
logic.py
|
@ -1,4 +1,4 @@
|
||||||
from typing import Any, Set, Tuple
|
from typing import Set, Tuple
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
|
|
||||||
class Operation:
|
class Operation:
|
||||||
|
|
5
model.py
5
model.py
|
@ -13,7 +13,8 @@ from itertools import combinations_with_replacement, permutations, product
|
||||||
from typing import Dict, List, Set, Tuple
|
from typing import Dict, List, Set, Tuple
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['ModelValue', 'ModelFunction', 'Model']
|
__all__ = ['ModelValue', 'ModelFunction', 'Model', 'Interpretation']
|
||||||
|
|
||||||
|
|
||||||
class ModelValue:
|
class ModelValue:
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
|
@ -63,6 +64,8 @@ class ModelFunction:
|
||||||
def __call__(self, *args):
|
def __call__(self, *args):
|
||||||
return self.mapping[args]
|
return self.mapping[args]
|
||||||
|
|
||||||
|
Interpretation = Dict[Operation, ModelFunction]
|
||||||
|
|
||||||
class Model:
|
class Model:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
|
Loading…
Reference in a new issue