added ternary support. explodes time complexity, but I think it could really help the max expression-tree size

This commit is contained in:
Alex Thannhauser 2025-06-10 12:57:11 -05:00
parent 2499db7c7d
commit 98bf135199

60
main.py
View file

@ -67,6 +67,7 @@ symbol_to_name = {
"==": "nxor", "==": "nxor",
"|!": "orn", "|!": "orn",
"&!": "andn", "&!": "andn",
"?:": "ternary",
}; };
def determine_available_operators(args): def determine_available_operators(args):
@ -201,6 +202,8 @@ def calculate_simplifications(args, available_operators):
return extract_variables(inner); return extract_variables(inner);
case (_, left, right): case (_, left, right):
return extract_variables(left) + extract_variables(right); return extract_variables(left) + extract_variables(right);
case (_, cond, true, false):
return extract_variables(cond) + extract_variables(true) + extract_variables(false);
case _: case _:
print(exp); print(exp);
assert(not "TODO"); assert(not "TODO");
@ -225,6 +228,10 @@ def calculate_simplifications(args, available_operators):
'==': lambda x, y: ~(x ^ y), # nxor '==': lambda x, y: ~(x ^ y), # nxor
} }
ternary_operators = {
'?:': lambda x, y, z: (x & y) | (~x & z), # ternary
};
def print_status(): def print_status():
numerator = 65536 - todo_count[0]; numerator = 65536 - todo_count[0];
denominator = 65536 denominator = 65536
@ -307,6 +314,29 @@ def calculate_simplifications(args, available_operators):
consider(binary_truthtable, binary_expression, binary_cost); consider(binary_truthtable, binary_expression, binary_cost);
# consider ternary operators:
for name, function in sorted(ternary_operators.items()):
if name in available_operators:
s = sorted(lookup.items());
for a_truthtable, a_expression in s:
for b_truthtable, b_expression in s:
# x ? y : z
ternary_truthtable = function(
my_truthtable, a_truthtable, b_truthtable) & M;
ternary_expression = (name,
my_expression, a_expression, b_expression);
ternary_cost = 1 + my_cost + \
costs[a_truthtable] + costs[b_truthtable];
consider(ternary_truthtable, ternary_expression, \
ternary_cost);
# y ? x : z
# assert(not "TODO");
# z ? y : z
# assert(not "TODO");
return costs, lookup return costs, lookup
pathname = "simplifications.bin" pathname = "simplifications.bin"
@ -393,7 +423,7 @@ def parse(text):
self.tokendata = self.text[self.position]; self.tokendata = self.text[self.position];
self.position += 1; self.position += 1;
case "(" | ")": case "(" | ")" | "?" | ":":
self.tokenkind = self.text[self.position]; self.tokenkind = self.text[self.position];
self.position += 1; self.position += 1;
@ -551,8 +581,30 @@ def parse(text):
return left; return left;
def parse_ternary(tokenizer):
exp = parse_ors(tokenizer);
if tokenizer.tokenkind in ("?", ):
cond = exp;
tokenizer.next();
true = parse_ors(tokenizer);
if tokenizer.tokenkind != ":":
raise BaseException("expecting ':' in ternary expression, "
"found: '{tokenizer.tokenkind}'!");
tokenizer.next();
false = parse_ternary(tokenizer);
return ("?:", cond, true, false);
else:
return exp;
def parse_root(tokenizer): def parse_root(tokenizer):
return parse_ors(tokenizer); return parse_ternary(tokenizer);
tokenizer = Tokenizer(text); tokenizer = Tokenizer(text);
@ -608,6 +660,10 @@ def evaluate(expr):
case ("!&", left, right): case ("!&", left, right):
return ~(evaluate(left) & evaluate(right)) & M; return ~(evaluate(left) & evaluate(right)) & M;
case ("?:", cond, left, right):
cond = evaluate(cond);
return (cond & evaluate(left)) | (~cond & evaluate(right));
case _: case _:
print(f'expr = {expr}'); print(f'expr = {expr}');
assert(not "TODO"); assert(not "TODO");