Returns true if the nodes are polynomial terms that can be added together.
336709
function canAddLikeTermPolynomialNodes(node) {
  if (!Node.Type.isOperator(node) || node.op !== '+') {
    return false;
  }
  const args = node.args;
  if (!args.every(n => Node.PolynomialTerm.isPolynomialTerm(n))) {
    return false;
  }
  if (args.length === 1) {
    return false;
  }

  const polynomialTermList = args.map(n => new Node.PolynomialTerm(n));

  // to add terms, they must have the same symbol name *and* exponent
  const firstTerm = polynomialTermList[0];
  const sharedSymbol = firstTerm.getSymbolName();
  const sharedExponentNode = firstTerm.getExponentNode(true);

  const restTerms = polynomialTermList.slice(1);
  return restTerms.every(term => {
    const haveSameSymbol = sharedSymbol === term.getSymbolName();
    const exponentNode = term.getExponentNode(true);
    const haveSameExponent = exponentNode.equals(sharedExponentNode);
    return haveSameSymbol && haveSameExponent;
  });
}
99147
def is_subsumed_by(x, y):
    
    varsX = __split_expression(x)[1]
    theta = unify(x, y)
    if theta is problem.FAILURE:
        return False
    return all(__is_variable(theta[var]) for var in theta.keys()
               if var in varsX)
54472
public function append(Node $node) : bool
    {
        $node->parent = $this;

        return $this->childNodes->add($node);
    }
344534
def mul_at(self, other, k):
        ''''''
        if k > (self.degree + other.degree) or k > self.degree: return 0 # optimization: if the required coefficient is above the maximum coefficient of the resulting polynomial, we can already predict that and just return 0

        term = 0

        for i in _range(min(len(self), len(other))):
            coef1 = self.coefficients[-(k-i+1)]
            coef2 = other.coefficients[-(i+1)]
            if coef1 == 0 or coef2 == 0: continue # log(0) is undefined, skip (and in addition it's a nice optimization)
            term += coef1 * coef2
        return term
661881
def is_syntactic(self):
        """"""
        for term in self._terms:
            if isinstance(term, Wildcard) and not term.fixed_size:
                return False
            if is_operation(term) and issubclass(term, (AssociativeOperation, CommutativeOperation)):
                return False
        return True
204271
def union(self, i, j):
        '''
        
        '''
        roots = (self.find(i), self.find(j))
        if roots[0] == roots[1]:
            return False
        if self.sizes[roots[0]] <= self.sizes[roots[1]] or not self.optimize:
            self.add_edge(roots[0], roots[1])
            self.sizes[roots[1]] += self.sizes[roots[0]]
            return True
        else:
            self.add_edge(roots[1], roots[0])
            self.sizes[roots[0]] += self.sizes[roots[1]]
            return True
952600
def expand(self, vs=None, conj=False):
        """"""
        vs = self._expect_vars(vs)
        if vs:
            outer, inner = (And, Or) if conj else (Or, And)
            terms = [inner(self.restrict(p),
                           *boolfunc.point2term(p, conj))
                     for p in boolfunc.iter_points(vs)]
            if conj:
                terms = [term for term in terms if term is not One]
            else:
                terms = [term for term in terms if term is not Zero]
            return outer(*terms, simplify=False)
        else:
            return self
188155
def is_cyclic(graph):
    
    path = set()

    def visit(vertex):
        path.add(vertex)
        for neighbour in graph.get(vertex, ()):
            if neighbour in path or visit(neighbour):
                return True
        path.remove(vertex)
        return False

    return any(visit(v) for v in graph)
305165
def get_support(variables, polynomial):
    
    support = []
    if is_number_type(polynomial):
        support.append([0] * len(variables))
        return support
    for monomial in polynomial.expand().as_coefficients_dict():
        tmp_support = [0] * len(variables)
        mon, _ = __separate_scalar_factor(monomial)
        symbolic_support = flatten(split_commutative_parts(mon))
        for s in symbolic_support:
            if isinstance(s, Pow):
                base = s.base
                if is_adjoint(base):
                    base = base.adjoint()
                tmp_support[variables.index(base)] = s.exp
            elif is_adjoint(s):
                tmp_support[variables.index(s.adjoint())] = 1
            elif isinstance(s, (Operator, Symbol)):
                tmp_support[variables.index(s)] = 1
        support.append(tmp_support)
    return support
