Skip to content

graflo.architecture.evolution.project

Pure planning for :class:~graflo.architecture.evolution.ops.ProjectManifestOp.

Selector validation and manifest unwrapping live here; the induced-connectivity kernel itself lives at layer 2 in :mod:graflo.architecture.schema.projection so manifest projection and schema context projection cannot drift apart. The depth walk borrows the same way, from :mod:graflo.architecture.schema.context.graph — the hop machinery is shared with rank-then-budget schema context rather than reimplemented here.

Attributes

Classes

Functions:

compute_projection(manifest, op)

Compute survivor/removal sets without mutating manifest.

Source code in graflo/architecture/evolution/project.py
def compute_projection(
    manifest: GraphManifest, op: ProjectManifestOp
) -> SubschemaSelection:
    """Compute survivor/removal sets without mutating *manifest*."""
    schema = manifest.graph_schema
    if schema is None:
        raise ValueError("project_manifest requires graph_schema")

    if op.strict:
        _validate_strict(manifest, op)

    keep_edge_ids = (
        _selector_edge_ids(op.keep_edges) if op.keep_edges is not None else None
    )
    if keep_edge_ids is not None and op.keep_inverse_edges:
        # A materialized pair is two declared edges; keeping one reading of the
        # fact and dropping the other would leave a schema that states half of it.
        edge_config = schema.core_schema.edge_config
        keep_edge_ids = keep_edge_ids | {
            mirror
            for edge_id in keep_edge_ids
            if (mirror := materialized_inverse_id(edge_config, edge_id)) is not None
            and mirror in edge_config
        }
    keep_vertices = op.keep_vertices
    if op.depth > 0:
        keep_vertices = _expand_seeds(schema, op, keep_edge_ids)

    return select_induced(
        schema.core_schema,
        keep_vertices=keep_vertices,
        keep_edge_ids=keep_edge_ids,
        connectivity=op.connectivity,
    )