{
  "schema_version": 1,
  "name": "Floquet spin chain with linked ISAES checkpoints (v2)",
  "description": "Version 2 adds explicitly calculated reduced q0 states at every cycle to the unchanged Floquet evolution; links retained observables, tables and reduced-state checkpoints. Full final state remains retained.",
  "adapter": "python",
  "entrypoint": "main.py:run",
  "requirements": [
    {
      "distribution": "qiskit",
      "version": "2.5.2"
    },
    {
      "distribution": "numpy",
      "version": "2.3.5"
    }
  ],
  "parameters": [
    {
      "name": "n",
      "label": "Qubits",
      "type": "integer",
      "default": 6,
      "minimum": 2,
      "maximum": 8,
      "required": true,
      "help": "Local density matrix uses dimension 2**n; q0 is the least-significant bit."
    },
    {
      "name": "cycles",
      "label": "Floquet cycles",
      "type": "integer",
      "default": 8,
      "minimum": 0,
      "maximum": 16,
      "required": true,
      "help": "Cycle 0 and every completed cycle are recorded."
    },
    {
      "name": "J",
      "label": "Ising coupling J (rad)",
      "type": "number",
      "default": 0.34,
      "minimum": 0,
      "maximum": 3.141592653589793,
      "required": true,
      "help": "RZZ(2J) on each undirected edge once per cycle."
    },
    {
      "name": "h",
      "label": "Transverse rotation h (rad)",
      "type": "number",
      "default": 0.71,
      "minimum": 0,
      "maximum": 3.141592653589793,
      "required": true,
      "help": "RX(2h) on each qubit after all ZZ gates."
    },
    {
      "name": "p",
      "label": "Phase-flip probability",
      "type": "number",
      "default": 0.025,
      "minimum": 0,
      "maximum": 0.5,
      "required": true,
      "help": "Independent Z flip channel on every qubit after the unitary cycle."
    },
    {
      "name": "boundary",
      "label": "Boundary",
      "type": "choice",
      "default": "ring",
      "choices": [
        "open",
        "ring"
      ],
      "required": true,
      "help": "Ring adds the closing edge only for n>2, avoiding a duplicate edge for two qubits."
    },
    {
      "name": "initial_state",
      "label": "Initial product state",
      "type": "choice",
      "default": "neel",
      "choices": [
        "neel",
        "zero"
      ],
      "required": true,
      "help": "Neel: q0=0,q1=1,q2=0,...; zero: every qubit is 0."
    }
  ],
  "outputs": [
    {
      "name": "fidelity",
      "label": "Ideal-state overlap fidelity",
      "kind": "number"
    },
    {
      "name": "purity",
      "label": "Purity",
      "kind": "number"
    },
    {
      "name": "magnetization",
      "label": "Mean Z magnetization",
      "kind": "number"
    },
    {
      "name": "zz_correlation",
      "label": "Mean nearest-neighbor ZZ correlation",
      "kind": "number"
    },
    {
      "name": "half_entropy_bits",
      "label": "Half-system entropy (bits)",
      "kind": "number"
    },
    {
      "name": "mutual_information_bits",
      "label": "Mutual information (bits)",
      "kind": "number"
    },
    {
      "name": "fidelity_series",
      "label": "Ideal-state overlap fidelity versus cycle",
      "kind": "series"
    },
    {
      "name": "purity_series",
      "label": "Purity versus cycle",
      "kind": "series"
    },
    {
      "name": "magnetization_series",
      "label": "Mean Z magnetization versus cycle",
      "kind": "series"
    },
    {
      "name": "zz_correlation_series",
      "label": "Mean nearest-neighbor ZZ correlation versus cycle",
      "kind": "series"
    },
    {
      "name": "half_entropy_bits_series",
      "label": "Half-system entropy (bits) versus cycle",
      "kind": "series"
    },
    {
      "name": "mutual_information_bits_series",
      "label": "Mutual information (bits) versus cycle",
      "kind": "series"
    },
    {
      "name": "observables",
      "label": "Cycle observables",
      "kind": "table"
    },
    {
      "name": "observables_csv",
      "label": "Observables CSV",
      "kind": "file"
    },
    {
      "name": "settings",
      "label": "Input settings",
      "kind": "json"
    },
    {
      "name": "trajectory",
      "label": "Complete observable trajectory",
      "kind": "json"
    },
    {
      "name": "edges",
      "label": "Undirected edges",
      "kind": "json"
    },
    {
      "name": "final_density_matrix",
      "label": "Final noisy density matrix (real/imag)",
      "kind": "json"
    },
    {
      "name": "final_ideal_statevector",
      "label": "Final ideal statevector (real/imag)",
      "kind": "json"
    },
    {
      "name": "conventions",
      "label": "Scientific conventions",
      "kind": "json"
    },
    {
      "name": "dependencies",
      "label": "Dependency versions",
      "kind": "json"
    },
    {
      "name": "final_states_json",
      "label": "Full final states JSON",
      "kind": "file"
    },
    {
      "name": "state_artifact",
      "label": "Final states artifact location and format",
      "kind": "json"
    },
    {
      "name": "reduced_q0_checkpoints",
      "kind": "json"
    }
  ],
  "checks": [
    {
      "name": "Zero-cycle six-qubit Neel state",
      "inputs": {
        "n": 6,
        "cycles": 0,
        "initial_state": "neel",
        "boundary": "ring"
      },
      "expectations": [
        {
          "output": "/metrics/fidelity",
          "operator": "close",
          "value": 1,
          "atol": 2e-10,
          "rtol": 0
        },
        {
          "output": "/metrics/purity",
          "operator": "close",
          "value": 1,
          "atol": 2e-10,
          "rtol": 0
        },
        {
          "output": "/metrics/magnetization",
          "operator": "close",
          "value": 0,
          "atol": 2e-10,
          "rtol": 0
        },
        {
          "output": "/metrics/zz_correlation",
          "operator": "close",
          "value": -1,
          "atol": 2e-10,
          "rtol": 0
        },
        {
          "output": "/metrics/half_entropy_bits",
          "operator": "close",
          "value": 0,
          "atol": 2e-10,
          "rtol": 0
        },
        {
          "output": "/metrics/mutual_information_bits",
          "operator": "close",
          "value": 0,
          "atol": 2e-10,
          "rtol": 0
        },
        {
          "output": "/data/trajectory",
          "operator": "length",
          "value": 1
        }
      ]
    },
    {
      "name": "Noiseless evolution remains pure and matches ideal",
      "inputs": {
        "n": 4,
        "cycles": 5,
        "p": 0
      },
      "expectations": [
        {
          "output": "/metrics/fidelity",
          "operator": "close",
          "value": 1,
          "atol": 2e-10,
          "rtol": 0
        },
        {
          "output": "/metrics/purity",
          "operator": "close",
          "value": 1,
          "atol": 2e-10,
          "rtol": 0
        },
        {
          "output": "/data/trajectory",
          "operator": "length",
          "value": 6
        }
      ]
    },
    {
      "name": "Zero rotations keep the zero state stationary under phase flips",
      "inputs": {
        "n": 3,
        "cycles": 4,
        "J": 0.83,
        "h": 0,
        "p": 0.5,
        "boundary": "open",
        "initial_state": "zero"
      },
      "expectations": [
        {
          "output": "/metrics/fidelity",
          "operator": "close",
          "value": 1,
          "atol": 2e-10,
          "rtol": 0
        },
        {
          "output": "/metrics/purity",
          "operator": "close",
          "value": 1,
          "atol": 2e-10,
          "rtol": 0
        },
        {
          "output": "/metrics/magnetization",
          "operator": "close",
          "value": 1,
          "atol": 2e-10,
          "rtol": 0
        },
        {
          "output": "/metrics/zz_correlation",
          "operator": "close",
          "value": 1,
          "atol": 2e-10,
          "rtol": 0
        },
        {
          "output": "/metrics/half_entropy_bits",
          "operator": "close",
          "value": 0,
          "atol": 2e-10,
          "rtol": 0
        },
        {
          "output": "/metrics/mutual_information_bits",
          "operator": "close",
          "value": 0,
          "atol": 2e-10,
          "rtol": 0
        }
      ]
    }
  ],
  "files": [
    {
      "path": "main.py",
      "content": "\"\"\"Deterministic Floquet Ising evolution with Qiskit quantum states/channels.\n\nQubit q0 is the least-significant computational-basis bit. A cycle consists of\nall RZZ(2*J) gates, all RX(2*h) gates, then a phase-flip channel on every qubit.\nFidelity here means ideal-state overlap Re(<psi_ideal|rho|psi_ideal>).\n\"\"\"\n\nimport csv\nimport json\nimport math\nfrom pathlib import Path\n\nimport numpy as np\nimport qiskit\nfrom qiskit import QuantumCircuit\nfrom qiskit.quantum_info import DensityMatrix, Kraus, Pauli, Statevector, partial_trace\n\n\nMETRIC_NAMES = (\n    \"fidelity\", \"purity\", \"magnetization\", \"zz_correlation\",\n    \"half_entropy_bits\", \"mutual_information_bits\",\n)\nDEFAULTS = {\n    \"n\": 6, \"cycles\": 8, \"J\": 0.34, \"h\": 0.71, \"p\": 0.025,\n    \"boundary\": \"ring\", \"initial_state\": \"neel\",\n}\n\n\ndef _settings(inputs):\n    \"\"\"Also validate direct Python calls, outside the typed workflow service.\"\"\"\n    unknown = set(inputs) - set(DEFAULTS)\n    if unknown:\n        raise ValueError(\"Unknown input(s): \" + \", \".join(sorted(unknown)))\n    values = dict(DEFAULTS)\n    values.update(inputs)\n    for name, low, high in ((\"n\", 2, 8), (\"cycles\", 0, 16)):\n        value = values[name]\n        if type(value) is not int or not low <= value <= high:\n            raise ValueError(f\"{name} must be an integer in [{low}, {high}]\")\n    for name, low, high in ((\"J\", 0.0, math.pi), (\"h\", 0.0, math.pi), (\"p\", 0.0, 0.5)):\n        value = values[name]\n        if type(value) not in (int, float) or not math.isfinite(value) or not low <= value <= high:\n            raise ValueError(f\"{name} must be finite and in [{low}, {high}]\")\n        values[name] = float(value)\n    if values[\"boundary\"] not in (\"open\", \"ring\"):\n        raise ValueError(\"boundary must be open or ring\")\n    if values[\"initial_state\"] not in (\"neel\", \"zero\"):\n        raise ValueError(\"initial_state must be neel or zero\")\n    return values\n\n\ndef _entropy_bits(state):\n    \"\"\"Von Neumann entropy in bits; discard eigenvalue roundoff below zero.\"\"\"\n    matrix = np.asarray(state.data, dtype=complex)\n    eigenvalues = np.linalg.eigvalsh((matrix + matrix.conj().T) / 2.0)\n    if float(eigenvalues.min()) < -1e-10:\n        raise ValueError(\"Density matrix has a materially negative eigenvalue\")\n    probabilities = np.clip(eigenvalues, 0.0, 1.0)\n    positive = probabilities[probabilities > 0.0]\n    return float(-np.sum(positive * np.log2(positive)))\n\n\ndef _observables(rho, ideal, n, edges):\n    matrix = rho.data\n    vector = ideal.data\n    subsystem_a = list(range(n // 2))\n    subsystem_b = list(range(n // 2, n))\n    entropy_a = _entropy_bits(partial_trace(rho, subsystem_b))\n    entropy_b = _entropy_bits(partial_trace(rho, subsystem_a))\n    entropy_ab = _entropy_bits(rho)\n    return {\n        \"fidelity\": float(np.real(np.vdot(vector, matrix @ vector))),\n        \"purity\": float(np.real(np.trace(matrix @ matrix))),\n        \"magnetization\": float(np.mean([\n            np.real(rho.expectation_value(Pauli(\"Z\"), qargs=[q])) for q in range(n)\n        ])),\n        \"zz_correlation\": float(np.mean([\n            np.real(rho.expectation_value(Pauli(\"ZZ\"), qargs=[i, j])) for i, j in edges\n        ])),\n        \"half_entropy_bits\": entropy_a,\n        \"mutual_information_bits\": entropy_a + entropy_b - entropy_ab,\n    }\n\n\ndef _complex_arrays(array):\n    return {\"real\": array.real.tolist(), \"imag\": array.imag.tolist()}\n\n\ndef run(inputs, context):\n    \"\"\"Return six metrics, full trajectories, states, and a real CSV artifact.\"\"\"\n    settings = _settings(inputs)\n    n, cycles = settings[\"n\"], settings[\"cycles\"]\n    edges = [(q, q + 1) for q in range(n - 1)]\n    if settings[\"boundary\"] == \"ring\" and n > 2:\n        edges.append((n - 1, 0))\n\n    preparation = QuantumCircuit(n)\n    if settings[\"initial_state\"] == \"neel\":\n        for q in range(1, n, 2):\n            preparation.x(q)\n    ideal = Statevector.from_instruction(preparation)\n    rho = DensityMatrix(ideal)\n\n    cycle = QuantumCircuit(n, name=\"Floquet_cycle\")\n    for i, j in edges:\n        cycle.rzz(2.0 * settings[\"J\"], i, j)\n    for q in range(n):\n        cycle.rx(2.0 * settings[\"h\"], q)\n    p = settings[\"p\"]\n    phase_flip = Kraus([\n        np.sqrt(1.0 - p) * np.eye(2, dtype=complex),\n        np.sqrt(p) * np.diag([1.0, -1.0]),\n    ])\n\n    def checkpoint(at):\n        reduced = partial_trace(rho, list(range(1, n)))\n        return {\"at\": at, \"observation_id\": \"floquet-cycle:\" + str(at),\n                \"state\": _complex_arrays(reduced.data)}\n    reduced_checkpoints = [checkpoint(0)]\n    trajectory = [{\"cycle\": 0, **_observables(rho, ideal, n, edges)}]\n    for index in range(1, cycles + 1):\n        ideal = ideal.evolve(cycle)\n        rho = rho.evolve(cycle)\n        for q in range(n):\n            rho = rho.evolve(phase_flip, qargs=[q])\n        trajectory.append({\"cycle\": index, **_observables(rho, ideal, n, edges)})\n        reduced_checkpoints.append(checkpoint(index))\n\n    columns = [\"cycle\", *METRIC_NAMES]\n    rows = [[item[name] for name in columns] for item in trajectory]\n    output_dir = Path(context.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    with (output_dir / \"observables.csv\").open(\"w\", newline=\"\", encoding=\"utf-8\") as stream:\n        writer = csv.writer(stream)\n        writer.writerow(columns)\n        writer.writerows(rows)\n\n    final_states = {\n        \"final_density_matrix\": _complex_arrays(rho.data),\n        \"final_ideal_statevector\": _complex_arrays(ideal.data),\n    }\n    with (output_dir / \"final_states.json\").open(\"w\", encoding=\"utf-8\") as stream:\n        json.dump(final_states, stream, allow_nan=False, separators=(\",\", \":\"))\n    # At n=8 the full inline density arrays exceed r34's result quotas.\n    # Preserve the complete, unrounded arrays in the JSON artifact instead.\n    inline_states = final_states if n <= 7 else {\n        name: {\"artifact_path\": \"final_states.json\", \"json_pointer\": \"/\" + name}\n        for name in final_states\n    }\n\n    return {\n        \"metrics\": {name: trajectory[-1][name] for name in METRIC_NAMES},\n        \"tables\": [{\"name\": \"observables\", \"columns\": columns, \"rows\": rows,\n                    \"link_group\": \"floquet-cycles\", \"observation_ids\": [\"floquet-cycle:\" + str(item[\"cycle\"]) for item in trajectory]}],\n        \"series\": [\n            {\"name\": name + \"_series\", \"x\": [item[\"cycle\"] for item in trajectory],\n             \"y\": [item[name] for item in trajectory]}\n            for name in METRIC_NAMES\n        ],\n        \"artifacts\": [\n            {\"name\": \"observables_csv\", \"path\": \"observables.csv\", \"mime_type\": \"text/csv\"},\n            {\"name\": \"final_states_json\", \"path\": \"final_states.json\", \"mime_type\": \"application/json\"},\n        ],\n        \"data\": {\n            \"settings\": settings,\n            \"trajectory\": trajectory,\n            \"reduced_q0_checkpoints\": {\"coordinate\": \"cycle\", \"checkpoints\": reduced_checkpoints,\n                \"dynamics\": {\"model\": \"Floquet Ising phase-flip evolution\", \"settings\": settings,\n                    \"subsystem\": [0], \"traced_out_qubits\": list(range(1, n)),\n                    \"interpretation\": \"Calculated one-qubit reduced states at retained cycles; other intermediate full-state information is not retained.\"}},\n            \"edges\": [list(edge) for edge in edges],\n            \"final_density_matrix\": inline_states[\"final_density_matrix\"],\n            \"final_ideal_statevector\": inline_states[\"final_ideal_statevector\"],\n            \"state_artifact\": {\n                \"name\": \"final_states_json\", \"path\": \"final_states.json\",\n                \"format\": \"JSON with full final_density_matrix and final_ideal_statevector real/imag arrays\",\n                \"density_matrix_shape\": [2 ** n, 2 ** n],\n                \"ideal_statevector_shape\": [2 ** n],\n                \"inline_arrays\": n <= 7,\n                \"reason\": \"Full inline eight-qubit state arrays exceed r34 result JSON quotas; artifact retains all entries.\",\n            },\n            \"conventions\": {\n                \"basis\": \"Little-endian integer indexing; q0 is the least-significant bit.\",\n                \"initial_state\": \"neel: q0=0,q1=1,q2=0,...; zero: every qubit is 0.\",\n                \"cycle_order\": \"All undirected-edge RZZ(2J), then all RX(2h), then one phase-flip channel per qubit.\",\n                \"unitaries\": \"RZZ(2J)=exp(-i J ZiZj); RX(2h)=exp(-i h Xi); J,h are radians.\",\n                \"phase_flip\": \"rho -> (1-p)rho + p Zi rho Zi, independently on each qubit after each cycle.\",\n                \"fidelity\": \"Re(<psi_ideal|rho|psi_ideal>); psi_ideal has the same unitary evolution without noise.\",\n                \"magnetization\": \"Mean <Zq> over all n qubits.\",\n                \"zz_correlation\": \"Mean <ZiZj> over edges; ring adds (n-1,0) only for n>2.\",\n                \"entropy\": \"Von Neumann entropy in bits using log2; negative eigenvalue roundoff clipped at zero.\",\n                \"partition_a\": list(range(n // 2)),\n                \"partition_b\": list(range(n // 2, n)),\n                \"mutual_information\": \"S(A)+S(B)-S(AB), evaluated on the noisy density matrix.\",\n                \"sampling\": \"Deterministic local statevector/density-matrix simulation; no stochastic samples or hardware calls.\",\n                \"time_axis\": \"Cycle 0 is the prepared state; subsequent points follow full cycles including noise.\",\n            },\n            \"dependencies\": {\"qiskit\": qiskit.__version__, \"numpy\": np.__version__},\n        },\n    }\n"
    },
    {
      "path": "reporting.py",
      "content": "from pf_reporting.engine import StructureAnalyzer, SeriesAnalyzer\nfrom pf_reporting.sdk import capability\nclass Topology(StructureAnalyzer):\n    name, kinds = 'floquet_topology', ('floquet_topology',)\n    def analyze(self, dataset, value, context):\n        n = context['result']['data']['settings']['n']\n        declared = dict(dataset, kind='network')\n        return super().analyze(declared, {'nodes': list(range(n)), 'edges': value}, context)\nclass LinkedFloquetSeries(SeriesAnalyzer):\n    name, kinds = 'floquet_cycle_series', ('floquet_cycle_series',)\n    capability = capability(name, kinds, version='1.0.0', input_schema={'type': 'object', 'properties': {'x': {'type': 'array'}, 'y': {'type': 'array'}}, 'required': ['x', 'y']}, assumptions=['Cycle identities derive from explicitly retained x coordinates.'], applicability='Requires matching retained ordered x/y and cycle identity; no intermediate state reconstruction.')\n    def analyze(self, dataset, value, context):\n        item, graphs = super().analyze(dataset, value, context)\n        ids = ['floquet-cycle:' + str(int(x)) for x in value['x']]\n        if any(type(x) not in (int, float) or int(x) != x or x < 0 for x in value['x']) or len(set(ids)) != len(ids):\n            raise ValueError('Floquet cycle identity requires unique retained integer cycles')\n        for graph in graphs:\n            graph.update(link_group='floquet-cycles', observation_ids=ids)\n        return item, graphs\n\ndef configure(registry, context):\n    registry.register(Topology())\n    registry.register(LinkedFloquetSeries())\n    return {}\n"
    }
  ],
  "reporting": {
    "schema_version": 2,
    "intent": "Floquet spin-chain results",
    "datasets": [
      {
        "name": "final_density_matrix",
        "kind": "density_matrix",
        "source": "artifact:final_states_json#/final_density_matrix",
        "basis": "Computational basis; little-endian integer indexing, q0 least significant",
        "tolerance": 1e-08
      },
      {
        "name": "fidelity_series",
        "kind": "floquet_cycle_series",
        "source": "/series/0",
        "label": "Ideal-state overlap fidelity versus cycle",
        "x_label": "Completed cycle",
        "units": "dimensionless"
      },
      {
        "name": "purity_series",
        "kind": "floquet_cycle_series",
        "source": "/series/1",
        "label": "Purity versus cycle",
        "x_label": "Completed cycle",
        "units": "dimensionless"
      },
      {
        "name": "magnetization_series",
        "kind": "floquet_cycle_series",
        "source": "/series/2",
        "label": "Mean Z magnetization versus cycle",
        "x_label": "Completed cycle",
        "units": "dimensionless"
      },
      {
        "name": "zz_correlation_series",
        "kind": "floquet_cycle_series",
        "source": "/series/3",
        "label": "Mean nearest-neighbor ZZ correlation versus cycle",
        "x_label": "Completed cycle",
        "units": "dimensionless"
      },
      {
        "name": "half_entropy_bits_series",
        "kind": "floquet_cycle_series",
        "source": "/series/4",
        "label": "Half-system entropy (bits) versus cycle",
        "x_label": "Completed cycle",
        "units": "bits"
      },
      {
        "name": "mutual_information_bits_series",
        "kind": "floquet_cycle_series",
        "source": "/series/5",
        "label": "Mutual information (bits) versus cycle",
        "x_label": "Completed cycle",
        "units": "bits"
      },
      {
        "name": "interaction_topology",
        "kind": "floquet_topology",
        "source": "/data/edges",
        "label": "Executed interaction edges"
      },
      {
        "name": "quantum_state_evidence",
        "kind": "quantum_state",
        "source": "artifact:final_states_json#/final_density_matrix",
        "basis": "computational",
        "qubit_order": "little_endian",
        "origin": "numerical_state",
        "tolerance": 1e-08,
        "label": "Final state: local and joint evidence",
        "units": "dimensionless"
      },
      {
        "name": "reduced_q0_checkpoints",
        "kind": "quantum_checkpoints",
        "source": "/data/reduced_q0_checkpoints",
        "basis": "computational",
        "qubit_order": "little_endian",
        "origin": "numerical_state",
        "tolerance": 1e-08,
        "label": "Calculated reduced q0 state checkpoints",
        "units": "dimensionless",
        "link_group": "floquet-cycles",
        "observables": [
          "Z"
        ]
      }
    ],
    "require": [
      "matrix:final_density_matrix",
      "quantum_state:quantum_state_evidence",
      "quantum_checkpoints:reduced_q0_checkpoints"
    ],
    "extensions": [
      "reporting.py:configure"
    ],
    "analysis": {
      "mode": "exploratory",
      "question": "How do the retained Floquet dynamics and final quantum state compare with the declared ideal evolution?"
    },
    "presentation": {
      "audience": "technical"
    }
  }
}
