Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
118 commits
Select commit Hold shift + click to select a range
01413c9
workaround: ignore gate definitions when reading qasm files for now
joshmtlau Apr 4, 2025
7623a96
lint: explicitly initialize every field of ZXVertexAttrs
joshmtlau Apr 4, 2025
327c379
refactor: remove unimplemented TPar strategy; shorten PRT resyn class…
joshmtlau Apr 4, 2025
0d26093
refactor: move pauli rotation tableau synthesis strategies to dedicat…
joshmtlau Apr 4, 2025
8392eff
refactor: move tableau functionalities to namespace qsyn::tableau
joshmtlau Apr 4, 2025
4133f8a
fix: incorrect ccx/ccy/ccz decomposition
joshmtlau Apr 6, 2025
3f32386
feat: lazy tableau synthesis
joshmtlau Apr 8, 2025
b5a10b7
feat: spider fusion upper limit for CausalFlowOpt to avoid runtime bo…
joshmtlau Apr 8, 2025
0d5317f
✨ Add generalized mst resyn (pmst) strategy
arttr1521 May 19, 2025
0299d94
✨ Complete pmst resyn
arttr1521 May 20, 2025
277c1fc
✨ Complete basic tableau to qcir function
arttr1521 May 21, 2025
1bef990
🎉 Integrate forward and backward for pmst-synth
arttr1521 Jun 2, 2025
70cb78d
🔨 Refactor digraph with stl unorder_map/set
arttr1521 Jun 11, 2025
4f42ba4
🎉 Integrate forward and backward for basic tableau resyn
arttr1521 Jun 12, 2025
1599f2f
🔨 Modify hash_map/set back to dvlab version
arttr1521 Jun 19, 2025
7db652d
🔨 Add stop requested condition
arttr1521 Jun 21, 2025
f017a06
🎉 Add new mode AG to reduce cx count
arttr1521 Jun 22, 2025
ab3a3a3
🎉 Consider stabilizer in parity graph
arttr1521 Jun 27, 2025
084b3b4
🎉 Consider distance to identity
arttr1521 Jun 27, 2025
3319380
Remove timer
arttr1521 Jun 28, 2025
5ee6ed6
🔨 Refine the cost of distance to identity
arttr1521 Jul 7, 2025
a2493fb
:bug: num_qubits
jimmy312495 Sep 26, 2025
f1b34de
:memo: add comments
jimmy312495 Sep 26, 2025
c5a4b2f
:sparkles: change EdgeHash
jimmy312495 Sep 26, 2025
395e451
change ordered_set to unordered_set (slightly faster)
jimmy312495 Sep 26, 2025
bdfa173
Add unordered_set include
jimmy312495 Sep 26, 2025
921d56f
🚧 Reconstruct GeneralizedMST synthesis
arttr1521 Oct 16, 2025
5564bcc
🔨 Remove the unnecessary loggers
arttr1521 Oct 17, 2025
9f4f333
✨ Implement void edge attr of digraph
arttr1521 Dec 3, 2025
9c6b487
:bug: fix compilation error for cli_tab.cpp
joshmtlau Dec 4, 2025
89180d0
:wrench: fix MacOS compilation: removing libfort (poorly managed)
joshmtlau Dec 5, 2025
5eed7fb
:palette: clang-format
joshmtlau Dec 5, 2025
6ef8a56
:heavy-minus: remove libfort from dependency: poorly maintained
joshmtlau Dec 11, 2025
57e64e1
:art: lint
joshmtlau Dec 11, 2025
972c252
Merge pull request #154 from joshmtlau/develop
arttr1521 Dec 12, 2025
1d5c9ed
Merge branch 'develop' into feat/lazy-tableau-synthesis
joshmtlau Dec 22, 2025
a88153b
:art: lint
joshmtlau Dec 29, 2025
c9f68ef
Merge pull request #2 from joshmtlau/feat/lazy-tableau-synthesis
joshmtlau Dec 29, 2025
b7face8
Merge pull request #155 from joshmtlau/develop
arttr1521 Dec 29, 2025
bd081d1
🔧 Replace Digraph with DagPeeler to optimize Dag creation in generali…
arttr1521 Dec 31, 2025
e1d0bd8
🔧 Make lint
arttr1521 Dec 31, 2025
f2284b3
🔧 Update partial_synthesize method to override
arttr1521 Dec 31, 2025
acbdc78
🔧 Refactor Docker entrypoint script for deterministic builds by clean…
arttr1521 Dec 31, 2025
ccceb76
🔧 Enhance Docker entrypoint script to dynamically determine and verif…
arttr1521 Dec 31, 2025
956fec7
Revert "🔧 Update partial_synthesize method to override"
arttr1521 Dec 31, 2025
aa0009d
Merge remote-tracking branch 'remotes/upstream/develop' into feat/uti…
arttr1521 Jan 5, 2026
7972477
🔧 Update partial_synthesize method to include override specifier
arttr1521 Jan 5, 2026
fcfef21
🔧 Optimize edge comparison in Digraph class by iterating over vertice…
arttr1521 Jan 5, 2026
8ed8cf7
:wrench: suppress clang-tidy error messages due to gcc-only flags
joshmtlau Jan 5, 2026
6663fb9
feat: primordial impl of trotterization
joshmtlau Jan 5, 2026
d3cc671
feat: qubit hamiltonian managers
joshmtlau Jan 5, 2026
4fd6763
refactor: use qbham instead of hamiltonian for QubitHamiltonian-relat…
joshmtlau Jan 5, 2026
9a29266
Refactor: move filenames and procedures features to manager level; mo…
joshmtlau Jan 6, 2026
8e9af15
feat: lexicographical sort for qubit hamiltonians
joshmtlau Jan 14, 2026
8f22479
fix:using the --help flags on some messages lead to segfault
joshmtlau Jan 14, 2026
f0c72bd
lint; add abilities to select formatter and linter versions for scrip…
joshmtlau Jan 14, 2026
b06424c
added regession test for this segfault
joshmtlau Jan 14, 2026
df5234d
Fix: Update CMakeLists.txt to conditionally prefer pkg-config for BLA…
joshmtlau Jan 14, 2026
c9dfba6
fix: macos action doesn't download openblas
joshmtlau Jan 14, 2026
9a1ed9f
fix: update macOS workflow to include OpenBLAS paths in environment v…
joshmtlau Jan 14, 2026
24b133e
Merge pull request #157 from joshmtlau/refactor/filenames-and-procedures
Ferayer Jan 15, 2026
a83a8f9
Merge branch 'develop' into feat/util-dag
Ferayer Jan 15, 2026
730e974
Merge pull request #156 from arttr1521/feat/util-dag
Ferayer Jan 15, 2026
2200529
Merge pull request #159 from joshmtlau/bug/help-msgs-leads-to-segfault
Ferayer Jan 15, 2026
5935136
fix: previous refactor missed changes in develop branch
joshmtlau Jan 15, 2026
b47913a
Merge pull request #160 from joshmtlau/refactor/filenames-and-procedures
joshmtlau Jan 15, 2026
34adf6d
Merge branch 'develop' into feat/qubit-hamiltonian
joshmtlau Jan 15, 2026
fbc3683
fix: update manager template syntax
joshmtlau Jan 15, 2026
5e8d81e
Implemented magnitude sort and read hamiltonian from file.
april864 Jan 26, 2026
0ad9db0
feat: trotterization; connect to tableau
joshmtlau Jan 28, 2026
b96267e
fix: Use pkg-config directly for BLAS/LAPACK on Linux
joshmtlau Jan 30, 2026
2afde8b
Merge pull request #2 from paragon-lab/fix/blas-detection-linux
joshmtlau Jan 30, 2026
9587797
Fix BLAS/LAPACK detection and GCC-13 compatibility
joshmtlau Jan 30, 2026
f632ecc
Merge branch 'fix/blas-detection-linux' into develop
joshmtlau Jan 30, 2026
6c90fa3
Merge branch 'develop' into feat/qubit-hamiltonian
joshmtlau Feb 2, 2026
dd79ca0
Merge branch 'feat/qubit-hamiltonian' into my-qubit-hamiltonian
joshmtlau Feb 2, 2026
5e45fa8
Reenable -Werror for compiler warnings in CMake
joshmtlau Feb 2, 2026
7dc03fe
Merge pull request #1 from april864/my-qubit-hamiltonian
joshmtlau Feb 2, 2026
7ae395c
add hook to qiskit transpiler; uv environment for python dependencies
joshmtlau Feb 10, 2026
e17a30e
Implemented JW for hard-coded fermionic hamiltonians
april864 Feb 14, 2026
12ab840
refactor: always invoke python commands through uv
joshmtlau Feb 15, 2026
818577a
Merge pull request #3 from april864/my-qubit-hamiltonian
joshmtlau Feb 18, 2026
838297b
wip: fetching IBMQ device attributes
joshmtlau Feb 18, 2026
789285d
Merge branch 'feat/qubit-hamiltonian' of github.com:paragon-lab/qsyn …
joshmtlau Feb 18, 2026
00ec673
feat: refactored f2q mappings to be more extensible
joshmtlau Feb 19, 2026
d154540
Implemented TernaryTree class
april864 Feb 23, 2026
84850d5
refactor: change device package class names to better reflect functio…
joshmtlau Feb 25, 2026
efec078
refactor: decouple apsp from device
joshmtlau Feb 25, 2026
7e95124
Added basic mapping to fermionic operators, outputs everything as string
april864 Feb 26, 2026
af01039
feat: support per gate type info for Device
joshmtlau Mar 6, 2026
2e82727
refactor: change some type names
joshmtlau Mar 6, 2026
4469056
refactor: more renamings; move adjacency map to device level
joshmtlau Mar 6, 2026
edfd9da
refactor: decouple device reading with DeviceState
joshmtlau Mar 6, 2026
851072e
refactor: decouple device file reading with DeviceState
joshmtlau Mar 6, 2026
a056fc2
refactor: DeviceMgr takes Device instead of DeviceState
joshmtlau Mar 6, 2026
822279c
refactor: move DeviceState and PhysicalQubit to duostra package
joshmtlau Mar 6, 2026
42a6540
feat: readd device printing
joshmtlau Mar 6, 2026
0e51b8d
feat: fetch and read characteristics from IBM device
joshmtlau Mar 7, 2026
ffc5341
feat: customizable floyd-warshall for devices
joshmtlau Mar 7, 2026
1c19d9f
Implemented ternary tree mapping from fermionic to qubit hamiltonian
april864 Mar 7, 2026
e13a884
Removed some comments
april864 Mar 7, 2026
60d1d40
Merge pull request #4 from april864/my-qubit-hamiltonian
joshmtlau Mar 7, 2026
702b1ce
feat: device center finding
joshmtlau Mar 7, 2026
3da75bd
feat: bonsai algorithm (ternary tree refactored)
joshmtlau Mar 8, 2026
a5470ed
wip: ternary tree refactored; bonsai algorithm wip
joshmtlau Mar 8, 2026
2553dda
bug: invalid device error rates for qsyn device file
joshmtlau Mar 8, 2026
1fdabf9
feat: bonsai algorithms that can handle devices with disconnected com…
joshmtlau Mar 8, 2026
0e9a09d
doc: update comment for device analysis
joshmtlau Mar 8, 2026
858b3ca
feat: rudimentary treespilation flow
joshmtlau Mar 10, 2026
11aa84d
Hardware agnostic tree rotations
april864 Mar 10, 2026
23a27eb
CP leaf move
april864 Mar 10, 2026
e05c67e
Optimized ternary tree ftq mapping by pauli weight
april864 Mar 11, 2026
07cc780
commented out a line being flagged :/
april864 Mar 11, 2026
8d44d27
Merge pull request #5 from april864/my-qubit-hamiltonian (Note: code …
joshmtlau Mar 11, 2026
8b0accd
add: evolution time for treespile
joshmtlau Mar 11, 2026
f8b0406
Merge branch 'feat/qubit-hamiltonian' of github.com:paragon-lab/qsyn …
joshmtlau Mar 11, 2026
9431d97
hotfix: trotterize outputting identity pauli strings
joshmtlau Mar 11, 2026
32ef781
Included optimization flag in treespile (sim. annealing to minimize P…
april864 Mar 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Checks: >
-readability-magic-numbers,
-readability-identifier-length,
-readability-avoid-nested-conditional-operator,
-readability-math-missing-parentheses,
WarningsAsErrors: ""
HeaderFilterRegex: ".*"
FormatStyle: none
Expand Down
13 changes: 13 additions & 0 deletions .clangd
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Use the build dir's compile_commands.json (has correct include paths).
CompilationDatabase: build

# Fallback: clangd does not resolve relative paths in Add; use absolute paths.
# Disable fmt consteval for clangd so format-string checks are runtime-only;
# avoids false "not a constant expression" from Clang while the project builds with g++.
CompileFlags:
Add:
- -DFMT_CONSTEVAL=
- -isystem
- /home/zwischen/qsyn/build/_deps/spdlog-src/include
- -isystem
- /home/zwischen/qsyn/build/_deps/fmt-src/include
1 change: 1 addition & 0 deletions .env.default
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
IBMQ_API_KEY=
9 changes: 5 additions & 4 deletions .github/workflows/clang-test-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ jobs:
steps:
- name: Check out Git repository
uses: actions/checkout@v3
- name: Download llvm-clang, parallel and coreutils
- name: Download llvm-clang, parallel, coreutils and OpenBLAS
run: |
brew install llvm@18 parallel coreutils
brew install llvm@18 parallel coreutils openblas
echo 'export PATH="$(brew --prefix)/opt/llvm@18/bin:$PATH"' >> /Users/runner/.bash_profile
echo 'export LDFLAGS="-L$(brew --prefix)/opt/llvm@18/lib"' >> /Users/runner/.bash_profile
echo 'export CPPFLAGS="-I$(brew --prefix)/opt/llvm@18/include"' >> /Users/runner/.bash_profile
echo 'export LDFLAGS="-L$(brew --prefix)/opt/llvm@18/lib -L$(brew --prefix)/opt/openblas/lib $LDFLAGS"' >> /Users/runner/.bash_profile
echo 'export CPPFLAGS="-I$(brew --prefix)/opt/llvm@18/include -I$(brew --prefix)/opt/openblas/include $CPPFLAGS"' >> /Users/runner/.bash_profile
echo 'export CMAKE_PREFIX_PATH="$(brew --prefix)/opt/openblas:$CMAKE_PREFIX_PATH"' >> /Users/runner/.bash_profile

- name: Build and test qsyn
run: |
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ debug/
qsyn*
!src/qsyn*
!src/qsyn/qsyn*
!src/device/qsyn_device_file.cpp

# for work-in-progress things
wip/
Expand All @@ -26,3 +27,8 @@ docs/doc-coverage.info

perf.data
perf.data.old

# python environment
.venv/
.env
__pycache__/
84 changes: 55 additions & 29 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ set(CMAKE_CXX_FLAGS "")
set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")

# Set BLA_VENDOR before project() so it's available during initialization
# On macOS, we need to specify OpenBLAS explicitly
# On Linux, we'll use pkg-config instead (see find_package(BLAS) below)
if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(BLA_VENDOR OpenBLAS CACHE STRING "BLAS vendor to search for")
endif()

include(FetchContent)
include(CheckCXXCompilerFlag)
set(FETCHCONTENT_UPDATES_DISCONNECTED TRUE)
Expand Down Expand Up @@ -84,9 +91,34 @@ include(scripts/cmake/target_link_libraries_system.cmake)

# find_package(OpenMP REQUIRED)

set(BLA_VENDER OpenBLAS)
find_package(BLAS REQUIRED)
find_package(LAPACK REQUIRED)
# Use pkg-config to find BLAS and LAPACK on Linux where it's available and reliable
# On macOS, OpenBLAS from Homebrew doesn't provide pkg-config files, so use FindBLAS instead
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
find_package(PkgConfig)
if(PKG_CONFIG_FOUND)
pkg_check_modules(BLAS IMPORTED_TARGET blas)
pkg_check_modules(LAPACK IMPORTED_TARGET lapack)
if(BLAS_FOUND AND LAPACK_FOUND)
# Set variables expected by the rest of the build
set(BLAS_LIBRARIES PkgConfig::BLAS)
set(LAPACK_LIBRARIES PkgConfig::LAPACK)
endif()
endif()
endif()

# If pkg-config didn't find BLAS/LAPACK (or we're not on Linux), use CMake's find_package
if(NOT BLAS_FOUND OR NOT LAPACK_FOUND)
find_package(BLAS REQUIRED)
find_package(LAPACK REQUIRED)
endif()

# Ensure BLAS_LIBRARIES and LAPACK_LIBRARIES are set
if(NOT BLAS_LIBRARIES)
set(BLAS_LIBRARIES ${BLAS_openblas_LIBRARY})
endif()
if(NOT LAPACK_LIBRARIES)
set(LAPACK_LIBRARIES ${LAPACK_openblas_LIBRARY})
endif()

FetchContent_Declare(
xtl
Expand All @@ -109,26 +141,6 @@ FetchContent_Declare(
GIT_TAG 0.22.0)
FetchContent_MakeAvailable(xtensor-blas)

# --- libfort (patched for new CMake) ---
FetchContent_Declare(
libfort
SYSTEM
GIT_REPOSITORY https://github.com/seleznevae/libfort.git
GIT_TAG v0.4.2
GIT_SHALLOW ON
)

# turn off libfort's own tests
set(FORT_ENABLE_TESTING OFF CACHE INTERNAL "")

FetchContent_GetProperties(libfort)
if(NOT libfort_POPULATED)
FetchContent_Populate(libfort)
endif()
# Always bump (even if already populated from a previous configure)
qsyn_bump_min_cmake("${libfort_SOURCE_DIR}" 3.10)
add_subdirectory("${libfort_SOURCE_DIR}" "${libfort_BINARY_DIR}" SYSTEM)

FetchContent_Declare(
fmt
SYSTEM
Expand Down Expand Up @@ -185,6 +197,7 @@ FetchContent_Declare(
FetchContent_MakeAvailable(cadical)

# --- libabc (patched for new CMake) ---
set(READLINE_FOUND FALSE CACHE BOOL "Disable readline in libabc")
FetchContent_Declare(
libabc
SYSTEM
Expand Down Expand Up @@ -265,7 +278,6 @@ target_link_libraries_system(
xtl
xtensor
xtensor-blas
libfort::fort
fmt::fmt
spdlog::spdlog
Microsoft.GSL::GSL
Expand All @@ -275,7 +287,6 @@ target_link_libraries_system(
target_link_libraries(
${QSYN_LIB_NAME}
PRIVATE
lapack
# OpenMP::OpenMP_CXX
${BLAS_LIBRARIES}
${LAPACK_LIBRARIES})
Expand All @@ -302,6 +313,13 @@ target_compile_options(
target_compile_options(
${CMAKE_PROJECT_NAME} PRIVATE -Wno-missing-field-initializers)

# GCC-specific: disable -Wmaybe-uninitialized (has false positives with templates)
check_cxx_compiler_flag(-Wno-maybe-uninitialized COMPILER_SUPPORTS_WNO_MAYBE_UNINITIALIZED)
if(COMPILER_SUPPORTS_WNO_MAYBE_UNINITIALIZED)
target_compile_options(
${CMAKE_PROJECT_NAME} PRIVATE -Wno-maybe-uninitialized)
endif()

# GCC 12+ is too strict about restrict warnings in std::string operations
# Only apply to GCC, as Clang doesn't support this flag
check_cxx_compiler_flag(-Wno-restrict COMPILER_SUPPORTS_WNO_RESTRICT)
Expand All @@ -327,15 +345,14 @@ target_link_libraries_system(
xtl
xtensor
xtensor-blas
libfort::fort
fmt::fmt
spdlog::spdlog
Microsoft.GSL::GSL
sul::dynamic_bitset)
sul::dynamic_bitset
nlohmann_json::nlohmann_json)
target_link_libraries(
${CMAKE_PROJECT_NAME}
PRIVATE
lapack
# OpenMP::OpenMP_CXX
${BLAS_LIBRARIES}
${LAPACK_LIBRARIES})
Expand Down Expand Up @@ -368,7 +385,8 @@ target_link_libraries_system(
PRIVATE
fmt::fmt
spdlog::spdlog
Microsoft.GSL::GSL)
Microsoft.GSL::GSL
sul::dynamic_bitset)

target_compile_options(
${UNIT_TEST_NAME}
Expand All @@ -381,6 +399,14 @@ target_compile_options(
PRIVATE
-Wno-missing-field-initializers)

# GCC-specific: disable -Wmaybe-uninitialized (has false positives with templates)
if(COMPILER_SUPPORTS_WNO_MAYBE_UNINITIALIZED)
target_compile_options(
${UNIT_TEST_NAME}
PRIVATE
-Wno-maybe-uninitialized)
endif()

# GCC 12+ is too strict about restrict warnings in std::string operations
# Only apply to GCC, as Clang doesn't support this flag
if(COMPILER_SUPPORTS_WNO_RESTRICT)
Expand Down
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,11 @@ test-update:

# run clang-format and clang-tidy on the source code
lint:
./scripts/LINT
@if [ -z "$(ARGS)" ]; then \
./scripts/LINT; \
else \
./scripts/LINT $(ARGS); \
fi
.PHONY: lint

clean:
Expand Down
156 changes: 156 additions & 0 deletions benchmark/fham/convert_fermihedral.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#!/usr/bin/env python3
"""
Convert fermihedral model files to qsyn fermionic Hamiltonian (.fham) format.

Mapping rules:
- Input directory (default): ~/fermihedral/model
- Output directory (default): benchmark/fham
- Each non-empty, non-comment line in a fermihedral file is a single term.
- A term is a list of signed integers, e.g.:

-1 2

Interpretation:
- Sign encodes operator type:
k < 0 → creation operator a_{|k|}^†
k > 0 → annihilation operator a_{|k|}
- Indices are the same in both formats (no off-by-one).
- Coefficient is defaulted to (1, 0) (i.e. 1 + 0j) for every term.

Example:
fermihedral: -1 2
qsyn (.fham): (1, 0) 0^ 1
"""

from __future__ import annotations

import argparse
import pathlib
from typing import Iterable


def parse_line_to_ops(line: str) -> list[tuple[int, bool]]:
"""Parse a single fermihedral term line into (mode, is_creation) ops.

- Skips comments after '#'.
- Returns an empty list if there are no operator tokens.
"""
# Strip comments
line = line.split("#", maxsplit=1)[0].strip()
if not line:
return []

tokens = line.split()
ops: list[tuple[int, bool]] = []
for tok in tokens:
try:
k = int(tok)
except ValueError:
raise ValueError(f"Invalid integer token '{tok}' in line: {line!r}")

is_creation = k < 0
mode = abs(k) # no index shift; 0 is allowed

ops.append((mode, is_creation))
return ops


def convert_file(src_path: pathlib.Path, dst_path: pathlib.Path) -> None:
"""Convert one fermihedral model file to qsyn .fham format."""
lines: list[str] = src_path.read_text(encoding="utf-8").splitlines()

# Some fermihedral model files encode Majorana operators using an "mj"
# token on the first line. We currently do not support Majorana terms, so
# skip converting such files but emit a clear warning.
if lines:
first_tokens = lines[0].split()
if any(tok == "mj" for tok in first_tokens):
print(
f"Warning: skipping {src_path} because it uses Majorana operators "
"(mj), which are not supported yet."
)
return

out_lines: list[str] = []

# Many fermihedral model files start with a non-operator header line
# (e.g., "electronic 10 ac"). We skip the first line unconditionally.
for idx, line in enumerate(lines):
if idx == 0:
continue
stripped = line.strip()
# Preserve blank and comment-only lines for readability
if not stripped or stripped.startswith("#"):
out_lines.append(stripped)
continue

try:
ops = parse_line_to_ops(line)
except ValueError as e:
raise ValueError(f"Error in file {src_path}, line {line!r}: {e}") from e

if not ops:
# No operators after stripping comments; skip the line
continue

# Default coefficient (1, 0) as requested
pieces: list[str] = ["(1, 0)"]
for mode, is_creation in ops:
pieces.append(f"{mode}{'^' if is_creation else ''}")

out_lines.append(" ".join(pieces))

dst_path.parent.mkdir(parents=True, exist_ok=True)
dst_path.write_text("\n".join(out_lines) + "\n", encoding="utf-8")


def iter_model_files(src_dir: pathlib.Path) -> Iterable[pathlib.Path]:
"""Yield all regular files under src_dir (non-recursive)."""
if not src_dir.exists():
raise FileNotFoundError(f"Source directory does not exist: {src_dir}")
for p in sorted(src_dir.iterdir()):
if p.is_file():
yield p


def main() -> None:
parser = argparse.ArgumentParser(
description="Convert fermihedral model files to qsyn .fham format."
)
parser.add_argument(
"--src",
type=pathlib.Path,
default=pathlib.Path("~").expanduser() / "fermihedral" / "model",
help="Source directory containing fermihedral model files "
"(default: ~/fermihedral/model)",
)
parser.add_argument(
"--dst",
type=pathlib.Path,
default=pathlib.Path("benchmark") / "fham",
help="Destination directory for converted .fham files "
"(default: benchmark/fham)",
)
parser.add_argument(
"--suffix",
type=str,
default=".fham",
help="Suffix to append to converted filenames (default: .fham)",
)

args = parser.parse_args()

src_dir: pathlib.Path = args.src
dst_dir: pathlib.Path = args.dst
suffix: str = args.suffix

for src_file in iter_model_files(src_dir):
dst_name = src_file.name + suffix if not src_file.name.endswith(suffix) else src_file.name
dst_path = dst_dir / dst_name
convert_file(src_file, dst_path)
print(f"Converted {src_file} -> {dst_path}")


if __name__ == "__main__":
main()

Loading
Loading