Build Diagram

class SubproblemSummaryStats(**data)

Bases: BaseModel

This is the metadata about the SUBPROBLEM generation.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

skipped_not_enough_rules_applications_subproblems: int

How many times we skipped to get a subproblem because it was too short.

unhandled_failure_to_build_subproblem_count: int

How many times we failed to get a subproblem because of an unhandled exception.

skipped_blacklisted_aux_setup_pairs: int

How many times we skipped a subproblem because aux setup pair was a false positive on a previous goal.

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class FailedClauseAttempt(**data)

Bases: BaseModel

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

problem: ProblemSetup

The problem we were trying to add the clause to.

clause: JGEXClause

The clause we were trying to add.

attempt_time: float

How long did it take to check whether we can add it?

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class DiagramGenerationMetadata(**data)

Bases: BaseModel

This is the metadata about the DIAGRAM generation. NOT about the individual datapoints.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

run_uuid: str
diagram_uuid: str
is_predefined_diagram: bool

Whether the problem was specified as an input, which means we do NOT generate anything.

config: DiagramGenerationConfig

The config we used to generate this diagram.

diagram_construction_time_sec: float

How long we spent trying to get a diagram.

diagram_succeeded: bool

If we didn’t manage to get a diagram, we can still store the metadata for counters.

saturation_succeeded: bool

Whether saturation was successful.

saturation_time_sec: float | None

How long we spent trying to saturate the diagram. Assumes we succeeded in getting a diagram. If diagram_succeeded is False, this will be None.

agent_saturation_stats: BaseModel | None

Agent statistics during the saturation process.

failed_clause_attempts: list[FailedClauseAttempt]

List of all the failed clause attempts on that diagram generation process.

created_at: datetime
subproblem_summary_stats: SubproblemSummaryStats
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class Diagram(solver, jgex_problem, nc_problem, setup_graph, jgex_clauses_consequences)

Bases: object

Represents a geometric diagram with its associated data.

solver

The solver with everything in it to solve the diagram

problem

The geometric problem associated with the diagram

dependencies

List of dependencies in the diagram

setup_graph

Dictionary mapping points to their dependencies

solver: GeometricSolver
jgex_problem: JGEXFormulation
nc_problem: ProblemSetup
setup_graph: dict[str, set[str]]
jgex_clauses_consequences: dict[JGEXClause, JGEXClauseConsequences]
build_diagram(cfg, sweep_cfg, free, intersect, other, rng)

Builds a geometric diagram by incrementally adding constructions.

The algorithm works as follows: 1. If debug_problem is provided, builds that specific problem and returns 2. Otherwise, builds a diagram incrementally:

  1. Starts with a random base construction from FREE (e.g. triangle, circle)

  2. Adds sampled number of additional free points based on config

  3. Repeatedly adds new constructions until reaching desired point count:
    • Tries to add either OTHER constructions (parallel lines, circles etc.) or INTERSECT constructions (1 or 2 intersection points)

    • For each construction type, makes multiple attempts with different random input points

    • If no valid construction is found after all attempts, returns None

    • Otherwise adds the successful construction and continues

Parameters:

cfg (DiagramGenerationConfig) – Configuration controlling diagram generation parameters - min_pts/max_pts: Desired point count range - attempts_per_construction: Number of random attempts per construction - debug_problem: Optional specific problem to build instead - Various sampling parameters for construction choices

Return type:

tuple[Diagram | None, DiagramGenerationMetadata]

Returns:

Built Diagram object if successful, None if construction fails

setupgraph(prob)

Build a dependency graph showing how each point depends on other points.

For each point in the problem, tracks which other points were needed to construct it. The dependencies are transitive - if point C depends on B which depends on A, then C will also show a dependency on A.

Parameters:

prob (ProblemJGEX | str) – The geometric problem to analyze, either as a ProblemJGEX object or as a string that can be parsed into one.

Returns:

A dictionary mapping each point name to the set of point names it

depends on. The value set for a point includes both direct dependencies (points used in its construction) and indirect dependencies (points needed to construct its direct dependencies).

Return type:

SetupGraph

Raises:

AssertionError – If a point appears multiple times in the problem clauses.