Darwin Gödel Machine (DGM)

repository·main·Indexed 24 days ago

https://github.com/jennyzzt/dgm

A self-improving system that iteratively modifies its own code and validates changes using coding benchmarks such as SWE-bench and Polyglot. The system utilizes foundation models and includes a testbed with various implementation challenges across Go, Python, and Rust.

Tokens
42.8K
Snippets
97
Records
212
Agent score
79%

What's inside dgm

  1. Understand the DGM file structure

    main

    The repository is organized as follows:

    • analysis/: Scripts for plotting and data analysis.
    • initial/: SWE-bench logs and performance metrics for the initial agent.
    • initial_polyglot/: Polyglot logs and performance metrics for the initial agent.
    • swe_bench/: Code required for SWE-bench evaluation.
    • polyglot/: Code required for Polyglot evaluation.
    • prompts/: Prompts used for foundation models.
    • tests/: Test suite for the DGM system.
    • tools/: Tools available to the foundation models.
    • coding_agent.py: Main implementation of the initial coding agent.
    • DGM_outer.py: The primary entry point for running the DGM algorithm.
  2. Classify numbers as Perfect, Abundant, or Deficient

    main

    Based on Nicomachus' classification scheme, positive integers are categorized by comparing the number to its aliquot sum (the sum of all factors of the number excluding the number itself):

    • Perfect: The number equals its aliquot sum.
      • Example: 6 (factors 1, 2, 3 sum to 6).
    • Abundant: The number is less than its aliquot sum.
      • Example: 12 (factors 1, 2, 3, 4, 6 sum to 16).
    • Deficient: The number is greater than its aliquot sum.
      • Example: 8 (factors 1, 2, 4 sum to 7).
      • Note: All prime numbers are deficient.
  3. Implement the Allergy Score logic

    main

    The task is to implement a system that decodes a single numeric allergy score into a list of specific allergens. Each allergen is represented by a unique power of two (a bitmask).

    Allergen Bitmask Mapping:

    • eggs: 1
    • peanuts: 2
    • shellfish: 4
    • strawberries: 8
    • tomatoes: 16
    • chocolate: 32
    • pollen: 64
    • cats: 128

    Requirements:

    1. Determine if a person is allergic to a specific item based on the score.
    2. Return the full list of allergens present in the score.
    3. Ignore any bits in the score that correspond to allergens not in the provided list (e.g., scores of 256, 512, etc.). For example, a score of 257 should only report eggs (1).

    Example: A score of 34 (32 + 2) indicates allergies to chocolate and peanuts.

  4. Handle Global Mutable State in Rust tests

    main

    In this specific environment/problem context, the test setup forces the use of global mutable state. While this is considered unidiomatic in Rust, it is a deliberate design choice for this learning exercise.

    When working on this problem, you should be aware that you will likely need to interact with global state to satisfy the existing test suite, but you are encouraged to propose a better API design that avoids global mutable state as part of your solution.

  5. Implement robot-simulator Step 2: Room and Robot concurrency

    main

    Step 2 shifts the simulation from simple logic to a concurrent model using Go channels and goroutines.

    Core Abstractions

    • Room: Acts as a "physics engine." It models the coordinate space, walls, and the robot's location. It is responsible for ensuring the robot does not walk through walls and maintains the "coherent truth" of the physical world.
    • Robot: An agent that performs actions. It must accept commands via a channel and inform the Room of attempted actions.
    • Test Program: The orchestrator. It creates the necessary channels, launches the Room and Robot as goroutines, sends commands to the Robot, and closes the command channel when finished.

    Communication Flow

    1. The Test Program sends commands to the Robot via a channel.
    2. The Robot receives commands and informs the Room of its intended actions.
    3. The Room interprets the physical consequences (e.g., movement or hitting a wall).
    4. When the command channel closes, the Robot must shut down.
    5. When the Room detects the robot shutting down, it sends a final report back to the Test Program containing the robot's final position and direction.
  6. Implement a LIFO Stack using a Singly Linked List

    main

    This exercise requires implementing a Last-In, First-Out (LIFO) stack using a custom-made singly linked list rather than Python's built-in list, collections.deque, or queue.LifoQueue.

    Key requirements:

    • Create custom Node and LinkedList classes.
    • The LinkedList constructor should accept a list argument, but the internal storage must use nodes and pointers, not a Python list.
    • Implement a push and pop mechanism where the head of the list acts as the top of the stack.
    • The implementation must differ from a dynamic array-based stack in terms of memory footprint and time complexity (Big-O).
  7. Implement the Dominoes chain formation logic

    main

    The task is to implement the formChain method in the Dominoes class. The goal is to order a given set of Domino objects into a valid circular chain.

    Requirements for a valid chain:

    1. Adjacency Match: The dots on one half of a stone must match the dots on the neighboring half of the adjacent stone.
    2. Circular Match: The dots on the first stone's non-neighboring half must match the dots on the last stone's non-neighboring half (making the chain circular).
    3. Duplicates: The solution may use duplicate stones if multiple sets are provided.

    Example:

    • Given [2|1], [2|3], and [1|3], a valid chain is [1|2] [2|3] [3|1] because the first and last numbers match (1 == 1).
    • Given [1|2], [4|1], and [2|3], the chain [4|1] [1|2] [2|3] is invalid because 4 != 3.
  8. Understand the Graph DSL structure

    main

    The Domain Specific Language (DSL) is used to create graph data structures. A Graph object is initialized with a list of one or more tuples. Each tuple in the list must contain exactly three elements in the following order:

    1. Attributes: A dictionary (dict) representing graph-level attributes.
    2. Nodes: A list of tuples, where each tuple is (name, attrs). name must be a str and attrs must be a dict.
    3. Edges: A list of tuples, where each tuple is (src, dst, attrs). src and dst must be str, and attrs must be a dict.
  9. Implement the Robot Simulator (Step 1)

    main

    The first stage of the robot simulator involves defining basic movement and direction logic.

    Core Concepts:

    • Directions: The robot can face North (N), East (E), South (S), or West (W).
    • Movements:
      • Right(): Turns the robot 90 degrees clockwise.
      • Left(): Turns the robot 90 degrees counter-clockwise.
      • Advance(): Moves the robot one unit forward in its current direction on an infinite grid.

    Implementation Details: Directions are represented by the Dir type. The String() method on Dir provides the string representation (e.g., "N", "E").

  10. Use CodonsInfo to decode codons and translate RNA

    main

    The CodonsInfo struct provides functionality to map DNA codons (including those with ambiguous shorthand notation) to amino acid names, and to translate RNA sequences into a list of protein names.

    Key Features:

    • Shorthand Support: Supports ambiguous nucleotide shorthand (e.g., R for A or G). A codon is valid if it matches one or more canonical codons that all map to the same protein name.
    • RNA Translation: The of_rna method converts RNA (using U) to DNA (using T), segments it into codons, and translates them. Translation stops if a STOP codon is encountered.
    • Error Handling: Returns an Error if a codon is invalid, if the RNA length is not a multiple of 3, or if ambiguous codons map to different proteins.
  11. Understand Circular Buffer behavior

    main

    A circular buffer (also known as a cyclic buffer or ring buffer) is a fixed-size data structure that treats its buffer as if it were connected end-to-end.

    Key Behaviors:

    • Initialization: Starts empty with a predefined length.
    • Addition: Elements are appended to the buffer. When the buffer reaches its capacity, it is considered full.
    • Removal: Removing elements removes the oldest values in the buffer.
    • Full State: When the buffer is full, attempting to write more data will raise an error, blocking further writes until space is freed.
    • Overwrite Mode: Clients can opt for a "forced write" when the buffer is full. This overwrites the oldest data with the new elements. For example, if a buffer is full and two new elements are added via overwrite, the two oldest elements are replaced, and the new elements become the most recent. The next oldest element is then the one that was previously third-oldest.