feat(compiler): add more detailed statistics

This commit is contained in:
Umut
2023-07-26 14:27:32 +02:00
parent dae31f0f26
commit ade83d5335
14 changed files with 1407 additions and 272 deletions

View File

@@ -4,7 +4,7 @@ Concrete.
# pylint: disable=import-error,no-name-in-module
from concrete.compiler import EvaluationKeys, PublicArguments, PublicResult
from concrete.compiler import EvaluationKeys, Parameter, PublicArguments, PublicResult
from .compilation import (
DEFAULT_GLOBAL_P_ERROR,

View File

@@ -4,10 +4,15 @@ Declaration of `Circuit` class.
# pylint: disable=import-error,no-member,no-name-in-module
from typing import Any, List, Optional, Tuple, Union
from typing import Any, Dict, List, Optional, Tuple, Union
import numpy as np
from concrete.compiler import CompilationContext, SimulatedValueDecrypter, SimulatedValueExporter
from concrete.compiler import (
CompilationContext,
Parameter,
SimulatedValueDecrypter,
SimulatedValueExporter,
)
from mlir.ir import Module as MlirModule
from ..internal.utils import assert_that
@@ -266,118 +271,15 @@ class Circuit:
if hasattr(self, "server"): # pragma: no cover
self.server.cleanup()
@property
def size_of_secret_keys(self) -> int:
"""
Get size of the secret keys of the circuit.
"""
return self._statistic("size_of_secret_keys")
# Properties
@property
def size_of_bootstrap_keys(self) -> int:
def _property(self, name: str) -> Any:
"""
Get size of the bootstrap keys of the circuit.
"""
return self._statistic("size_of_bootstrap_keys")
@property
def size_of_keyswitch_keys(self) -> int:
"""
Get size of the key switch keys of the circuit.
"""
return self._statistic("size_of_keyswitch_keys")
@property
def size_of_inputs(self) -> int:
"""
Get size of the inputs of the circuit.
"""
return self._statistic("size_of_inputs")
@property
def size_of_outputs(self) -> int:
"""
Get size of the outputs of the circuit.
"""
return self._statistic("size_of_outputs")
@property
def p_error(self) -> int:
"""
Get probability of error for each simple TLU (on a scalar).
"""
return self._statistic("p_error")
@property
def global_p_error(self) -> int:
"""
Get the probability of having at least one simple TLU error during the entire execution.
"""
return self._statistic("global_p_error")
@property
def complexity(self) -> float:
"""
Get complexity of the circuit.
"""
return self._statistic("complexity")
@property
def total_pbs_count(self) -> int:
"""
Get the total number of programmable bootstraps in the circuit.
"""
return self._statistic("total_pbs_count")
@property
def total_ks_count(self) -> int:
"""
Get the total number of key switches in the circuit.
"""
return self._statistic("total_ks_count")
@property
def total_clear_addition_count(self) -> int:
"""
Get the total number of clear additions in the circuit.
"""
return self._statistic("total_clear_addition_count")
@property
def total_encrypted_addition_count(self) -> int:
"""
Get the total number of encrypted additions in the circuit.
"""
return self._statistic("total_encrypted_addition_count")
@property
def total_clear_multiplication_count(self) -> int:
"""
Get the total number of clear multiplications in the circuit.
"""
return self._statistic("total_clear_multiplication_count")
@property
def total_encrypted_negation_count(self) -> int:
"""
Get the total number of encrypted negations in the circuit.
"""
return self._statistic("total_encrypted_negation_count")
@property
def statistics(self) -> dict:
"""
Get all circuit statistics in a dict.
"""
return self._statistic("statistics")
def _statistic(self, name: str) -> Any:
"""
Get a statistic of the circuit by name.
Get a property of the circuit by name.
Args:
name (str):
name of the statistic
name of the property
Returns:
Any:
@@ -391,3 +293,282 @@ class Circuit:
self.enable_fhe_execution() # pragma: no cover
return getattr(self.server, name)
@property
def size_of_secret_keys(self) -> int:
"""
Get size of the secret keys of the circuit.
"""
return self._property("size_of_secret_keys") # pragma: no cover
@property
def size_of_bootstrap_keys(self) -> int:
"""
Get size of the bootstrap keys of the circuit.
"""
return self._property("size_of_bootstrap_keys") # pragma: no cover
@property
def size_of_keyswitch_keys(self) -> int:
"""
Get size of the key switch keys of the circuit.
"""
return self._property("size_of_keyswitch_keys") # pragma: no cover
@property
def size_of_inputs(self) -> int:
"""
Get size of the inputs of the circuit.
"""
return self._property("size_of_inputs") # pragma: no cover
@property
def size_of_outputs(self) -> int:
"""
Get size of the outputs of the circuit.
"""
return self._property("size_of_outputs") # pragma: no cover
@property
def p_error(self) -> int:
"""
Get probability of error for each simple TLU (on a scalar).
"""
return self._property("p_error") # pragma: no cover
@property
def global_p_error(self) -> int:
"""
Get the probability of having at least one simple TLU error during the entire execution.
"""
return self._property("global_p_error") # pragma: no cover
@property
def complexity(self) -> float:
"""
Get complexity of the circuit.
"""
return self._property("complexity") # pragma: no cover
# Programmable Bootstrap Statistics
@property
def programmable_bootstrap_count(self) -> int:
"""
Get the number of programmable bootstraps in the circuit.
"""
return self._property("programmable_bootstrap_count") # pragma: no cover
@property
def programmable_bootstrap_count_per_parameter(self) -> Dict[Parameter, int]:
"""
Get the number of programmable bootstraps per bit width in the circuit.
"""
return self._property("programmable_bootstrap_count_per_parameter") # pragma: no cover
@property
def programmable_bootstrap_count_per_tag(self) -> Dict[str, int]:
"""
Get the number of programmable bootstraps per tag in the circuit.
"""
return self._property("programmable_bootstrap_count_per_tag") # pragma: no cover
@property
def programmable_bootstrap_count_per_tag_per_parameter(self) -> Dict[str, Dict[int, int]]:
"""
Get the number of programmable bootstraps per tag per bit width in the circuit.
"""
return self._property(
"programmable_bootstrap_count_per_tag_per_parameter"
) # pragma: no cover
# Key Switch Statistics
@property
def key_switch_count(self) -> int:
"""
Get the number of key switches in the circuit.
"""
return self._property("key_switch_count") # pragma: no cover
@property
def key_switch_count_per_parameter(self) -> Dict[Parameter, int]:
"""
Get the number of key switches per parameter in the circuit.
"""
return self._property("key_switch_count_per_parameter") # pragma: no cover
@property
def key_switch_count_per_tag(self) -> Dict[str, int]:
"""
Get the number of key switches per tag in the circuit.
"""
return self._property("key_switch_count_per_tag") # pragma: no cover
@property
def key_switch_count_per_tag_per_parameter(self) -> Dict[str, Dict[Parameter, int]]:
"""
Get the number of key switches per tag per parameter in the circuit.
"""
return self._property("key_switch_count_per_tag_per_parameter") # pragma: no cover
# Packing Key Switch Statistics
@property
def packing_key_switch_count(self) -> int:
"""
Get the number of packing key switches in the circuit.
"""
return self._property("packing_key_switch_count") # pragma: no cover
@property
def packing_key_switch_count_per_parameter(self) -> Dict[Parameter, int]:
"""
Get the number of packing key switches per parameter in the circuit.
"""
return self._property("packing_key_switch_count_per_parameter") # pragma: no cover
@property
def packing_key_switch_count_per_tag(self) -> Dict[str, int]:
"""
Get the number of packing key switches per tag in the circuit.
"""
return self._property("packing_key_switch_count_per_tag") # pragma: no cover
@property
def packing_key_switch_count_per_tag_per_parameter(self) -> Dict[str, Dict[Parameter, int]]:
"""
Get the number of packing key switches per tag per parameter in the circuit.
"""
return self._property("packing_key_switch_count_per_tag_per_parameter") # pragma: no cover
# Clear Addition Statistics
@property
def clear_addition_count(self) -> int:
"""
Get the number of clear additions in the circuit.
"""
return self._property("clear_addition_count") # pragma: no cover
@property
def clear_addition_count_per_parameter(self) -> Dict[Parameter, int]:
"""
Get the number of clear additions per parameter in the circuit.
"""
return self._property("clear_addition_count_per_parameter") # pragma: no cover
@property
def clear_addition_count_per_tag(self) -> Dict[str, int]:
"""
Get the number of clear additions per tag in the circuit.
"""
return self._property("clear_addition_count_per_tag") # pragma: no cover
@property
def clear_addition_count_per_tag_per_parameter(self) -> Dict[str, Dict[Parameter, int]]:
"""
Get the number of clear additions per tag per parameter in the circuit.
"""
return self._property("clear_addition_count_per_tag_per_parameter") # pragma: no cover
# Encrypted Addition Statistics
@property
def encrypted_addition_count(self) -> int:
"""
Get the number of encrypted additions in the circuit.
"""
return self._property("encrypted_addition_count") # pragma: no cover
@property
def encrypted_addition_count_per_parameter(self) -> Dict[Parameter, int]:
"""
Get the number of encrypted additions per parameter in the circuit.
"""
return self._property("encrypted_addition_count_per_parameter") # pragma: no cover
@property
def encrypted_addition_count_per_tag(self) -> Dict[str, int]:
"""
Get the number of encrypted additions per tag in the circuit.
"""
return self._property("encrypted_addition_count_per_tag") # pragma: no cover
@property
def encrypted_addition_count_per_tag_per_parameter(self) -> Dict[str, Dict[Parameter, int]]:
"""
Get the number of encrypted additions per tag per parameter in the circuit.
"""
return self._property("encrypted_addition_count_per_tag_per_parameter") # pragma: no cover
# Clear Multiplication Statistics
@property
def clear_multiplication_count(self) -> int:
"""
Get the number of clear multiplications in the circuit.
"""
return self._property("clear_multiplication_count") # pragma: no cover
@property
def clear_multiplication_count_per_parameter(self) -> Dict[Parameter, int]:
"""
Get the number of clear multiplications per parameter in the circuit.
"""
return self._property("clear_multiplication_count_per_parameter") # pragma: no cover
@property
def clear_multiplication_count_per_tag(self) -> Dict[str, int]:
"""
Get the number of clear multiplications per tag in the circuit.
"""
return self._property("clear_multiplication_count_per_tag") # pragma: no cover
@property
def clear_multiplication_count_per_tag_per_parameter(self) -> Dict[str, Dict[Parameter, int]]:
"""
Get the number of clear multiplications per tag per parameter in the circuit.
"""
return self._property(
"clear_multiplication_count_per_tag_per_parameter"
) # pragma: no cover
# Encrypted Negation Statistics
@property
def encrypted_negation_count(self) -> int:
"""
Get the number of encrypted negations in the circuit.
"""
return self._property("encrypted_negation_count") # pragma: no cover
@property
def encrypted_negation_count_per_parameter(self) -> Dict[Parameter, int]:
"""
Get the number of encrypted negations per parameter in the circuit.
"""
return self._property("encrypted_negation_count_per_parameter") # pragma: no cover
@property
def encrypted_negation_count_per_tag(self) -> Dict[str, int]:
"""
Get the number of encrypted negations per tag in the circuit.
"""
return self._property("encrypted_negation_count_per_tag") # pragma: no cover
@property
def encrypted_negation_count_per_tag_per_parameter(self) -> Dict[str, Dict[Parameter, int]]:
"""
Get the number of encrypted negations per tag per parameter in the circuit.
"""
return self._property("encrypted_negation_count_per_tag_per_parameter") # pragma: no cover
# All Statistics
@property
def statistics(self) -> Dict:
"""
Get all statistics of the circuit.
"""
return self._property("statistics") # pragma: no cover

View File

@@ -485,7 +485,7 @@ class Compiler:
)
columns = 0
if show_graph or show_mlir or show_optimizer:
if show_graph or show_mlir or show_optimizer or show_statistics:
graph = (
self.graph.format()
if self.configuration.verbose or self.configuration.show_graph
@@ -556,8 +556,27 @@ class Compiler:
print("Statistics")
print("-" * columns)
for name, value in circuit.statistics.items():
print(f"{name}: {value}")
def pretty(d, indent=0): # pragma: no cover
if indent > 0:
print("{")
for key, value in d.items():
if isinstance(value, dict) and len(value) == 0:
continue
print(" " * indent + str(key) + ": ", end="")
if isinstance(value, dict):
pretty(value, indent + 1)
else:
print(value)
if indent > 0:
print(" " * (indent - 1) + "}")
pretty(circuit.statistics)
print("-" * columns)
print()

View File

@@ -8,7 +8,7 @@ import json
import shutil
import tempfile
from pathlib import Path
from typing import List, Optional, Tuple, Union
from typing import Dict, List, Optional, Tuple, Union
# mypy: disable-error-code=attr-defined
import concrete.compiler
@@ -23,11 +23,12 @@ from concrete.compiler import (
LibraryCompilationResult,
LibraryLambda,
LibrarySupport,
Parameter,
PublicArguments,
set_compiler_logging,
set_llvm_debug_flag,
)
from mlir._mlir_libs._concretelang._compiler import OptimizerStrategy
from mlir._mlir_libs._concretelang._compiler import KeyType, OptimizerStrategy, PrimitiveOperation
from mlir.ir import Module as MlirModule
from ..internal.utils import assert_that
@@ -435,66 +436,333 @@ class Server:
"""
return self._compilation_feedback.complexity
@property
def total_pbs_count(self) -> int:
"""
Get the total number of programmable bootstraps in the compiled program.
"""
return self._compilation_feedback.total_pbs_count
# Programmable Bootstrap Statistics
@property
def total_ks_count(self) -> int:
def programmable_bootstrap_count(self) -> int:
"""
Get the total number of key switches in the compiled program.
Get the number of programmable bootstraps in the compiled program.
"""
return self._compilation_feedback.total_ks_count
return self._compilation_feedback.count(
operations={PrimitiveOperation.PBS, PrimitiveOperation.WOP_PBS},
)
@property
def total_clear_addition_count(self) -> int:
def programmable_bootstrap_count_per_parameter(self) -> Dict[Parameter, int]:
"""
Get the total number of clear additions in the compiled program.
Get the number of programmable bootstraps per parameter in the compiled program.
"""
return self._compilation_feedback.total_clear_addition_count
return self._compilation_feedback.count_per_parameter(
operations={PrimitiveOperation.PBS, PrimitiveOperation.WOP_PBS},
key_types={KeyType.BOOTSTRAP},
client_parameters=self.client_specs.client_parameters,
)
@property
def total_encrypted_addition_count(self) -> int:
def programmable_bootstrap_count_per_tag(self) -> Dict[str, int]:
"""
Get the total number of encrypted additions in the compiled program.
Get the number of programmable bootstraps per tag in the compiled program.
"""
return self._compilation_feedback.total_encrypted_addition_count
return self._compilation_feedback.count_per_tag(
operations={PrimitiveOperation.PBS, PrimitiveOperation.WOP_PBS},
)
@property
def total_clear_multiplication_count(self) -> int:
def programmable_bootstrap_count_per_tag_per_parameter(self) -> Dict[str, Dict[Parameter, int]]:
"""
Get the total number of clear multiplications in the compiled program.
Get the number of programmable bootstraps per tag per parameter in the compiled program.
"""
return self._compilation_feedback.total_clear_multiplication_count
return self._compilation_feedback.count_per_tag_per_parameter(
operations={PrimitiveOperation.PBS, PrimitiveOperation.WOP_PBS},
key_types={KeyType.BOOTSTRAP},
client_parameters=self.client_specs.client_parameters,
)
# Key Switch Statistics
@property
def total_encrypted_negation_count(self) -> int:
def key_switch_count(self) -> int:
"""
Get the total number of encrypted negations in the compiled program.
Get the number of key switches in the compiled program.
"""
return self._compilation_feedback.total_encrypted_negation_count
return self._compilation_feedback.count(
operations={PrimitiveOperation.KEY_SWITCH, PrimitiveOperation.WOP_PBS},
)
@property
def statistics(self) -> dict:
def key_switch_count_per_parameter(self) -> Dict[Parameter, int]:
"""
Get all program statistics in a dict.
Get the number of key switches per parameter in the compiled program.
"""
return {
"size_of_secret_keys": self.size_of_secret_keys,
"size_of_bootstrap_keys": self.size_of_bootstrap_keys,
"size_of_keyswitch_keys": self.size_of_keyswitch_keys,
"size_of_inputs": self.size_of_inputs,
"size_of_outputs": self.size_of_outputs,
"p_error": self.p_error,
"global_p_error": self.global_p_error,
"complexity": self.complexity,
"total_pbs_count": self.total_pbs_count,
"total_ks_count": self.total_ks_count,
"total_clear_addition_count": self.total_clear_addition_count,
"total_encrypted_addition_count": self.total_encrypted_addition_count,
"total_clear_multiplication_count": self.total_clear_multiplication_count,
"total_encrypted_negation_count": self.total_encrypted_negation_count,
}
return self._compilation_feedback.count_per_parameter(
operations={PrimitiveOperation.KEY_SWITCH, PrimitiveOperation.WOP_PBS},
key_types={KeyType.KEY_SWITCH},
client_parameters=self.client_specs.client_parameters,
)
@property
def key_switch_count_per_tag(self) -> Dict[str, int]:
"""
Get the number of key switches per tag in the compiled program.
"""
return self._compilation_feedback.count_per_tag(
operations={PrimitiveOperation.KEY_SWITCH, PrimitiveOperation.WOP_PBS},
)
@property
def key_switch_count_per_tag_per_parameter(self) -> Dict[str, Dict[Parameter, int]]:
"""
Get the number of key switches per tag per parameter in the compiled program.
"""
return self._compilation_feedback.count_per_tag_per_parameter(
operations={PrimitiveOperation.KEY_SWITCH, PrimitiveOperation.WOP_PBS},
key_types={KeyType.KEY_SWITCH},
client_parameters=self.client_specs.client_parameters,
)
# Packing Key Switch Statistics
@property
def packing_key_switch_count(self) -> int:
"""
Get the number of packing key switches in the compiled program.
"""
return self._compilation_feedback.count(operations={PrimitiveOperation.WOP_PBS})
@property
def packing_key_switch_count_per_parameter(self) -> Dict[Parameter, int]:
"""
Get the number of packing key switches per parameter in the compiled program.
"""
return self._compilation_feedback.count_per_parameter(
operations={PrimitiveOperation.WOP_PBS},
key_types={KeyType.PACKING_KEY_SWITCH},
client_parameters=self.client_specs.client_parameters,
)
@property
def packing_key_switch_count_per_tag(self) -> Dict[str, int]:
"""
Get the number of packing key switches per tag in the compiled program.
"""
return self._compilation_feedback.count_per_tag(operations={PrimitiveOperation.WOP_PBS})
@property
def packing_key_switch_count_per_tag_per_parameter(self) -> Dict[str, Dict[Parameter, int]]:
"""
Get the number of packing key switches per tag per parameter in the compiled program.
"""
return self._compilation_feedback.count_per_tag_per_parameter(
operations={PrimitiveOperation.WOP_PBS},
key_types={KeyType.PACKING_KEY_SWITCH},
client_parameters=self.client_specs.client_parameters,
)
# Clear Addition Statistics
@property
def clear_addition_count(self) -> int:
"""
Get the number of clear additions in the compiled program.
"""
return self._compilation_feedback.count(operations={PrimitiveOperation.CLEAR_ADDITION})
@property
def clear_addition_count_per_parameter(self) -> Dict[Parameter, int]:
"""
Get the number of clear additions per parameter in the compiled program.
"""
return self._compilation_feedback.count_per_parameter(
operations={PrimitiveOperation.CLEAR_ADDITION},
key_types={KeyType.SECRET},
client_parameters=self.client_specs.client_parameters,
)
@property
def clear_addition_count_per_tag(self) -> Dict[str, int]:
"""
Get the number of clear additions per tag in the compiled program.
"""
return self._compilation_feedback.count_per_tag(
operations={PrimitiveOperation.CLEAR_ADDITION},
)
@property
def clear_addition_count_per_tag_per_parameter(self) -> Dict[str, Dict[Parameter, int]]:
"""
Get the number of clear additions per tag per parameter in the compiled program.
"""
return self._compilation_feedback.count_per_tag_per_parameter(
operations={PrimitiveOperation.CLEAR_ADDITION},
key_types={KeyType.SECRET},
client_parameters=self.client_specs.client_parameters,
)
# Encrypted Addition Statistics
@property
def encrypted_addition_count(self) -> int:
"""
Get the number of encrypted additions in the compiled program.
"""
return self._compilation_feedback.count(operations={PrimitiveOperation.ENCRYPTED_ADDITION})
@property
def encrypted_addition_count_per_parameter(self) -> Dict[Parameter, int]:
"""
Get the number of encrypted additions per parameter in the compiled program.
"""
return self._compilation_feedback.count_per_parameter(
operations={PrimitiveOperation.ENCRYPTED_ADDITION},
key_types={KeyType.SECRET},
client_parameters=self.client_specs.client_parameters,
)
@property
def encrypted_addition_count_per_tag(self) -> Dict[str, int]:
"""
Get the number of encrypted additions per tag in the compiled program.
"""
return self._compilation_feedback.count_per_tag(
operations={PrimitiveOperation.ENCRYPTED_ADDITION},
)
@property
def encrypted_addition_count_per_tag_per_parameter(self) -> Dict[str, Dict[Parameter, int]]:
"""
Get the number of encrypted additions per tag per parameter in the compiled program.
"""
return self._compilation_feedback.count_per_tag_per_parameter(
operations={PrimitiveOperation.ENCRYPTED_ADDITION},
key_types={KeyType.SECRET},
client_parameters=self.client_specs.client_parameters,
)
# Clear Multiplication Statistics
@property
def clear_multiplication_count(self) -> int:
"""
Get the number of clear multiplications in the compiled program.
"""
return self._compilation_feedback.count(
operations={PrimitiveOperation.CLEAR_MULTIPLICATION},
)
@property
def clear_multiplication_count_per_parameter(self) -> Dict[Parameter, int]:
"""
Get the number of clear multiplications per parameter in the compiled program.
"""
return self._compilation_feedback.count_per_parameter(
operations={PrimitiveOperation.CLEAR_MULTIPLICATION},
key_types={KeyType.SECRET},
client_parameters=self.client_specs.client_parameters,
)
@property
def clear_multiplication_count_per_tag(self) -> Dict[str, int]:
"""
Get the number of clear multiplications per tag in the compiled program.
"""
return self._compilation_feedback.count_per_tag(
operations={PrimitiveOperation.CLEAR_MULTIPLICATION},
)
@property
def clear_multiplication_count_per_tag_per_parameter(self) -> Dict[str, Dict[Parameter, int]]:
"""
Get the number of clear multiplications per tag per parameter in the compiled program.
"""
return self._compilation_feedback.count_per_tag_per_parameter(
operations={PrimitiveOperation.CLEAR_MULTIPLICATION},
key_types={KeyType.SECRET},
client_parameters=self.client_specs.client_parameters,
)
# Encrypted Negation Statistics
@property
def encrypted_negation_count(self) -> int:
"""
Get the number of encrypted negations in the compiled program.
"""
return self._compilation_feedback.count(operations={PrimitiveOperation.ENCRYPTED_NEGATION})
@property
def encrypted_negation_count_per_parameter(self) -> Dict[Parameter, int]:
"""
Get the number of encrypted negations per parameter in the compiled program.
"""
return self._compilation_feedback.count_per_parameter(
operations={PrimitiveOperation.ENCRYPTED_NEGATION},
key_types={KeyType.SECRET},
client_parameters=self.client_specs.client_parameters,
)
@property
def encrypted_negation_count_per_tag(self) -> Dict[str, int]:
"""
Get the number of encrypted negations per tag in the compiled program.
"""
return self._compilation_feedback.count_per_tag(
operations={PrimitiveOperation.ENCRYPTED_NEGATION},
)
@property
def encrypted_negation_count_per_tag_per_parameter(self) -> Dict[str, Dict[Parameter, int]]:
"""
Get the number of encrypted negations per tag per parameter in the compiled program.
"""
return self._compilation_feedback.count_per_tag_per_parameter(
operations={PrimitiveOperation.ENCRYPTED_NEGATION},
key_types={KeyType.SECRET},
client_parameters=self.client_specs.client_parameters,
)
# All Statistics
@property
def statistics(self) -> Dict:
"""
Get all statistics of the compiled program.
"""
attributes = [
"size_of_secret_keys",
"size_of_bootstrap_keys",
"size_of_keyswitch_keys",
"size_of_inputs",
"size_of_outputs",
"p_error",
"global_p_error",
"complexity",
"programmable_bootstrap_count",
"programmable_bootstrap_count_per_parameter",
"programmable_bootstrap_count_per_tag",
"programmable_bootstrap_count_per_tag_per_parameter",
"key_switch_count",
"key_switch_count_per_parameter",
"key_switch_count_per_tag",
"key_switch_count_per_tag_per_parameter",
"packing_key_switch_count",
"packing_key_switch_count_per_parameter",
"packing_key_switch_count_per_tag",
"packing_key_switch_count_per_tag_per_parameter",
"clear_addition_count",
"clear_addition_count_per_parameter",
"clear_addition_count_per_tag",
"clear_addition_count_per_tag_per_parameter",
"encrypted_addition_count",
"encrypted_addition_count_per_parameter",
"encrypted_addition_count_per_tag",
"encrypted_addition_count_per_tag_per_parameter",
"clear_multiplication_count",
"clear_multiplication_count_per_parameter",
"clear_multiplication_count_per_tag",
"clear_multiplication_count_per_tag_per_parameter",
"encrypted_negation_count",
"encrypted_negation_count_per_parameter",
"encrypted_negation_count_per_tag",
"encrypted_negation_count_per_tag_per_parameter",
]
return {attribute: getattr(self, attribute) for attribute in attributes}