1264697
def is_bifurcating(self, include_root=True):
        
        ctn1 = -1 + (2 * len(self))
        ctn2 = -2 + (2 * len(self))
        if self.is_rooted():
            return bool(ctn1 == sum(1 for i in self.treenode.traverse()))
        if include_root:
            return bool(ctn2 == -1 + sum(1 for i in self.treenode.traverse()))
        return bool(ctn2 == sum(1 for i in self.treenode.traverse()))
152239
def get_support_variables(polynomial):
    
    support = []
    if is_number_type(polynomial):
        return support
    for monomial in polynomial.expand().as_coefficients_dict():
        mon, _ = __separate_scalar_factor(monomial)
        symbolic_support = flatten(split_commutative_parts(mon))
        for s in symbolic_support:
            if isinstance(s, Pow):
                base = s.base
                if is_adjoint(base):
                    base = base.adjoint()
                support.append(base)
            elif is_adjoint(s):
                support.append(s.adjoint())
            elif isinstance(s, Operator):
                support.append(s)
    return support
131744
function groupCoefficientsForAdding(node) {
  let newNode = clone(node);

  const polynomialTermList = newNode.args.map(n => new Node.PolynomialTerm(n));
  const coefficientList = polynomialTermList.map(p => p.getCoeffNode(true));
  const sumOfCoefficents = Node.Creator.parenthesis(
    Node.Creator.operator('+', coefficientList));
  // TODO: changegroups should also be on the before node, on all the
  // coefficients, but changegroups with polyTerm gets messy so let's tackle
  // that later.
  sumOfCoefficents.changeGroup = 1;

  // Polynomial terms that can be added together must share the same symbol
  // name and exponent. Get that name and exponent from the first term
  const firstTerm = polynomialTermList[0];
  const exponentNode = firstTerm.getExponentNode();
  const symbolNode = firstTerm.getSymbolNode();
  newNode = Node.Creator.polynomialTerm(
    symbolNode, exponentNode, sumOfCoefficents);

  return Node.Status.nodeChanged(
    ChangeTypes.GROUP_COEFFICIENTS, node, newNode);
}
1283791
function canCollectOrCombine(node) {
  return LikeTermCollector.canCollectLikeTerms(node) ||
    checks.resolvesToConstant(node) ||
    checks.canSimplifyPolynomialTerms(node);
}
1232686
public static boolean isNodeTheSame(Node node1, Node node2)
  {
    if (node1 instanceof DTMNodeProxy && node2 instanceof DTMNodeProxy)
      return ((DTMNodeProxy)node1).equals((DTMNodeProxy)node2);
    else
      return (node1 == node2);
  }
1335565
function getTermName(node, op) {
  const polyNode = new Node.PolynomialTerm(node);
  // we 'name' polynomial terms by their symbol name
  let termName = polyNode.getSymbolName();
  // when adding terms, the exponent matters too (e.g. 2x^2 + 5x^3 can't be combined)
  if (op === '+') {
    const exponent = print(polyNode.getExponentNode(true));
    termName += '^' + exponent;
  }
  return termName;
}
616594
function hasMultiplicationBesideDivision(node) {
  if (!Node.Type.isOperator(node)) {
    return false;
  }
  if (node.op === '*') {
    return true;
  }
  // we ony recurse through division
  if (node.op !== '/') {
    return false;
  }
  return node.args.some(hasMultiplicationBesideDivision);
}
1046725
def polynomial_multiply_mod( m1, m2, polymod, p ):
  """"""

  # This is just a seat-of-the-pants implementation.

  # This module has been tested only by extensive use
  # in calculating modular square roots.

  # Initialize the product to zero:

  prod = ( len( m1 ) + len( m2 ) - 1 ) * [0]

  # Add together all the cross-terms:

  for i in range( len( m1 ) ):
    for j in range( len( m2 ) ):
      prod[i+j] = ( prod[i+j] + m1[i] * m2[j] ) % p

  return polynomial_reduce_mod( prod, polymod, p )