Skip to content

GraphProblemIR

from cascaqit import GraphProblemIR

GraphProblemIR

GraphProblemIR(
    problem_id: str,
    nodes: tuple[str, ...],
    edges: tuple[tuple[str, str], ...],
    node_positions: tuple[
        tuple[str, tuple[float, float]], ...
    ] = (),
    graph_type: Literal["undirected"] = "undirected",
    schema_version: str = SCHEMA_VERSION,
    metadata: dict[str, Any] = dict(),
)

Store undirected nodes, edges and optional two-dimensional positions for MIS modeling, reference layouts and result decoding. Usually use from_edges(). Direct construction preserves input order without performing structural validation; inspect validate() explicitly.

nodes defines node and result-bit order. Isolated nodes affect the problem even when absent from edges, so list them in from_edges(nodes=...). node_positions is a layout hint. It does not guarantee that distance-dependent interactions reproduce edges or establish an executable atom layout. problem_id, metadata and schema_version retain identity, additional information and format.

from cascaqit import GraphProblemIR

problem = GraphProblemIR.from_edges(problem_id="edge_and_isolated",
    nodes=("c", "b", "a"), edges=(("b", "a"), ("a", "b")))
assert problem.nodes == ("a", "b", "c")
assert problem.edges == (("a", "b"),)
assert not problem.validate()
assert problem.result_decoding_metadata().variable_order == problem.nodes
assert problem.to_mis_instance().node_order() == problem.nodes
assert GraphProblemIR.from_json(problem.to_json()) == problem

See Graph problem modeling for an experiment.

from_edges

from_edges(
    *,
    problem_id: str,
    edges: list[tuple[str, str]]
    | tuple[tuple[str, str], ...],
    nodes: list[str] | tuple[str, ...] | None = None,
    positions: dict[str, tuple[float, float]] | None = None,
    metadata: dict[str, Any] | None = None,
) -> GraphProblemIR

Convert node IDs to strings, deduplicate and sort them. Sort endpoints of undirected edges and keep one copy of repeated or reversed edges. Without nodes, infer nodes only from edges. Explicit nodes defines the node set and does not automatically add omitted endpoints; validate() reports unknown nodes. positions becomes a key-sorted coordinate tuple. Check self-loops, empty graphs and references after construction.

position_by_node

position_by_node() -> dict[str, tuple[float, float]]

Return a dictionary copy of saved node_positions. This does not fill missing coordinates or validate geometry or graph embedding.

validate

validate() -> tuple[DiagnosticsIR, ...]

Return diagnostics for an empty graph, duplicate nodes, self-loops and edges referring to unknown nodes without modifying the graph. Current checks do not validate coordinate coverage, finiteness or physical target constraints. No errors does not establish a usable simulation layout.

to_mis_instance

to_mis_instance(
    *, fallback_spacing: float = 5.0
) -> MISInstance

Return cascaqit.problems.MISInstance. Keep supplied coordinates only when their keys exactly cover nodes; otherwise replace all positions with a line using fallback_spacing. Partial coordinates are not retained. Edges remain the declared edges and are not reconstructed from distance. MISInstance sorts node names; after converting a directly constructed graph with a different order, read node_order() again. This does not solve MIS or check target feasibility.

result_decoding_metadata

result_decoding_metadata() -> ProblemResultDecodingIR

Return ProblemResultDecodingIR containing node order, source digest and the convention that 1 selects a node. It does not include the complete edge constraints, so this metadata alone cannot establish whether a selected set is independent.

layout_candidate

layout_candidate(
    *,
    layout: Literal["line", "grid"] = "line",
    spacing: float = 5.0,
    columns: int | None = None,
) -> ProblemCandidateIR

Return a line or grid ProblemCandidateIR with newly generated coordinates, edges and limitation diagnostics, without changing node_positions. spacing must be positive. For grid, columns sets the column count; omitted columns uses a near-square count. This does not optimize placement, generate pulses or verify that geometry reproduces all edges and nonedges.

from_dict

from_dict(data: dict[str, Any]) -> GraphProblemIR

Restore GraphProblemIR from a dictionary. Restore saved node, edge and coordinate order without from_edges() normalization; call validate() separately for structural checks. Missing required fields or invalid values can raise KeyError, TypeError or ValueError.

from_json

from_json(text: str) -> GraphProblemIR

Parse a JSON object and call from_dict(), returning GraphProblemIR. Invalid JSON raises a parsing error; a non-object root raises TypeError.

to_dict

to_dict() -> dict[str, Any]

Return a JSON-compatible dictionary, serializing nested objects and converting tuples to arrays. This stores the declaration, not an execution result.

to_json

to_json(*, indent: int | None = None) -> str

Return a JSON string without writing a file. indent=None uses compact formatting; supply an indentation width for readable output.

stable_hash

stable_hash() -> str

Return the SHA-256 hex digest of canonical JSON. Fields, identifiers and metadata can affect it. Use it to compare saved content, not to decide physical equivalence.