diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index e55e329d..e254d089 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -39,25 +39,4 @@ jobs: with: files: lcov.info token: ${{ secrets.CODECOV_TOKEN }} - fail_ci_if_error: false - docs: - name: Documentation - runs-on: ubuntu-latest - permissions: - contents: write - statuses: write - steps: - - uses: actions/checkout@v2 - - uses: julia-actions/setup-julia@v1 - with: - version: '1' - - uses: julia-actions/julia-buildpkg@v1 - - uses: julia-actions/julia-docdeploy@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - run: | - julia --project=docs -e ' - using Documenter: DocMeta, doctest - using QuantumCollocation - DocMeta.setdocmeta!(QuantumCollocation, :DocTestSetup, :(using QuantumCollocation); recursive=true) - doctest(QuantumCollocation)' + fail_ci_if_error: false \ No newline at end of file diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000..21b313ab --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,45 @@ +name: Documentation +on: + pull_request: + push: + branches: + - main + tags: ['*'] +concurrency: + # Skip intermediate builds: always. + # Cancel intermediate builds: only if it is a pull request build. + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} +jobs: + docs: + name: Documentation + runs-on: ubuntu-latest + permissions: + contents: write + statuses: write + env: + DOC_TEMPLATE_VERSION: "v0.2.1" # Change this to the specific tag version you want + steps: + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v2 + - uses: julia-actions/cache@v2 + - name: Use Documentation Template + run: | + ./docs/get_docs_utils.sh ${{ env.DOC_TEMPLATE_VERSION }} + - uses: julia-actions/julia-buildpkg@v1 + - uses: julia-actions/julia-docdeploy@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Upload documentation artifacts + uses: actions/upload-artifact@v4 + with: + name: documentation-build + path: docs/build/ + retention-days: 1 + - run: | + julia --project=docs -e ' + using Documenter: DocMeta, doctest + using QuantumCollocation + DocMeta.setdocmeta!(QuantumCollocation, :DocTestSetup, :(using QuantumCollocation); recursive=true) + doctest(QuantumCollocation)' + diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml deleted file mode 100644 index 11403a3e..00000000 --- a/.github/workflows/documentation.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Documentation - -on: - push: - branches: - - main # update to match your development branch (master, main, dev, trunk, ...) - tags: '*' - pull_request: - -jobs: - build: - permissions: - contents: write - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: julia-actions/setup-julia@v1 - with: - version: '1.10' - - name: Install dependencies - run: julia --project=docs -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' - - name: Build and deploy - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # If authenticating with GitHub Actions token - DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} # If authenticating with SSH deploy key - run: julia --project=docs docs/make.jl \ No newline at end of file diff --git a/.gitignore b/.gitignore index ac13bb9f..62f6bf05 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,10 @@ build/ # VS code *.code-workspace .vscode/settings.json + +# doc_template stuff +# Temporary directory for doc_template cloning +doc_template_temp/ + +# This file is updated via script +docs/utils.jl \ No newline at end of file diff --git a/README.md b/README.md index 154bc062..4b223d7b 100644 --- a/README.md +++ b/README.md @@ -91,3 +91,35 @@ U_goal = GATES.H prob = UnitarySmoothPulseProblem(system, U_goal, T, Δt) solve!(prob, max_iter=100) ``` + + +### Building Documentation +This package uses a Documenter config that is shared with many of our other repositories. To build the docs, you will need to run the docs setup script to clone and pull down the utility. +``` +# first time only +./docs/get_docs_utils.sh # or ./get_docs_utils.sh if cwd is in ./docs/ +``` + +To build the docs pages: +``` +julia --project=docs docs/make.jl +``` + +or editing the docs live: +``` +julia --project=docs +> using LiveServer, QuantumCollocation, Revise +> servedocs(literate_dir="docs/literate", skip_dirs=["docs/src/generated"]) +``` + +> **Note:** `servedocs` needs to watch a subset of the files in the `docs/` folder. If it watches files that are generated on a docs build/re-build, `servedocs` will continuously try to re-serve the pages. +> +> To prevent this, ensure all generated files are included in the skip dirs or skip files args for `servedocs`. + +For example, if we forget docs/src/generated like so: +``` +julia --project=docs +> using LiveServer, Piccolo, Revise +> servedocs(literate_dir="docs/literate") +``` +it will not build and serve. \ No newline at end of file diff --git a/docs/Project.toml b/docs/Project.toml index eaecb613..9a164c2b 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -4,6 +4,7 @@ Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306" LiveServer = "16fef848-5104-11e9-1b77-fb7a48bbb589" NamedTrajectories = "538bc3a1-5ab9-4fc3-b776-35ca1e893e08" +PiccoloDocsTemplate = "a90a139f-c522-4b23-980b-4210ddb8d065" PiccoloPlots = "f42a522c-b487-4f73-ad5a-ad0c3e4a12c8" PiccoloQuantumObjects = "5a402ddf-f93c-42eb-975e-5582dcda653d" QuantumCollocation = "0dc23a59-5ffb-49af-b6bd-932a8ae77adf" diff --git a/docs/get_docs_utils.sh b/docs/get_docs_utils.sh new file mode 100755 index 00000000..9723a50d --- /dev/null +++ b/docs/get_docs_utils.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +set -euo pipefail + +# Get the directory where this script is located +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$SCRIPT_DIR/.." + +# if argument is provided, use it as the DOC_TEMPLATE_VERSION +if [[ $# -gt 0 ]]; then + DOC_TEMPLATE_VERSION="$1" +else + WORKFLOW_FILE="$PROJECT_ROOT/.github/workflows/docs.yml" + + # Check if workflow file exists + if [[ ! -f "$WORKFLOW_FILE" ]]; then + echo "GitHub workflow file not found at: $WORKFLOW_FILE" + exit 1 + fi + + DOC_TEMPLATE_VERSION=$(grep -E '^\s*DOC_TEMPLATE_VERSION:' "$WORKFLOW_FILE" | sed -E 's/.*DOC_TEMPLATE_VERSION:\s*"([^"]+)".*/\1/') +fi + +if [[ -z "$DOC_TEMPLATE_VERSION" ]]; then + echo "DOC_TEMPLATE_VERSION is not set" + echo "Please provide a version tag as an arg or ensure it is set in $WORKFLOW_FILE" + echo "Could not extract DOC_TEMPLATE_VERSION from $WORKFLOW_FILE" + echo "Expected format: DOC_TEMPLATE_VERSION: \"\"" + exit 1 +fi + +# Clone the repository +echo "Grabbing PiccoloDocsTemplate at version $DOC_TEMPLATE_VERSION" +julia --project="$PROJECT_ROOT/docs" -e " +using Pkg; Pkg.add(url=\"https://github.com/harmoniqs/PiccoloDocsTemplate.jl\", rev=\"$DOC_TEMPLATE_VERSION\") +" + +echo "Successfully updated PiccoloDocsTemplate with version $DOC_TEMPLATE_VERSION" \ No newline at end of file diff --git a/docs/make.jl b/docs/make.jl index 3a296bca..e8a8ae25 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,66 +1,25 @@ using QuantumCollocation -using Documenter -using Literate - -push!(LOAD_PATH, joinpath(@__DIR__, "..", "src")) - -@info "Building Documenter site for QuantumCollocation.jl" +using PiccoloDocsTemplate pages = [ "Home" => "index.md", + "Manual" => [ + "Ket Problem Templates" => "generated/man/ket_problem_templates.md", + "Unitary Problem Templates" => "generated/man/unitary_problem_templates.md", + ], "Examples" => [ "Two Qubit Gates" => "generated/examples/two_qubit_gates.md", "Multilevel Transmon" => "generated/examples/multilevel_transmon.md", ], - "Library" => [ - "Ket Problem Templates" => "generated/man/ket_problem_templates.md", - "Unitary Problem Templates" => "generated/man/unitary_problem_templates.md", - ], + "Library" => "lib.md", ] -format = Documenter.HTML(; - prettyurls=get(ENV, "CI", "false") == "true", - canonical="https://docs.harmoniqs.co/QuantumCollocation.jl", - edit_link="main", - assets=String[], - mathengine = MathJax3(Dict( - :loader => Dict("load" => ["[tex]/physics"]), - :tex => Dict( - "inlineMath" => [["\$","\$"], ["\\(","\\)"]], - "tags" => "ams", - "packages" => [ - "base", - "ams", - "autoload", - "physics" - ], - ), - )), - # size_threshold=4_000_000, -) - -src = joinpath(@__DIR__, "src") -lit = joinpath(@__DIR__, "literate") - -lit_output = joinpath(src, "generated") - -for (root, _, files) ∈ walkdir(lit), file ∈ files - splitext(file)[2] == ".jl" || continue - ipath = joinpath(root, file) - opath = splitdir(replace(ipath, lit=>lit_output))[1] - Literate.markdown(ipath, opath) -end - -makedocs(; - modules=[QuantumCollocation], - authors="Aaron Trowbridge and contributors", - sitename="QuantumCollocation.jl", - format=format, - pages=pages, - warnonly=true, -) - -deploydocs(; - repo="github.com/harmoniqs/QuantumCollocation.jl.git", - devbranch="main", -) +generate_docs( + @__DIR__, + "QuantumCollocation", + [QuantumCollocation], + pages; + make_index = false, + make_assets = false, + format_kwargs = (canonical = "https://docs.harmoniqs.co/QuantumCollocation.jl",), +) \ No newline at end of file diff --git a/docs/src/index.md b/docs/src/index.md index b548075a..aaa32321 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -59,4 +59,4 @@ In each case, the dynamics between *knot points* $(U_t, a_t)$ and $(U_{t+1}, a_{ ----- -Problem templates give the user the ability to add other constraints and objective functions to this problem and solve it efficiently using [Ipopt.jl](https://github.com/jump-dev/Ipopt.jl) and [MathOptInterface.jl](https://github.com/jump-dev/MathOptInterface.jl) under the hood. +Problem templates give the user the ability to add other constraints and objective functions to this problem and solve it efficiently using [Ipopt.jl](https://github.com/jump-dev/Ipopt.jl) and [MathOptInterface.jl](https://github.com/jump-dev/MathOptInterface.jl) under the hood (support for additional backends coming soon!). diff --git a/docs/src/lib.md b/docs/src/lib.md index f25d4542..f89d16d3 100644 --- a/docs/src/lib.md +++ b/docs/src/lib.md @@ -5,6 +5,26 @@ Modules = [QuantumCollocation.ProblemTemplates] ``` +## Quantum System Templates +```@autodocs +Modules = [QuantumCollocation.QuantumSystemTemplates] +``` + +## Quantum Objectives +```@autodocs +Modules = [QuantumCollocation.QuantumObjectives] +``` + +## Quantum Constraints +```@autodocs +Modules = [QuantumCollocation.QuantumObjectives] +``` + +## Quantum Integrators +```@autodocs +Modules = [QuantumCollocation.QuantumObjectives] +``` + ## Options ```@autodocs Modules = [QuantumCollocation.Options] diff --git a/src/quantum_system_templates/cats.jl b/src/quantum_system_templates/cats.jl index 5d4b188b..1d37a194 100644 --- a/src/quantum_system_templates/cats.jl +++ b/src/quantum_system_templates/cats.jl @@ -6,6 +6,21 @@ function coherent_ket(α::Union{Real, Complex}, levels::Int)::Vector{ComplexF64} return [exp(-0.5 * abs2(α)) * α^n / sqrt(factorial(n)) for n in 0:levels-1] end +""" + CatSystem(; + g2::Real=0.36, + χ_aa::Real=-7e-3, + χ_bb::Real=-32, + χ_ab::Real=0.79, + κa::Real=53e-3, + κb::Real=13, + cat_levels::Int=13, + buffer_levels::Int=3, + prefactor::Real=1, + )::OpenQuantumSystem + +Returns an `OpenQuantumSystem` for a quantum cat. +""" function CatSystem(; g2::Real=0.36, χ_aa::Real=-7e-3, diff --git a/src/quantum_system_templates/rydberg.jl b/src/quantum_system_templates/rydberg.jl index 1c13269f..56a64e03 100644 --- a/src/quantum_system_templates/rydberg.jl +++ b/src/quantum_system_templates/rydberg.jl @@ -23,7 +23,9 @@ function generate_pattern_with_gap(N::Int, i::Int, gap::Int) end """ -Embed a character into a string at a specific position. + lift(x::Char, i::Int, N::Int)::String + +Embed a character into a string of the form 'I' * N at a specific position (meant for use with `PiccoloQuantumObjects.QuantumObjectUtils.operator_from_string`). """ function lift(x::Char,i::Int, N::Int) qubits = fill('I', N) @@ -40,7 +42,7 @@ end local_detune::Bool=false, # If true, include one local detuning pattern. all2all::Bool=true, # If true, include all-to-all interactions. ignore_Y_drive::Bool=false, # If true, ignore the Y drive. (In the experiments, X&Y drives are implemented by Rabi amplitude and its phase.) - ) -> QuantumSystem + )::QuantumSystem Returns a `QuantumSystem` object for the Rydberg atom chain in the spin basis |g⟩ = |0⟩ = [1, 0], |r⟩ = |1⟩ = [0, 1].