| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- class Variable:
- def __init__(self, name):
- self.name = name
- def __pow__(self, n):
- expr = MultiplyExpression()
- expr.set_symbol(self.name, n)
- return expr
- def __eq__(self, other):
- return self.name == other.name
- def termify(self):
- expr = MultiplyExpression()
- expr.set_symbol(self.name, 1)
- return expr
- class MultiplyExpression:
- def __init__(self):
- self.coeff = fp(1)
- self.symbols = {}
- def clean(self):
- for symbol in list(self.symbols.keys()):
- if self.symbols[symbol] == 0:
- del self.symbols[symbol]
- def matches(self, other):
- return self.symbols == other.symbols
- def set_symbol(self, var_name, power):
- self.symbols[var_name] = power
- def __mul__(self, expr):
- result = MultiplyExpression()
- result.coeff = self.coeff
- result.symbols = self.symbols.copy()
- if hasattr(expr, "field"):
- result.coeff *= expr
- return result
- if isinstance(expr, Variable):
- expr = expr.termify()
- for var_name, power in expr.symbols.items():
- if var_name in result.symbols:
- result.symbols[var_name] += power
- else:
- result.symbols[var_name] = power
- return result
- def __add__(self, expr):
- if isinstance(expr, Variable):
- expr = expr.termify()
- return MultivariatePolynomial([self, expr])
- def __str__(self):
- repr = ""
- first = True
- if self.coeff != fp(1):
- repr += str(self.coeff)
- first = False
- for var_name, power in self.symbols.items():
- if first:
- first = False
- else:
- repr += " "
- if power == 1:
- repr += var_name
- else:
- repr += var_name + "^" + str(power)
- return repr
- class MultivariatePolynomial:
- def __init__(self, terms=[]):
- self.terms = terms
- def copy(self):
- return MultivariatePolynomial(self.terms[:])
- def __add__(self, term):
- if isinstance(term, Variable):
- term = term.termify()
- if hasattr(term, "field"):
- expr = MultiplyExpression()
- expr.coeff = term
- term = expr
- if isinstance(term, MultiplyExpression):
- # Delete ^0 variables
- term.clean()
- # Skip zero terms
- #if term.coeff is None or term.coeff == 0:
- # return self
- result = self.copy()
- result_term = result.find(term)
- if result_term is None:
- result.terms.append(term)
- else:
- result_term.coeff += term.coeff
- return result
- else:
- assert isinstance(term, MultivariatePolynomial)
- result = self.copy()
- for other_term in term.terms:
- result += other_term
- return result
- def __mul__(self, other):
- if isinstance(term, Variable):
- term = term.termify()
- if hasattr(term, "field"):
- expr = MultiplyExpression()
- expr.coeff = term
- term = expr
- if isinstance(term, MultiplyExpression):
- # Delete ^0 variables
- term.clean()
- return None
- else:
- assert isinstance(term, MultivariatePolynomial)
- return None
- def find(self, other):
- for term in self.terms:
- if term.matches(other):
- return term
- return None
- def __str__(self):
- if not self.terms:
- return "0"
- repr = ""
- first = True
- for term in self.terms:
- if first:
- first = False
- else:
- repr += " + "
- repr += str(term)
- return repr
- if __name__ == "__main__":
- from finite_fields import finitefield
- p = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001
- fp = finitefield.IntegersModP(p)
- x = Variable("X")
- y = Variable("Y")
- z = Variable("Z")
- p = x**3 * y**2 * x**2 * fp(5) * fp(2) + x**3 * y + z + fp(6)
- q = x**3 * y * fp(3) + y
- print(p)
- print(q)
- print(p + q)
|