public static Tensor symmetrize(SimpleTensor tensor, int[] freeIndices, Symmetries symmetries) {
    if (symmetries.isEmpty()) return tensor;
    int[] tempI = freeIndices.clone();
    int[] allFreeIndices = tensor.getIndices().getFree().getAllIndices().copy();
    Arrays.sort(tempI);
    Arrays.sort(allFreeIndices);
    int[] diff = MathUtils.intSetDifference(tempI, allFreeIndices);
    System.arraycopy(freeIndices, 0, allFreeIndices, 0, freeIndices.length);
    System.arraycopy(diff, 0, allFreeIndices, freeIndices.length, diff.length);

    SumBuilder builder = new SumBuilder();
    Tensor temp;
    for (Symmetry symmetry : symmetries) {
      temp =
          applyIndexMapping(tensor, allFreeIndices, permute(allFreeIndices, symmetry), new int[0]);
      if (symmetry.isAntiSymmetry()) temp = negate(temp);
      builder.put(temp);
    }
    temp = builder.build();
    if (temp instanceof Sum) {
      // retrieving factor
      Complex factor = null, tempF;
      for (int i = temp.size() - 1; i >= 0; --i) {
        if (temp.get(i) instanceof Product) {
          tempF = ((Product) temp.get(i)).getFactor();
          assert tempF.isInteger();
          tempF = tempF.abs();
        } else tempF = Complex.ONE;
        if (factor == null) factor = tempF;
        assert factor.equals(tempF);
      }

      if (!factor.isOne())
        temp = FastTensors.multiplySumElementsOnFactor((Sum) temp, factor.reciprocal());
      return multiply(new Complex(new Rational(1, temp.size())), temp);
    }
    return temp;
  }