SimiLie
Loading...
Searching...
No Matches
generate_cpp_hamiltonian.py
1#!/usr/bin/env python3
2# SPDX-FileCopyrightText: 2026 Baptiste Legouix
3# SPDX-License-Identifier: AGPL-3.0-or-later
4
5from __future__ import annotations
6
7from dataclasses import dataclass
8from pathlib import Path
9
10from sympy import Derivative, Subs, Symbol, diff, solve, symbols
11from sympy.printing.codeprinter import cxxcode
12
13
14@dataclass(frozen=True)
16 value_expression: str
17 derivative_expressions: dict[int, str]
18
19
20@dataclass(frozen=True)
22 namespace: str
23 struct_name: str
24 parameters: list[str]
25 hamiltonian: object
26 variables: list[object]
27 includes: list[str] | None = None
28 moments_computer: str | None = None
29 template_parameters: list[str] | None = None
30 parameter_types: dict[str, str] | None = None
31 parameter_value_expressions: dict[str, str] | None = None
32 symbolic_functions: dict[str, SymbolicFunctionDefinition] | None = None
33 moments_object_component_expression: str | None = None
34 moments_object_norm2_expression: str | None = None
35 generate_moments_jacobian: bool = False
36 namespace_preamble: str = ""
37 namespace_epilogue: str = ""
38 is_linear: bool = False
39
40
41def _flatten_variable_entries(entries: list[object]) -> list[object]:
42 flattened: list[object] = []
43 for entry in entries:
44 if isinstance(entry, (list, tuple)):
45 flattened.extend(_flatten_variable_entries(list(entry)))
46 else:
47 flattened.append(entry)
48 return flattened
49
50
51def _entry_symbols(entry: object) -> list[object]:
52 if isinstance(entry, (list, tuple)):
53 return _flatten_variable_entries(list(entry))
54 return [entry]
55
56
57def _entry_name(entry: object) -> str:
58 symbols_ = _entry_symbols(entry)
59 if len(symbols_) == 1:
60 return str(symbols_[0])
61 first_name = str(symbols_[0])
62 prefix = first_name.rstrip("0123456789")
63 return prefix if prefix else first_name
64
65
66def _replace_symbols(expression: str, replacements: dict[str, str]) -> str:
67 for source, target in sorted(
68 replacements.items(), key=lambda replacement: len(replacement[0]), reverse=True
69 ):
70 expression = expression.replace(source, target)
71 return expression
72
73
75 expression,
76 replacements: dict[str, str],
77 symbolic_functions: dict[str, SymbolicFunctionDefinition] | None = None,
78 expression_replacements: dict[object, str] | None = None,
79) -> str:
80 symbolic_functions = symbolic_functions or {}
81 expression_replacements = expression_replacements or {}
82 placeholder_replacements: dict[str, str] = {}
83
84 def render_subexpression(subexpression) -> str:
85 for source_expression, target_expression in expression_replacements.items():
86 if subexpression == source_expression:
87 return target_expression
89 subexpression,
90 replacements,
91 symbolic_functions,
92 expression_replacements,
93 )
94
95 def placeholder(rendered_expression: str) -> Symbol:
96 symbol = Symbol(f"__similie_symbolic_function_{len(placeholder_replacements)}")
97 placeholder_replacements[str(symbol)] = rendered_expression
98 return symbol
99
100 for function_name, function_definition in symbolic_functions.items():
101 expression = expression.replace(
102 lambda node, name=function_name: (
103 isinstance(node, Subs)
104 and isinstance(node.expr, Derivative)
105 and node.expr.expr.func.__name__ == name
106 ),
107 lambda node, definition=function_definition: placeholder(
108 definition.derivative_expressions[node.expr.derivative_count].format(
109 argument=render_subexpression(node.point[0])
110 )
111 ),
112 )
113 expression = expression.replace(
114 lambda node, name=function_name: node.func.__name__ == name,
115 lambda node, definition=function_definition: placeholder(
116 definition.value_expression.format(
117 argument=render_subexpression(node.args[0])
118 )
119 ),
120 )
121
122 for source_expression, target_expression in expression_replacements.items():
123 expression = expression.replace(
124 lambda node, source=source_expression: node == source,
125 lambda node, target=target_expression: placeholder(target),
126 )
127
128 return _replace_symbols(
129 _replace_symbols(cxxcode(expression), replacements),
130 placeholder_replacements,
131 )
132
133
134def _render_members(parameters: list[tuple[str, str, bool, str]]) -> str:
135 return "\n".join(
136 f" {'const ' if is_const else ''}{type_name} {name};"
137 for name, _, is_const, type_name in parameters
138 )
139
140
142 struct_name: str, parameters: list[tuple[str, str, bool, str]]
143) -> str:
144 params = ",\n ".join(
145 f"{type_name} {constructor_name}_"
146 for _, constructor_name, _, type_name in parameters
147 )
148 return f" KOKKOS_FUNCTION constexpr {struct_name}(\n {params})"
149
150
152 parameters: list[tuple[str, str, bool, str]],
153) -> str:
154 return ", ".join(
155 f"{name}({constructor_name}_)" for name, constructor_name, _, _ in parameters
156 )
157
158
160 symbol_name: str,
161 expression,
162 replacements: dict[str, str],
163 component_argument_name: str,
164 symbolic_functions: dict[str, SymbolicFunctionDefinition] | None = None,
165 expression_replacements: dict[object, str] | None = None,
166) -> str:
168 expression,
169 {**replacements, symbol_name: component_argument_name},
170 symbolic_functions,
171 expression_replacements,
172 )
173
174
175def _all_same(expressions: list[str]) -> bool:
176 return all(expression == expressions[0] for expression in expressions)
177
178
179def _has_temporal_index(template_parameters: list[str] | None) -> bool:
180 return (
181 template_parameters is not None and "class TemporalIndex" in template_parameters
182 )
183
184
186 method_name: str,
187 argument_prefix: str,
188 symbols_: list[str],
189 expressions: list,
190 replacements: dict[str, str],
191 template_parameters: list[str] | None,
192 symbolic_functions: dict[str, SymbolicFunctionDefinition] | None = None,
193 expression_replacements: dict[object, str] | None = None,
194) -> str:
195 component_expressions = [
197 symbol_name,
198 expression,
199 replacements,
200 argument_prefix,
201 symbolic_functions,
202 expression_replacements,
203 )
204 for symbol_name, expression in zip(symbols_, expressions, strict=True)
205 ]
206 if _all_same(component_expressions):
207 body = f" return {component_expressions[0]};"
208 elif _has_temporal_index(template_parameters):
209 body = f""" if constexpr (std::is_same_v<Index, TemporalIndex>) {{
210 return {component_expressions[0]};
211 }} else {{
212 return {component_expressions[1]};
213 }}"""
214 else:
215 raise ValueError(
216 f"{method_name} cannot be generated from a scalar component without tag-specific "
217 "expressions"
218 )
219
220 return f"""
221 template <class Index>
222 KOKKOS_FUNCTION constexpr double {method_name}(double {argument_prefix}) const
223 {{
224{body}
225 }}
226"""
227
228
230 method_name: str,
231 argument_prefix: str,
232 symbols_: list[str],
233 expressions: list,
234 replacements: dict[str, str],
235 template_parameters: list[str] | None,
236 symbolic_functions: dict[str, SymbolicFunctionDefinition] | None = None,
237 expression_replacements: dict[object, str] | None = None,
238) -> str:
239 component_expressions = [
241 symbol_name,
242 expression,
243 replacements,
244 argument_prefix,
245 symbolic_functions,
246 expression_replacements,
247 )
248 for symbol_name, expression in zip(symbols_, expressions, strict=True)
249 ]
250 if _all_same(component_expressions):
251 body = f" return {component_expressions[0]};"
252 elif _has_temporal_index(template_parameters):
253 body = f""" if constexpr (std::is_same_v<Index, TemporalIndex>) {{
254 return {component_expressions[0]};
255 }} else {{
256 return {component_expressions[1]};
257 }}"""
258 else:
259 raise ValueError(
260 f"{method_name} cannot be generated from a scalar component without tag-specific "
261 "expressions"
262 )
263
264 return f"""
265 template <class Index, class Elem>
266 KOKKOS_FUNCTION constexpr double {method_name}(double {argument_prefix}, Elem elem) const
267 {{
268{body}
269 }}
270"""
271
272
274 method_name: str,
275 symbols_: list[str],
276 expressions: list,
277 replacements: dict[str, str],
278 symbolic_functions: dict[str, SymbolicFunctionDefinition] | None = None,
279) -> str:
280 differentiated_expressions = [
281 diff(expression, symbols(symbol_name))
282 for symbol_name, expression in zip(symbols_, expressions, strict=True)
283 ]
284 generalized_expressions = [
285 _render_cxx_expression(expression, replacements, symbolic_functions)
286 for expression in differentiated_expressions
287 ]
288 if _all_same(generalized_expressions):
289 body = f""" auto value = MomentsComputer::template forward_value<Index>(elem);
290 value *= {generalized_expressions[0]};
291 return value;"""
292 else:
293 raise ValueError(
294 f"{method_name} cannot be generated without tag-specific nonlocal expressions"
295 )
296
297 return f"""
298 template <class Index, class Elem>
299 KOKKOS_FUNCTION constexpr auto {method_name}(Elem elem) const
300 {{
301{body}
302 }}
303"""
304
305
307 symbols_: list[str],
308 expressions: list,
309 replacements: dict[str, str],
310 symbolic_functions: dict[str, SymbolicFunctionDefinition],
311 expression_replacements: dict[object, str],
312 component_expression: str,
313) -> str:
314 component_expressions = [
316 symbol_name,
317 expression,
318 replacements,
319 component_expression.format(index="Index", moments="moments"),
320 symbolic_functions,
321 expression_replacements,
322 )
323 for symbol_name, expression in zip(symbols_, expressions, strict=True)
324 ]
325 if not _all_same(component_expressions):
326 raise ValueError(
327 "dhamiltonian_dmoments object method cannot be generated without "
328 "tag-independent component expressions"
329 )
330
331 return f"""
332 template <class Index, class Moments, class Elem>
333 KOKKOS_FUNCTION constexpr double dhamiltonian_dmoments(Moments moments, Elem elem) const
334 {{
335 static_cast<void>(elem);
336 return {component_expressions[0]};
337 }}
338
339 template <class Index, class Moments, class Elem>
340 KOKKOS_FUNCTION constexpr double dpotential_dt(Moments moments, Elem elem) const
341 {{
342 return dhamiltonian_dmoments<Index>(moments, elem);
343 }}
344"""
345
346
348 symbols_: list[str],
349 hamiltonian,
350 replacements: dict[str, str],
351 symbolic_functions: dict[str, SymbolicFunctionDefinition],
352 expression_replacements: dict[object, str],
353 component_expression: str,
354) -> str:
355 row_component = component_expression.format(index="RowIndex", moments="moments")
356 column_component = component_expression.format(
357 index="ColumnIndex", moments="moments"
358 )
359 diagonal_expressions = [
361 diff(diff(hamiltonian, symbol), symbol),
362 {**replacements, str(symbol): row_component},
363 symbolic_functions,
364 expression_replacements,
365 )
366 for symbol in symbols_
367 ]
368 off_diagonal_expressions = [
370 diff(diff(hamiltonian, symbols_[0]), symbol),
371 {
372 **replacements,
373 str(symbols_[0]): row_component,
374 str(symbol): column_component,
375 },
376 symbolic_functions,
377 expression_replacements,
378 )
379 for symbol in symbols_[1:]
380 ]
381 if not _all_same(diagonal_expressions) or not _all_same(off_diagonal_expressions):
382 raise ValueError(
383 "moments jacobian cannot be generated without tag-independent expressions"
384 )
385
386 return f"""
387 template <class RowIndex, class ColumnIndex, class Moments, class Elem>
388 KOKKOS_FUNCTION constexpr double jacobian(Moments moments, Elem elem) const
389 {{
390 static_cast<void>(elem);
391 if constexpr (std::is_same_v<RowIndex, ColumnIndex>) {{
392 return {diagonal_expressions[0]};
393 }} else {{
394 return {off_diagonal_expressions[0]};
395 }}
396 }}
397"""
398
399
401 output_path: Path,
402 namespace: str,
403 struct_name: str,
404 parameters: list[tuple[str, str, bool, str]],
405 hamiltonian,
406 variable_entries: list[dict[str, object]],
407 includes: list[str] | None = None,
408 moments_computer: str | None = None,
409 inverse_symbols: list[str] | None = None,
410 inverse_expressions: list | None = None,
411 template_parameters: list[str] | None = None,
412 parameter_value_expressions: dict[str, str] | None = None,
413 definition: HamiltonianDefinition | None = None,
414) -> None:
415 output_path.parent.mkdir(parents=True, exist_ok=True)
416
417 parameter_value_expressions = parameter_value_expressions or {}
418 symbolic_functions = (
419 {} if definition is None else (definition.symbolic_functions or {})
420 )
421 parameter_replacements = {}
422 for member_name, constructor_name, _, _ in parameters:
423 parameter_replacements[constructor_name] = parameter_value_expressions.get(
424 constructor_name, member_name
425 )
426 h_replacements = dict(parameter_replacements)
427 requires_elem = any(
428 "elem" in replacement for replacement in parameter_replacements.values()
429 )
430 argument_signature_parts: list[str] = []
431 arguments_call_parts: list[str] = []
432 for entry in variable_entries:
433 entry_name = entry["name"]
434 entry_symbols = entry["symbols"]
435 if len(entry_symbols) == 1:
436 argument_signature_parts.append(f"double {entry_name}")
437 arguments_call_parts.append(entry_name)
438 h_replacements[str(entry_symbols[0])] = entry_name
439 else:
440 argument_signature_parts.append(
441 f"std::span<double const, {len(entry_symbols)}> {entry_name}"
442 )
443 arguments_call_parts.append(entry_name)
444 for i, symbol in enumerate(entry_symbols):
445 h_replacements[str(symbol)] = f"{entry_name}[{i}]"
446
447 if requires_elem:
448 h_signature = (
449 f" template <class Elem>\n"
450 f" KOKKOS_FUNCTION constexpr double hamiltonian({', '.join(argument_signature_parts)}, Elem elem) const"
451 )
452 else:
453 h_signature = f" KOKKOS_FUNCTION constexpr double hamiltonian({', '.join(argument_signature_parts)}) const"
454
455 potential_entry = variable_entries[0]
456 moments_entry = variable_entries[1]
457 potential_symbols = potential_entry["symbols"]
458 moments_symbols = moments_entry["symbols"]
459
460 potential_replacements = dict(h_replacements)
461 moments_replacements = dict(parameter_replacements)
462
463 potential_derivative_expressions = [
464 diff(hamiltonian, symbol) for symbol in potential_symbols
465 ]
466 moments_derivative_expressions = [
467 diff(hamiltonian, symbol) for symbol in moments_symbols
468 ]
469
470 potential_argument_entries = [potential_entry, *variable_entries[2:]]
471 potential_signature_parts: list[str] = []
472 for entry in potential_argument_entries:
473 entry_name = entry["name"]
474 entry_symbols = entry["symbols"]
475 if len(entry_symbols) == 1:
476 potential_signature_parts.append(f"double {entry_name}")
477 else:
478 potential_signature_parts.append(
479 f"std::span<double const, {len(entry_symbols)}> {entry_name}"
480 )
481
482 if len(potential_symbols) == 1:
483 potential_method_signature = ", ".join(potential_signature_parts)
484 if requires_elem:
485 potential_method = f"""
486 template <class Elem>
487 KOKKOS_FUNCTION constexpr double dhamiltonian_dpotential({potential_method_signature}, Elem elem) const
488 {{
489 return {_render_cxx_expression(potential_derivative_expressions[0], potential_replacements, symbolic_functions)};
490 }}
491"""
492 else:
493 potential_method = f"""
494 KOKKOS_FUNCTION constexpr double dhamiltonian_dpotential({potential_method_signature}) const
495 {{
496 return {_render_cxx_expression(potential_derivative_expressions[0], potential_replacements, symbolic_functions)};
497 }}
498"""
499 else:
500 potential_method = ""
501
502 inverse_methods = ""
503 if inverse_symbols is not None and inverse_expressions is not None:
504 inverse_methods = _render_indexed_method(
505 "moments",
506 "dpotential_dx",
507 inverse_symbols,
508 inverse_expressions,
509 potential_replacements,
510 template_parameters,
511 symbolic_functions,
512 )
513
514 use_moments_object = (
515 len(moments_symbols) > 1
516 and definition is not None
517 and definition.moments_object_component_expression is not None
518 )
519
520 if not use_moments_object and (
521 len(moments_symbols) == 1 or moments_computer is None
522 ):
523 moments_method = _render_indexed_method(
524 "dhamiltonian_dmoments",
525 "moments",
526 [str(symbol) for symbol in moments_symbols],
527 moments_derivative_expressions,
528 moments_replacements,
529 template_parameters,
530 symbolic_functions,
531 )
532 else:
533 moments_method = ""
534 generic_moments_method = ""
535 if len(moments_symbols) > 1 and moments_computer is not None:
536 generic_moments_replacements = {
537 **parameter_replacements,
538 **{str(symbol): "moments" for symbol in moments_symbols},
539 }
540 if requires_elem:
541 generic_moments_method = _render_indexed_elem_method(
542 "dhamiltonian_dmoments",
543 "moments",
544 [str(symbol) for symbol in moments_symbols],
545 moments_derivative_expressions,
546 generic_moments_replacements,
547 template_parameters,
548 symbolic_functions,
549 )
550 else:
551 generic_moments_method = _render_indexed_method(
552 "dhamiltonian_dmoments",
553 "moments",
554 [str(symbol) for symbol in moments_symbols],
555 moments_derivative_expressions,
556 generic_moments_replacements,
557 template_parameters,
558 symbolic_functions,
559 )
560
561 moments_object_method = ""
562 moments_jacobian_method = ""
563 if use_moments_object:
564 object_expression_replacements = {}
565 if definition.moments_object_norm2_expression is not None:
566 object_expression_replacements[
567 sum(symbol**2 for symbol in moments_symbols)
568 ] = definition.moments_object_norm2_expression.format(moments="moments")
569 moments_object_method = _render_moments_object_method(
570 [str(symbol) for symbol in moments_symbols],
571 moments_derivative_expressions,
572 moments_replacements,
573 symbolic_functions,
574 object_expression_replacements,
575 definition.moments_object_component_expression,
576 )
577 if definition.generate_moments_jacobian:
578 moments_jacobian_method = _render_moments_object_jacobian_method(
579 moments_symbols,
580 hamiltonian,
581 moments_replacements,
582 symbolic_functions,
583 object_expression_replacements,
584 definition.moments_object_component_expression,
585 )
586
587 nonlocal_value_methods = ""
588 if moments_computer is not None:
589 nonlocal_value_methods = _render_indexed_nonlocal_value_method(
590 "dhamiltonian_dmoments_value",
591 [str(symbol) for symbol in moments_symbols],
592 moments_derivative_expressions,
593 moments_replacements,
594 symbolic_functions,
595 )
596 rendered_includes = ""
597 if includes:
598 rendered_includes += "".join(f"#include {header}\n" for header in includes)
599
600 rendered_moments_computer = ""
601 if moments_computer is not None:
602 rendered_moments_computer = (
603 f" using MomentsComputer = {moments_computer};\n\n"
604 )
605 template_prefix = ""
606 if template_parameters:
607 template_prefix = "template <" + ", ".join(template_parameters) + ">\n"
608
609 is_linear = False if definition is None else definition.is_linear
610
611 output_path.write_text(
612 f"""\
613// SPDX-FileCopyrightText: 2026 Baptiste Legouix
614// SPDX-License-Identifier: AGPL-3.0-or-later
615
616#pragma once
617
618#include <array>
619#include <cmath>
620#include <cstddef>
621#include <Kokkos_Core.hpp>
622#include <span>
623#include <type_traits>
624#include <utility>
625{rendered_includes}
626
627namespace {namespace} {{
628
629{"" if definition is None else definition.namespace_preamble}
630
631{template_prefix}struct {struct_name} {{
632 static constexpr std::size_t N = {len(moments_symbols)};
633 static constexpr bool IS_LINEAR = {"true" if is_linear else "false"};
634
635{rendered_moments_computer}\
636{_render_members(parameters)}
637
638{_render_constructor_signature(struct_name, parameters)}
639 : {_render_constructor_initializers(parameters)} {{}}
640
641{h_signature}
642 {{
643 return {_render_cxx_expression(hamiltonian, h_replacements, symbolic_functions)};
644 }}
645{potential_method}{moments_method}{generic_moments_method}{moments_object_method}{moments_jacobian_method}{nonlocal_value_methods}
646{inverse_methods}}};
647
648{"" if definition is None else definition.namespace_epilogue}
649}} // namespace {namespace}
650"""
651 )
652
653
654def generate_cpp_hamiltonian(functor_class, output_path: Path, *args, **kwargs) -> None:
655 definition = functor_class.__call__(*args, **kwargs)
656 parameter_types = definition.parameter_types or {}
657 parameter_tuples = [
658 (f"m_{name}", name, True, parameter_types.get(name, "double"))
659 for name in definition.parameters
660 ]
661
662 inverse_symbols = None
663 inverse_expressions = None
664 variable_entries = [
665 {"name": _entry_name(entry), "symbols": _entry_symbols(entry)}
666 for entry in definition.variables
667 ]
668
669 flat_variables = _flatten_variable_entries(list(definition.variables))
670 if variable_entries[0]["name"] == "phi":
671 dphi_dx_symbols = symbols(f"dphi_dx0:{len(variable_entries[1]['symbols'])}")
672 inverse_solution = solve(
673 [
674 dphi_dx_symbols[i]
675 - diff(definition.hamiltonian, variable_entries[1]["symbols"][i])
676 for i in range(len(variable_entries[1]["symbols"]))
677 ],
678 variable_entries[1]["symbols"],
679 dict=True,
680 )
681 if inverse_solution:
682 inverse_symbols = [str(symbol) for symbol in dphi_dx_symbols]
683 inverse_expressions = [
684 inverse_solution[0][variable_entries[1]["symbols"][i]]
685 for i in range(len(variable_entries[1]["symbols"]))
686 ]
687
689 output_path=output_path,
690 namespace=definition.namespace,
691 struct_name=definition.struct_name,
692 parameters=parameter_tuples,
693 hamiltonian=definition.hamiltonian,
694 variable_entries=variable_entries,
695 includes=definition.includes,
696 moments_computer=definition.moments_computer,
697 inverse_symbols=inverse_symbols,
698 inverse_expressions=inverse_expressions,
699 template_parameters=definition.template_parameters,
700 parameter_value_expressions=definition.parameter_value_expressions,
701 definition=definition,
702 )
list[object] _entry_symbols(object entry)
str _render_cxx_expression(expression, dict[str, str] replacements, dict[str, SymbolicFunctionDefinition]|None symbolic_functions=None, dict[object, str]|None expression_replacements=None)
str _generalize_component_expression(str symbol_name, expression, dict[str, str] replacements, str component_argument_name, dict[str, SymbolicFunctionDefinition]|None symbolic_functions=None, dict[object, str]|None expression_replacements=None)
str _render_indexed_elem_method(str method_name, str argument_prefix, list[str] symbols_, list expressions, dict[str, str] replacements, list[str]|None template_parameters, dict[str, SymbolicFunctionDefinition]|None symbolic_functions=None, dict[object, str]|None expression_replacements=None)
str _render_moments_object_method(list[str] symbols_, list expressions, dict[str, str] replacements, dict[str, SymbolicFunctionDefinition] symbolic_functions, dict[object, str] expression_replacements, str component_expression)
str _render_constructor_initializers(list[tuple[str, str, bool, str]] parameters)
str _render_constructor_signature(str struct_name, list[tuple[str, str, bool, str]] parameters)
str _replace_symbols(str expression, dict[str, str] replacements)
str _render_moments_object_jacobian_method(list[str] symbols_, hamiltonian, dict[str, str] replacements, dict[str, SymbolicFunctionDefinition] symbolic_functions, dict[object, str] expression_replacements, str component_expression)
bool _all_same(list[str] expressions)
str _render_members(list[tuple[str, str, bool, str]] parameters)
list[object] _flatten_variable_entries(list[object] entries)
str _render_indexed_method(str method_name, str argument_prefix, list[str] symbols_, list expressions, dict[str, str] replacements, list[str]|None template_parameters, dict[str, SymbolicFunctionDefinition]|None symbolic_functions=None, dict[object, str]|None expression_replacements=None)
str _render_indexed_nonlocal_value_method(str method_name, list[str] symbols_, list expressions, dict[str, str] replacements, dict[str, SymbolicFunctionDefinition]|None symbolic_functions=None)
bool _has_temporal_index(list[str]|None template_parameters)
None write_cpp_hamiltonian_header(Path output_path, str namespace, str struct_name, list[tuple[str, str, bool, str]] parameters, hamiltonian, list[dict[str, object]] variable_entries, list[str]|None includes=None, str|None moments_computer=None, list[str]|None inverse_symbols=None, list|None inverse_expressions=None, list[str]|None template_parameters=None, dict[str, str]|None parameter_value_expressions=None, HamiltonianDefinition|None definition=None)