diff --git a/GALLERY.md b/GALLERY.md index dd0b6b71..e5c3116c 100644 --- a/GALLERY.md +++ b/GALLERY.md @@ -2,6 +2,8 @@ This gallery shows examples from all available datasets using their default configurations. ## Available Datasets (101) +Legend: ✅ = Has curriculum, ❌ = No curriculum + - [ab](#ab) ✅ - [acre](#acre) ❌ - [advanced_geometry](#advanced_geometry) ✅ @@ -43,7 +45,7 @@ This gallery shows examples from all available datasets using their default conf - [gsm_symbolic](#gsm_symbolic) ❌ - [intermediate_integration](#intermediate_integration) ✅ - [isomorphic_strings](#isomorphic_strings) ✅ -- [jugs](#jugs) ❌ +- [jugs](#jugs) ✅ - [knight_swap](#knight_swap) ❌ - [knights_knaves](#knights_knaves) ❌ - [largest_island](#largest_island) ✅ @@ -2944,10 +2946,10 @@ All occurrences of a character must be replaced with another character while pre No two characters may map to the same character, but a character may map to itself. Return True if the following two strings are isomorphic, or False otherwise: -zg bn +cj oe Answer: True -Metadata: {'words': ['zg', 'bn'], 'solution': True, 'solvable': True, 'difficulty': {'string_length': 3}} +Metadata: {'words': ['cj', 'oe'], 'solution': True, 'solvable': True, 'difficulty': {'string_length': 3}} Example 2: Question: Two strings are isomorphic if the characters in one string can be replaced to get the second string. @@ -2957,10 +2959,10 @@ All occurrences of a character must be replaced with another character while pre No two characters may map to the same character, but a character may map to itself. Return True if the following two strings are isomorphic, or False otherwise: -f n +t e Answer: True -Metadata: {'words': ['f', 'n'], 'solution': True, 'solvable': True, 'difficulty': {'string_length': 2}} +Metadata: {'words': ['t', 'e'], 'solution': True, 'solvable': True, 'difficulty': {'string_length': 2}} Example 3: Question: Two strings are isomorphic if the characters in one string can be replaced to get the second string. @@ -2970,10 +2972,10 @@ All occurrences of a character must be replaced with another character while pre No two characters may map to the same character, but a character may map to itself. Return True if the following two strings are isomorphic, or False otherwise: -hogtoyty kgqwpfwf +sdjxdqxq lcdqmtqt Answer: False -Metadata: {'words': ['hogtoyty', 'kgqwpfwf'], 'solution': False, 'solvable': False, 'difficulty': {'string_length': 8}} +Metadata: {'words': ['sdjxdqxq', 'lcdqmtqt'], 'solution': False, 'solvable': False, 'difficulty': {'string_length': 8}} ```` @@ -3010,7 +3012,7 @@ How do you defuse the bomb? Reply as a JSON-parsable list of moves which result in any of the jugs being filled with the target amount. Answer: ["fill A", "pour A->C", "fill B", "empty C", "pour A->C", "empty C", "pour A->C", "empty C", "pour A->C", "pour B->C"] -Metadata: {'puzzle': {'jug_capacities': [13, 13, 4], 'target': 10, 'min_moves': 10}} +Metadata: {'puzzle': {'jug_capacities': [13, 13, 4], 'target': 10, 'min_moves': 10}, 'difficulty': {'num_jugs': 3, 'difficulty': 10}} Example 2: Question: You are a police officer. A maniac has planted a bomb next to a public fountain. @@ -3032,7 +3034,7 @@ How do you defuse the bomb? Reply as a JSON-parsable list of moves which result in any of the jugs being filled with the target amount. Answer: ["fill A", "pour A->B", "fill A", "pour A->B", "pour A->C", "fill A", "pour A->C", "empty B", "pour A->B", "fill A", "pour A->B", "fill A", "pour A->B"] -Metadata: {'puzzle': {'jug_capacities': [7, 10, 10], 'target': 5, 'min_moves': 13}} +Metadata: {'puzzle': {'jug_capacities': [7, 10, 10], 'target': 5, 'min_moves': 13}, 'difficulty': {'num_jugs': 3, 'difficulty': 10}} Example 3: Question: You are a police officer. A maniac has planted a bomb next to a public fountain. @@ -3054,7 +3056,7 @@ How do you defuse the bomb? Reply as a JSON-parsable list of moves which result in any of the jugs being filled with the target amount. Answer: ["fill B", "pour B->A", "empty A", "pour B->A", "fill B", "pour B->A", "empty A", "pour B->A", "fill B", "pour B->A", "pour B->C"] -Metadata: {'puzzle': {'jug_capacities': [7, 10, 7], 'target': 2, 'min_moves': 11}} +Metadata: {'puzzle': {'jug_capacities': [7, 10, 7], 'target': 2, 'min_moves': 11}, 'difficulty': {'num_jugs': 3, 'difficulty': 10}} ```` @@ -4569,31 +4571,31 @@ size = 500 Example tasks: ```` Example 1: -Question: Calculate the following: (-95*z**3 + 18*z)*(-12*z**2 + 78*z - 104) +Question: Calculate the following: (18*z**3 - 95*z)*(78*z**3 - 104*z**2 - 12) When performing calculations, please follow these guidelines: 1. Use ** instead of ^ to represent exponents. For example, write 7*X**2 instead of 7*X^2. 2. Always include the * symbol for all multiplication operations in your reasoning steps. For example, write `-3*X**3*sin(X) - 9*X**2*cos(X) + 18*X*sin(X) + 18*cos(X) + C` instead of `-3x3sin(x) - 9x2cos(x) + 18xsin(x) + 18cos(x) + C`. -Answer: 1140*z**5 - 7410*z**4 + 9664*z**3 + 1404*z**2 - 1872*z -Metadata: {'polynomial_expr': '(-95*z**3 + 18*z)*(-12*z**2 + 78*z - 104)', 'variables': [z], 'difficulty': {'min_terms': 2, 'max_terms': 4, 'min_value': 1, 'max_value': 100, 'min_degree': 0, 'max_degree': 3, 'min_polynomials': 2, 'max_polynomials': 3}} +Answer: 1404*z**6 - 1872*z**5 - 7410*z**4 + 9664*z**3 + 1140*z +Metadata: {'polynomial_expr': '(18*z**3 - 95*z)*(78*z**3 - 104*z**2 - 12)', 'variables': [z], 'difficulty': {'min_terms': 2, 'max_terms': 4, 'min_value': 1, 'max_value': 100, 'min_degree': 0, 'max_degree': 3, 'min_polynomials': 2, 'max_polynomials': 3}} Example 2: -Question: Simplify this expression: (-49*x**3 + 77*x + 8)*(8*x**3 - 163*x**2 - 49)*(16*x**3 + 74*x + 98) +Question: Simplify this expression: (-49*x**3 + 8*x**2 - 163)*(8*x**3 - 49*x**2 + 77*x)*(98*x**3 + 16*x**2 + 74*x) When performing calculations, please follow these guidelines: 1. Use ** instead of ^ to represent exponents. For example, write 7*X**2 instead of 7*X^2. 2. Always include the * symbol for all multiplication operations in your reasoning steps. For example, write `-3*X**3*sin(X) - 9*X**2*cos(X) + 18*X*sin(X) + 18*cos(X) + C` instead of `-3x3sin(x) - 9x2cos(x) + 18xsin(x) + 18cos(x) + C`. -Answer: -6272*x**9 + 127792*x**8 - 19152*x**7 + 391246*x**6 + 807446*x**5 - 746364*x**4 - 1091196*x**3 - 406994*x**2 - 398762*x - 38416 -Metadata: {'polynomial_expr': '(-49*x**3 + 77*x + 8)*(8*x**3 - 163*x**2 - 49)*(16*x**3 + 74*x + 98)', 'variables': [x], 'difficulty': {'min_terms': 2, 'max_terms': 4, 'min_value': 1, 'max_value': 100, 'min_degree': 0, 'max_degree': 3, 'min_polynomials': 2, 'max_polynomials': 3}} +Answer: -38416*x**9 + 235298*x**8 - 397738*x**7 + 48346*x**6 + 463508*x**5 - 1153118*x**4 + 390222*x**3 - 928774*x**2 +Metadata: {'polynomial_expr': '(-49*x**3 + 8*x**2 - 163)*(8*x**3 - 49*x**2 + 77*x)*(98*x**3 + 16*x**2 + 74*x)', 'variables': [x], 'difficulty': {'min_terms': 2, 'max_terms': 4, 'min_value': 1, 'max_value': 100, 'min_degree': 0, 'max_degree': 3, 'min_polynomials': 2, 'max_polynomials': 3}} Example 3: -Question: Calculate the following: (29*y**2 - 49*y)*(21*y**3 + 49) +Question: Calculate the following: (49*y**2 + 21)*(29*y**3 - 49*y) When performing calculations, please follow these guidelines: 1. Use ** instead of ^ to represent exponents. For example, write 7*X**2 instead of 7*X^2. 2. Always include the * symbol for all multiplication operations in your reasoning steps. For example, write `-3*X**3*sin(X) - 9*X**2*cos(X) + 18*X*sin(X) + 18*cos(X) + C` instead of `-3x3sin(x) - 9x2cos(x) + 18xsin(x) + 18cos(x) + C`. -Answer: 609*y**5 - 1029*y**4 + 1421*y**2 - 2401*y -Metadata: {'polynomial_expr': '(29*y**2 - 49*y)*(21*y**3 + 49)', 'variables': [y], 'difficulty': {'min_terms': 2, 'max_terms': 4, 'min_value': 1, 'max_value': 100, 'min_degree': 0, 'max_degree': 3, 'min_polynomials': 2, 'max_polynomials': 3}} +Answer: 1421*y**5 - 1792*y**3 - 1029*y +Metadata: {'polynomial_expr': '(49*y**2 + 21)*(29*y**3 - 49*y)', 'variables': [y], 'difficulty': {'min_terms': 2, 'max_terms': 4, 'min_value': 1, 'max_value': 100, 'min_degree': 0, 'max_degree': 3, 'min_polynomials': 2, 'max_polynomials': 3}} ```` @@ -4986,33 +4988,33 @@ Question: Given two strings representing a ransom note and a magazine, return Tr Each letter in the magazine string can only be used once in your ransom note. -Ransom note: gg -Magazine: jg +Ransom note: jj +Magazine: nj Answer: False -Metadata: {'ransom_note': 'gg', 'magazine': 'jg', 'solution': False, 'solvable': False, 'difficulty': {'note_length': 2, 'magazine_length': 2}} +Metadata: {'ransom_note': 'jj', 'magazine': 'nj', 'solution': False, 'solvable': False, 'difficulty': {'note_length': 2, 'magazine_length': 2}} Example 2: Question: Given two strings representing a ransom note and a magazine, return True if you can construct the ransom note using the letters in the magazine, and False otherwise. Each letter in the magazine string can only be used once in your ransom note. -Ransom note: q -Magazine: ishmdfkzuhv +Ransom note: r +Magazine: vipyjtlzxpb Answer: False -Metadata: {'ransom_note': 'q', 'magazine': 'ishmdfkzuhv', 'solution': False, 'solvable': False, 'difficulty': {'note_length': 1, 'magazine_length': 11}} +Metadata: {'ransom_note': 'r', 'magazine': 'vipyjtlzxpb', 'solution': False, 'solvable': False, 'difficulty': {'note_length': 1, 'magazine_length': 11}} Example 3: Question: Given two strings representing a ransom note and a magazine, return True if you can construct the ransom note using the letters in the magazine, and False otherwise. Each letter in the magazine string can only be used once in your ransom note. -Ransom note: otgegyu -Magazine: ivxiiacuuagotqfppkoggge +Ransom note: dxjijqv +Magazine: vbfvvsgxvsjdxdtmmlhcjci Answer: False -Metadata: {'ransom_note': 'otgegyu', 'magazine': 'ivxiiacuuagotqfppkoggge', 'solution': False, 'solvable': False, 'difficulty': {'note_length': 7, 'magazine_length': 23}} +Metadata: {'ransom_note': 'dxjijqv', 'magazine': 'vbfvvsgxvsjdxdtmmlhcjci', 'solution': False, 'solvable': False, 'difficulty': {'note_length': 7, 'magazine_length': 23}} ```` @@ -6935,7 +6937,7 @@ Metadata: {'task_type': 'datetime_tz', 'start_time': datetime.datetime(2964, 6, Example 2: Question: A video call started at 09:44 and ended at 12:22. How long was the call? Answer in HH:MM. Answer: 02:38 -Metadata: {'task_type': 'time', 'start_time': datetime.datetime(2025, 3, 14, 9, 44), 'end_time': datetime.datetime(2025, 3, 14, 12, 22), 'format': '%H:%M', 'expected_format': 'HH:MM', 'difficulty': {'max_time_difference_seconds': 86400, 'max_date_difference_days': 100}} +Metadata: {'task_type': 'time', 'start_time': datetime.datetime(2025, 3, 16, 9, 44), 'end_time': datetime.datetime(2025, 3, 16, 12, 22), 'format': '%H:%M', 'expected_format': 'HH:MM', 'difficulty': {'max_time_difference_seconds': 86400, 'max_date_difference_days': 100}} Example 3: Question: Calculate the time difference between Sat Dec 22 2677 and Thu Mar 21 2678. Express the result in D days. @@ -7194,7 +7196,7 @@ Example 1: Question: Transform the word ladder 'HAND' to 'GLEE' by changing one letter at a time. Provide your answer as a comma-separated sequence of uppercase letters without spaces. Each step must be a valid English word. -Answer: HAND,HARD,HERD,HEED,FEED,FLED,FLEE,GLEE +Answer: HAND,LAND,LEND,FEND,FEED,FLED,FLEE,GLEE Metadata: {'start_word': 'HAND', 'end_word': 'GLEE', 'word_length': 4, 'chain_length': 8, 'difficulty': {'word_length': 4, 'chain_length': 8}} Example 2: diff --git a/reasoning_gym/algebra/complex_arithmetic.py b/reasoning_gym/algebra/complex_arithmetic.py index 1175d92f..5c641ba2 100644 --- a/reasoning_gym/algebra/complex_arithmetic.py +++ b/reasoning_gym/algebra/complex_arithmetic.py @@ -4,7 +4,7 @@ import random from dataclasses import dataclass, field from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -191,46 +191,31 @@ class ComplexArithmeticCurriculum(BaseCurriculum): name="min_real", field_name="min_real", levels=[-10, -100, -10000, -100000000], - default_level=0, description="Minimum real part for complex numbers", - attr_type=AttributeType.STATIC, - min_value=-10, ), ScalarAttributeDefinition( name="max_real", field_name="max_real", levels=[10, 100, 10000, 100000000], - default_level=0, description="Maximum real part for complex numbers", - attr_type=AttributeType.STATIC, - min_value=10, ), ScalarAttributeDefinition( name="min_imag", field_name="min_imag", levels=[-10, -100, -10000, -100000000], - default_level=0, description="Minimum imaginary part for complex numbers", - attr_type=AttributeType.STATIC, - min_value=-10, ), ScalarAttributeDefinition( name="max_imag", field_name="max_imag", levels=[10, 100, 10000, 100000000], - default_level=0, description="Maximum imaginary part for complex numbers", - attr_type=AttributeType.STATIC, - min_value=10, ), ScalarAttributeDefinition( name="operations_weights", field_name="operations_weights", levels=[[0.4, 0.4, 0.1, 0.1], [0.25, 0.25, 0.25, 0.25], [0.2, 0.2, 0.3, 0.3], [0.1, 0.1, 0.4, 0.4]], - default_level=0, description="Operations weights to sample operation to use for each complex arithmetic problem", - attr_type=AttributeType.STATIC, - min_value=[0.4, 0.4, 0.1, 0.1], ), ) diff --git a/reasoning_gym/algebra/intermediate_integration.py b/reasoning_gym/algebra/intermediate_integration.py index 06a4288f..bed3cd67 100644 --- a/reasoning_gym/algebra/intermediate_integration.py +++ b/reasoning_gym/algebra/intermediate_integration.py @@ -4,7 +4,7 @@ from typing import Any, Optional import sympy -from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -286,10 +286,7 @@ class IntermediateIntegrationCurriculum(BaseCurriculum): [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 1], ], - default_level=0, description="The weights of the problem types", - attr_type=AttributeType.STATIC, - min_value=[1, 0, 0, 0, 0, 0, 0, 0], ) ) diff --git a/reasoning_gym/algebra/polynomial_equations.py b/reasoning_gym/algebra/polynomial_equations.py index 58a97865..83576a0a 100644 --- a/reasoning_gym/algebra/polynomial_equations.py +++ b/reasoning_gym/algebra/polynomial_equations.py @@ -5,7 +5,7 @@ from typing import Any, Optional from sympy import Eq, Symbol, expand, solve -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -277,9 +277,6 @@ class PolynomialEquationsCurriculum(BaseCurriculum): RangeAttributeDefinition( name="degree", levels=[1, 2, 3, 4], - default_level=0, - min_value=1, - attr_type=AttributeType.APPEND, lower_field_name="min_degree", upper_field_name="max_degree", description="The degree of the polynomial equation", @@ -287,9 +284,6 @@ class PolynomialEquationsCurriculum(BaseCurriculum): RangeAttributeDefinition( name="terms", levels=[2, 3, 4, 5], - default_level=0, - min_value=2, - attr_type=AttributeType.APPEND, lower_field_name="min_terms", upper_field_name="max_terms", description="The number of terms in the polynomial equation", diff --git a/reasoning_gym/algebra/polynomial_multiplication.py b/reasoning_gym/algebra/polynomial_multiplication.py index 8c913203..d3ba1c12 100644 --- a/reasoning_gym/algebra/polynomial_multiplication.py +++ b/reasoning_gym/algebra/polynomial_multiplication.py @@ -5,7 +5,7 @@ from typing import Any, Optional import sympy as sp from sympy.polys.monomials import itermonomials -from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -182,73 +182,49 @@ class PolynomialMultiplicationCurriculum(BaseCurriculum): name="min_terms", field_name="min_terms", levels=[2, 4, 6, 8], - default_level=0, description="Minimum number of terms in polynomial expressions", - attr_type=AttributeType.STATIC, - min_value=2, ), ScalarAttributeDefinition( name="max_terms", field_name="max_terms", levels=[4, 8, 12, 16], - default_level=0, description="Maximum number of terms in polynomial expressions", - attr_type=AttributeType.STATIC, - min_value=4, ), ScalarAttributeDefinition( name="min_value", field_name="min_value", levels=[1, 10, 100, 1000], - default_level=0, description="Minimum value for coefficients", - attr_type=AttributeType.STATIC, - min_value=1, ), ScalarAttributeDefinition( name="max_value", field_name="max_value", levels=[100, 10000, 1000000, 100000000], - default_level=0, description="Maximum value for coefficients", - attr_type=AttributeType.STATIC, - min_value=100, ), ScalarAttributeDefinition( name="min_degree", field_name="min_degree", levels=[0, 1, 2, 3], - default_level=0, description="Minimum polynomial degree", - attr_type=AttributeType.STATIC, - min_value=0, ), ScalarAttributeDefinition( name="max_degree", field_name="max_degree", levels=[2, 4, 8, 10], - default_level=0, description="Maximum polynomial degree", - attr_type=AttributeType.STATIC, - min_value=2, ), ScalarAttributeDefinition( name="min_polynomials", field_name="min_polynomials", levels=[2, 3, 4, 5], - default_level=0, description="Minimum number of polynomials being multiplied", - attr_type=AttributeType.STATIC, - min_value=2, ), ScalarAttributeDefinition( name="max_polynomials", field_name="max_polynomials", levels=[4, 6, 8, 10], - default_level=0, description="Maximum number of polynomials being multiplied", - attr_type=AttributeType.STATIC, - min_value=2, ), ) diff --git a/reasoning_gym/algebra/simple_equations.py b/reasoning_gym/algebra/simple_equations.py index a529c99e..389e560d 100644 --- a/reasoning_gym/algebra/simple_equations.py +++ b/reasoning_gym/algebra/simple_equations.py @@ -5,7 +5,7 @@ from typing import Optional from sympy import Symbol -from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -137,46 +137,31 @@ class SimpleEquationsCurriculum(BaseCurriculum): name="min_terms", field_name="min_terms", levels=[2, 3, 4, 5], - default_level=0, description="Minimum number of terms in simple equations", - attr_type=AttributeType.STATIC, - min_value=-2, ), ScalarAttributeDefinition( name="max_terms", field_name="max_terms", levels=[5, 10, 15, 20], - default_level=0, description="Maximum number of terms in simple equations", - attr_type=AttributeType.STATIC, - min_value=5, ), ScalarAttributeDefinition( name="min_value", field_name="min_value", levels=[1, 10, 100, 1000], - default_level=0, description="Minimum value for constants in simple equations", - attr_type=AttributeType.STATIC, - min_value=1, ), ScalarAttributeDefinition( name="max_value", field_name="max_value", levels=[100, 10000, 1000000, 100000000], - default_level=0, description="Maximum value for constants in simple equations", - attr_type=AttributeType.STATIC, - min_value=100, ), ScalarAttributeDefinition( name="operators_weights", field_name="operators_weights", levels=[[0.4, 0.4, 0.2], [0.35, 0.35, 0.3], [0.3, 0.3, 0.4], [0.2, 0.2, 0.6]], - default_level=0, description="Weights for each operator in simple equations", - attr_type=AttributeType.STATIC, - min_value=[0.4, 0.4, 0.2], ), ) diff --git a/reasoning_gym/algebra/simple_integration.py b/reasoning_gym/algebra/simple_integration.py index 3e9df2dc..610aa7fe 100644 --- a/reasoning_gym/algebra/simple_integration.py +++ b/reasoning_gym/algebra/simple_integration.py @@ -5,7 +5,7 @@ from typing import Any, Optional import sympy -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -118,9 +118,6 @@ class SimpleIntegrationCurriculum(BaseCurriculum): RangeAttributeDefinition( name="terms", levels=[2, 3, 4, 5], - default_level=0, - min_value=2, - attr_type=AttributeType.APPEND, lower_field_name="min_terms", upper_field_name="max_terms", description="The number of terms in the polynomial", diff --git a/reasoning_gym/algorithmic/ab.py b/reasoning_gym/algorithmic/ab.py index ff488a0e..9dad7f0f 100644 --- a/reasoning_gym/algorithmic/ab.py +++ b/reasoning_gym/algorithmic/ab.py @@ -2,7 +2,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -152,10 +152,7 @@ class ABCurriculum(BaseCurriculum): name="length", field_name="length", levels=[1, 10, 50, 100], - default_level=0, description="Length of the A::B program", - attr_type=AttributeType.STATIC, - min_value=1, ) ) diff --git a/reasoning_gym/algorithmic/base_conversion.py b/reasoning_gym/algorithmic/base_conversion.py index 15607ed4..bea8bbbf 100644 --- a/reasoning_gym/algorithmic/base_conversion.py +++ b/reasoning_gym/algorithmic/base_conversion.py @@ -4,7 +4,7 @@ from dataclasses import dataclass from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """Your task is to convert a number between two different bases. @@ -126,22 +126,18 @@ class BaseConversionCurriculum(BaseCurriculum): RangeAttributeDefinition( name="base", levels=[2, 9, 18, 27, 36], - default_level=1, description="The base of the number system", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_base", upper_field_name="max_base", + ensure_interval=True, ), RangeAttributeDefinition( name="value", levels=[1_000, 10_000, 100_000, 1_000_000], - default_level=0, description="The value to convert", - attr_type=AttributeType.APPEND, - min_value=0, lower_field_name="min_value", upper_field_name="max_value", + ensure_interval=True, ), ) diff --git a/reasoning_gym/algorithmic/binary_alternation.py b/reasoning_gym/algorithmic/binary_alternation.py index 7180291d..42d3b17f 100644 --- a/reasoning_gym/algorithmic/binary_alternation.py +++ b/reasoning_gym/algorithmic/binary_alternation.py @@ -7,7 +7,7 @@ from dataclasses import dataclass from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """Given a binary string, return the minimum number of character swaps to make it alternating, or -1 if it is impossible. @@ -122,10 +122,7 @@ class BinaryAlternationCurriculum(BaseCurriculum): RangeAttributeDefinition( name="n", levels=[10, 50, 500, 1000], - default_level=0, description="Number of bits in the binary string", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_n", upper_field_name="max_n", ) diff --git a/reasoning_gym/algorithmic/binary_matrix.py b/reasoning_gym/algorithmic/binary_matrix.py index 9a1c2e32..b90215d3 100644 --- a/reasoning_gym/algorithmic/binary_matrix.py +++ b/reasoning_gym/algorithmic/binary_matrix.py @@ -9,7 +9,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """Given a square matrix, your job is to find the taxicab (Manhattan) distance of the nearest 0 for each cell. @@ -147,18 +147,12 @@ class BinaryMatrixCurriculum(BaseCurriculum): name="p_zero", field_name="p_zero", levels=[0.5, 0.25, 0.1, 0.05], - default_level=0, description="Board size", - attr_type=AttributeType.STATIC, - min_value=0, ), RangeAttributeDefinition( name="n", levels=[10, 50, 250, 1000], - default_level=0, description="Board size", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_n", upper_field_name="max_n", ), diff --git a/reasoning_gym/algorithmic/caesar_cipher.py b/reasoning_gym/algorithmic/caesar_cipher.py index 6a69159a..579a35ca 100644 --- a/reasoning_gym/algorithmic/caesar_cipher.py +++ b/reasoning_gym/algorithmic/caesar_cipher.py @@ -4,7 +4,7 @@ from dataclasses import dataclass from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..data import read_data_file from ..factory import ProceduralDataset, register_dataset @@ -98,18 +98,14 @@ class CaesarCipherCurriculum(BaseCurriculum): RangeAttributeDefinition( name="rotation", levels=[5, 10, 15, 25], - default_level=0, description="Max rotation for cipher", - attr_type=AttributeType.APPEND, lower_field_name="min_rotation", upper_field_name="max_rotation", ), RangeAttributeDefinition( name="words", levels=[5, 10, 15, 25], - default_level=0, description="Max number of words", - attr_type=AttributeType.APPEND, lower_field_name="min_words", upper_field_name="max_words", ), diff --git a/reasoning_gym/algorithmic/count_primes.py b/reasoning_gym/algorithmic/count_primes.py index 8620bf29..af0bf84f 100644 --- a/reasoning_gym/algorithmic/count_primes.py +++ b/reasoning_gym/algorithmic/count_primes.py @@ -9,7 +9,7 @@ from dataclasses import dataclass from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """Count how many prime numbers there are between {start} and {end} (inclusive) ?""" @@ -80,10 +80,7 @@ class CountPrimesCurriculum(BaseCurriculum): RangeAttributeDefinition( name="n", levels=[1000, 10_000, 50_000, 100_000], - default_level=0, description="Up to which number to consider the primes", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_n", upper_field_name="max_n", ) diff --git a/reasoning_gym/algorithmic/cryptarithm.py b/reasoning_gym/algorithmic/cryptarithm.py index b3f7d767..3ca9c6a0 100644 --- a/reasoning_gym/algorithmic/cryptarithm.py +++ b/reasoning_gym/algorithmic/cryptarithm.py @@ -15,7 +15,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -253,12 +253,10 @@ class CryptarithmCurriculum(BaseCurriculum): RangeAttributeDefinition( name="words", levels=[2, 5, 10, 50], - default_level=1, description="Number of words in the cryptarithm puzzle", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_words", upper_field_name="max_words", + ensure_interval=True, ) ) diff --git a/reasoning_gym/algorithmic/game_of_life.py b/reasoning_gym/algorithmic/game_of_life.py index 12857e52..f1c2fa78 100644 --- a/reasoning_gym/algorithmic/game_of_life.py +++ b/reasoning_gym/algorithmic/game_of_life.py @@ -5,7 +5,7 @@ from typing import Any, Optional import cellpylib as cpl -from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -163,38 +163,26 @@ class GameOfLifeCurriculum(BaseCurriculum): name="grid_size_x", field_name="grid_size_x", levels=[10, 100, 500, 999], - default_level=0, description="Grid size in the x direction", - attr_type=AttributeType.STATIC, - min_value=10, ), ScalarAttributeDefinition( name="grid_size_y", field_name="grid_size_y", levels=[10, 100, 500, 999], - default_level=0, description="Grid size in the y direction", - attr_type=AttributeType.STATIC, - min_value=-10, ), # Filled cells should be 10%, 20%, 30%, 50% of the grid_size_x * grid_size_y ScalarAttributeDefinition( name="filled_cells_weights", field_name="filled_cells_weights", levels=[0.1, 0.2, 0.5, 0.8], - default_level=0, description="Percentage of filled cells in the grid", - attr_type=AttributeType.STATIC, - min_value=0.1, ), ScalarAttributeDefinition( name="simulation_steps", field_name="simulation_steps", levels=[1, 2, 5, 10], - default_level=0, description="Number of simulation steps to run", - attr_type=AttributeType.STATIC, - min_value=1, ), ) diff --git a/reasoning_gym/algorithmic/game_of_life_halting.py b/reasoning_gym/algorithmic/game_of_life_halting.py index a9c19868..e5b464c4 100644 --- a/reasoning_gym/algorithmic/game_of_life_halting.py +++ b/reasoning_gym/algorithmic/game_of_life_halting.py @@ -4,7 +4,7 @@ from typing import Dict, List, Optional import cellpylib as cpl -from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -402,46 +402,31 @@ class GameOfLifeHaltingCurriculum(BaseCurriculum): name="grid_size_x", field_name="grid_size_x", levels=[12, 25, 50, 200], - default_level=0, description="Grid size in the x direction", - attr_type=AttributeType.STATIC, - min_value=12, ), ScalarAttributeDefinition( name="grid_size_y", field_name="grid_size_y", levels=[12, 25, 50, 200], - default_level=0, description="Grid size in the y direction", - attr_type=AttributeType.STATIC, - min_value=12, ), ScalarAttributeDefinition( name="difficulty", field_name="difficulty", levels=[1, 2, 3], - default_level=0, description="Oscillator type difficulty", - attr_type=AttributeType.STATIC, - min_value=1, ), ScalarAttributeDefinition( name="num_oscillators", field_name="num_oscillators", levels=[3, 7, 10, 20], - default_level=0, description="Number of oscillators to place", - attr_type=AttributeType.STATIC, - min_value=3, ), ScalarAttributeDefinition( name="max_simulation_steps", field_name="max_simulation_steps", levels=[20, 50, 100, 200], - default_level=0, description="Number of simulation steps to query", - attr_type=AttributeType.STATIC, - min_value=20, ), ) diff --git a/reasoning_gym/algorithmic/graph_color.py b/reasoning_gym/algorithmic/graph_color.py index 4dc57589..75c99e05 100644 --- a/reasoning_gym/algorithmic/graph_color.py +++ b/reasoning_gym/algorithmic/graph_color.py @@ -3,7 +3,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -255,10 +255,7 @@ class GraphColorCurriculum(BaseCurriculum): RangeAttributeDefinition( name="num_vertices", levels=[10, 20, 25, 50], - default_level=0, description="Number of vertices in the graph", - attr_type=AttributeType.STATIC, - min_value=10, lower_field_name="min_num_vertices", upper_field_name="max_num_vertices", ), @@ -266,10 +263,7 @@ class GraphColorCurriculum(BaseCurriculum): name="num_colors", field_name="num_colors", levels=[5, 4, 3], - default_level=0, description="Number of colors in the graph", - attr_type=AttributeType.STATIC, - min_value=3, ), ) diff --git a/reasoning_gym/algorithmic/group_anagrams.py b/reasoning_gym/algorithmic/group_anagrams.py index 7fe200cc..ec212843 100644 --- a/reasoning_gym/algorithmic/group_anagrams.py +++ b/reasoning_gym/algorithmic/group_anagrams.py @@ -12,7 +12,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..data import get_data_file_path from ..factory import ProceduralDataset, register_dataset @@ -133,20 +133,14 @@ class GroupAnagramsCurriculum(BaseCurriculum): RangeAttributeDefinition( name="anagram_groups", levels=[10, 100, 1_000, 10_000], - default_level=0, description="Number of anagram groups in the input", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_anagram_groups", upper_field_name="max_anagram_groups", ), RangeAttributeDefinition( name="words_per_group", levels=[2, 5, 10, 20], - default_level=0, description="Number of words in a single anagram group", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_words_per_group", upper_field_name="max_words_per_group", ), diff --git a/reasoning_gym/algorithmic/isomorphic_strings.py b/reasoning_gym/algorithmic/isomorphic_strings.py index 0edd3a16..1b539383 100644 --- a/reasoning_gym/algorithmic/isomorphic_strings.py +++ b/reasoning_gym/algorithmic/isomorphic_strings.py @@ -10,7 +10,7 @@ from dataclasses import dataclass from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """Two strings are isomorphic if the characters in one string can be replaced to get the second string. @@ -126,10 +126,7 @@ class IsomorphicStringsCurriculum(BaseCurriculum): RangeAttributeDefinition( name="string_length", levels=[10, 50, 100, 1000], - default_level=0, description="Length of the strings", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_string_length", upper_field_name="max_string_length", ) diff --git a/reasoning_gym/algorithmic/jugs.py b/reasoning_gym/algorithmic/jugs.py index c0077a23..3dbf84d4 100644 --- a/reasoning_gym/algorithmic/jugs.py +++ b/reasoning_gym/algorithmic/jugs.py @@ -6,7 +6,7 @@ from functools import reduce from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -329,19 +329,13 @@ class JugsCurriculum(BaseCurriculum): name="num_jugs", field_name="num_jugs", levels=[3, 4, 5, 7], - default_level=0, description="Number of jugs in the puzzle", - attr_type=AttributeType.STATIC, - min_value=3, ), ScalarAttributeDefinition( name="difficulty", field_name="difficulty", levels=[2, 4, 6, 8], - default_level=0, description="Minimum required moves to solve the puzzle", - attr_type=AttributeType.STATIC, - min_value=10, ), ) diff --git a/reasoning_gym/algorithmic/letter_counting.py b/reasoning_gym/algorithmic/letter_counting.py index 43d49178..e2262ffd 100644 --- a/reasoning_gym/algorithmic/letter_counting.py +++ b/reasoning_gym/algorithmic/letter_counting.py @@ -7,7 +7,7 @@ from typing import Optional from reasoning_gym.data import read_data_file -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -81,12 +81,10 @@ class LetterCountingCurriculum(BaseCurriculum): RangeAttributeDefinition( name="words", levels=[10, 50, 100, 1000], - default_level=1, description="Number of words in the span", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_words", upper_field_name="max_words", + ensure_interval=True, ), ) diff --git a/reasoning_gym/algorithmic/letter_jumble.py b/reasoning_gym/algorithmic/letter_jumble.py index 61c49174..0e896b93 100644 --- a/reasoning_gym/algorithmic/letter_jumble.py +++ b/reasoning_gym/algorithmic/letter_jumble.py @@ -7,7 +7,7 @@ from typing import Any, Optional from reasoning_gym.data import read_data_file -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """Your task is to unsramble words in a sentence. @@ -169,32 +169,26 @@ class LetterJumbleCurriculum(BaseCurriculum): RangeAttributeDefinition( name="word_len", levels=[5, 15, 30, 50], - default_level=1, description="Word length", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_word_len", upper_field_name="max_word_len", + ensure_interval=True, ), RangeAttributeDefinition( name="words", levels=[10, 50, 100, 500], - default_level=1, description="Number of words", - attr_type=AttributeType.APPEND, - min_value=5, lower_field_name="min_words", upper_field_name="max_words", + ensure_interval=True, ), RangeAttributeDefinition( name="corruption_level", levels=[0.1, 0.3, 0.6, 0.9], - default_level=1, description="Corruption level", - attr_type=AttributeType.APPEND, - min_value=0.0, lower_field_name="min_corruption_level", upper_field_name="max_corruption_level", + ensure_interval=True, ), ) diff --git a/reasoning_gym/algorithmic/manipulate_matrix.py b/reasoning_gym/algorithmic/manipulate_matrix.py index f82ef736..e6193388 100644 --- a/reasoning_gym/algorithmic/manipulate_matrix.py +++ b/reasoning_gym/algorithmic/manipulate_matrix.py @@ -7,7 +7,7 @@ from typing import Any, Optional import numpy as np -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """For the following matrix: @@ -327,30 +327,21 @@ class ManipulateMatrixCurriculum(BaseCurriculum): RangeAttributeDefinition( name="rows", levels=[10, 25, 50, 100], - default_level=0, description="Number of rows in the matrix", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_rows", upper_field_name="max_rows", ), RangeAttributeDefinition( name="cols", levels=[10, 25, 50, 100], - default_level=0, description="Number of columns in the matrix", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_cols", upper_field_name="max_cols", ), RangeAttributeDefinition( name="num_transforms", levels=[5, 10, 20, 30], - default_level=0, description="Number of transformations to apply", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_transforms", upper_field_name="max_transforms", ), diff --git a/reasoning_gym/algorithmic/number_filtering.py b/reasoning_gym/algorithmic/number_filtering.py index 523933bf..6eeb335f 100644 --- a/reasoning_gym/algorithmic/number_filtering.py +++ b/reasoning_gym/algorithmic/number_filtering.py @@ -4,7 +4,7 @@ from dataclasses import dataclass from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -113,32 +113,26 @@ class NumberFilteringCurriculum(BaseCurriculum): RangeAttributeDefinition( name="numbers", levels=[10, 100, 500, 1000], - default_level=1, description="How many numbers to sort", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_numbers", upper_field_name="max_numbers", + ensure_interval=True, ), RangeAttributeDefinition( name="decimals", levels=[0, 2, 4, 6], - default_level=1, description="Number of decimal places", - attr_type=AttributeType.APPEND, - min_value=0, lower_field_name="min_decimals", upper_field_name="max_decimals", + ensure_interval=True, ), RangeAttributeDefinition( name="value", levels=[-10_000, 10_000], - default_level=1, description="Range of numbers to sort", - attr_type=AttributeType.APPEND, - min_value=-10_000, lower_field_name="min_value", upper_field_name="max_value", + ensure_interval=True, ), ) diff --git a/reasoning_gym/algorithmic/number_sorting.py b/reasoning_gym/algorithmic/number_sorting.py index 3c02896c..d3dae5aa 100644 --- a/reasoning_gym/algorithmic/number_sorting.py +++ b/reasoning_gym/algorithmic/number_sorting.py @@ -4,7 +4,7 @@ from dataclasses import dataclass from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -110,32 +110,26 @@ class NumberSortingCurriculum(BaseCurriculum): RangeAttributeDefinition( name="numbers", levels=[10, 100, 500, 1000], - default_level=1, description="How many numbers to sort", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_numbers", upper_field_name="max_numbers", + ensure_interval=True, ), RangeAttributeDefinition( name="decimals", levels=[0, 2, 4, 6], - default_level=1, description="Number of decimal places", - attr_type=AttributeType.APPEND, - min_value=0, lower_field_name="min_decimals", upper_field_name="max_decimals", + ensure_interval=True, ), RangeAttributeDefinition( name="value", levels=[-10_000, 10_000], - default_level=1, description="Range of numbers to sort", - attr_type=AttributeType.APPEND, - min_value=-10_000, lower_field_name="min_value", upper_field_name="max_value", + ensure_interval=True, ), ) diff --git a/reasoning_gym/algorithmic/palindrome_generation.py b/reasoning_gym/algorithmic/palindrome_generation.py index dd130036..157d780d 100644 --- a/reasoning_gym/algorithmic/palindrome_generation.py +++ b/reasoning_gym/algorithmic/palindrome_generation.py @@ -3,7 +3,7 @@ import string from dataclasses import dataclass from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPALTE = """Your task is, given a list of letters, to form a valid palindrome. @@ -129,12 +129,10 @@ class PalindromeCurriculum(BaseCurriculum): RangeAttributeDefinition( name="length", levels=[10, 50, 100, 500], - default_level=1, description="Length of the generated palindrome.", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_length", upper_field_name="max_length", + ensure_interval=True, ) ) diff --git a/reasoning_gym/algorithmic/palindrome_partitioning.py b/reasoning_gym/algorithmic/palindrome_partitioning.py index 52637772..103a6fbb 100644 --- a/reasoning_gym/algorithmic/palindrome_partitioning.py +++ b/reasoning_gym/algorithmic/palindrome_partitioning.py @@ -10,7 +10,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """Given a string, partition it such that every substring is a palindrome. @@ -156,20 +156,14 @@ class PalindromePartitioningCurriculum(BaseCurriculum): RangeAttributeDefinition( name="string_len", levels=[10, 100, 500, 1000], - default_level=0, description="Length of the string", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_string_len", upper_field_name="max_string_len", ), RangeAttributeDefinition( name="substring_palindrome_len", levels=[5, 10, 50, 100], - default_level=0, description="Length of the substring palindrome", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_substring_palindrome_len", upper_field_name="max_substring_palindrome_len", ), diff --git a/reasoning_gym/algorithmic/pool_matrix.py b/reasoning_gym/algorithmic/pool_matrix.py index 7e2acabc..24af56f9 100644 --- a/reasoning_gym/algorithmic/pool_matrix.py +++ b/reasoning_gym/algorithmic/pool_matrix.py @@ -6,7 +6,7 @@ from typing import Any, Optional import numpy as np -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """Your job is to perform max/average pooling on the given matrix. @@ -134,30 +134,21 @@ class PoolMatrixCurriculum(BaseCurriculum): RangeAttributeDefinition( name="rows", levels=[10, 25, 50, 100], - default_level=0, description="Board size", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_rows", upper_field_name="max_rows", ), RangeAttributeDefinition( name="cols", levels=[10, 25, 50, 100], - default_level=0, description="Board size", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_cols", upper_field_name="max_cols", ), RangeAttributeDefinition( name="pool_size", levels=[3, 5, 7, 9], - default_level=0, description="Pool size", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_pool_size", upper_field_name="max_pool_size", ), diff --git a/reasoning_gym/algorithmic/ransom_note.py b/reasoning_gym/algorithmic/ransom_note.py index 108c5b64..23851e11 100644 --- a/reasoning_gym/algorithmic/ransom_note.py +++ b/reasoning_gym/algorithmic/ransom_note.py @@ -9,7 +9,7 @@ from dataclasses import dataclass from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """Given two strings representing a ransom note and a magazine, return True if you can construct the ransom note using the letters in the magazine, and False otherwise. @@ -120,20 +120,14 @@ class RansomNoteCurriculum(BaseCurriculum): RangeAttributeDefinition( name="note_length", levels=[10, 50, 100, 500], - default_level=0, description="Length of the ransom note", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_note_length", upper_field_name="max_note_length", ), RangeAttributeDefinition( name="magazine_length", levels=[50, 100, 500, 1000], - default_level=0, description="Length of the magazine", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_magazine_length", upper_field_name="max_magazine_length", ), diff --git a/reasoning_gym/algorithmic/rotate_matrix.py b/reasoning_gym/algorithmic/rotate_matrix.py index 7df1fba2..ee91f8d1 100644 --- a/reasoning_gym/algorithmic/rotate_matrix.py +++ b/reasoning_gym/algorithmic/rotate_matrix.py @@ -9,7 +9,7 @@ from dataclasses import dataclass from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """Given a square matrix, your job is to rotate it clockwise. @@ -103,20 +103,14 @@ class RotateMatrixCurriculum(BaseCurriculum): RangeAttributeDefinition( name="n", levels=[10, 25, 50, 100], - default_level=0, description="Size of the square matrix", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_n", upper_field_name="max_n", ), RangeAttributeDefinition( name="num_rotations", levels=[4, 8, 12, 16], - default_level=0, description="Number of 90-degree rotations", - attr_type=AttributeType.APPEND, - min_value=0, lower_field_name="min_rotations", upper_field_name="max_rotations", ), diff --git a/reasoning_gym/algorithmic/rotten_oranges.py b/reasoning_gym/algorithmic/rotten_oranges.py index 3995fcc4..f1de4318 100644 --- a/reasoning_gym/algorithmic/rotten_oranges.py +++ b/reasoning_gym/algorithmic/rotten_oranges.py @@ -9,7 +9,7 @@ from dataclasses import dataclass from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """You are given an n x n grid where each cell can have one of three values: @@ -136,10 +136,7 @@ class RottenOrangesCurriculum(BaseCurriculum): RangeAttributeDefinition( name="n", levels=[10, 25, 50, 100], - default_level=0, description="Size of the square matrix", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_n", upper_field_name="max_n", ) diff --git a/reasoning_gym/algorithmic/sentence_reordering.py b/reasoning_gym/algorithmic/sentence_reordering.py index 3cc697d4..c5eab985 100644 --- a/reasoning_gym/algorithmic/sentence_reordering.py +++ b/reasoning_gym/algorithmic/sentence_reordering.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..data import read_data_file from ..factory import ProceduralDataset, register_dataset @@ -124,12 +124,10 @@ class SentenceReorderingCurriculum(BaseCurriculum): RangeAttributeDefinition( name="words_in_sentence", levels=[5, 20, 50, 100], - default_level=1, description="Number of words in the sentence", - attr_type=AttributeType.APPEND, - min_value=3, lower_field_name="min_words_in_sentence", upper_field_name="max_words_in_sentence", + ensure_interval=True, ), ) diff --git a/reasoning_gym/algorithmic/spell_backward.py b/reasoning_gym/algorithmic/spell_backward.py index c2e9d767..24d980db 100644 --- a/reasoning_gym/algorithmic/spell_backward.py +++ b/reasoning_gym/algorithmic/spell_backward.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..data import read_data_file from ..factory import ProceduralDataset, register_dataset @@ -81,12 +81,10 @@ class SpellBackwardCurriculum(BaseCurriculum): RangeAttributeDefinition( name="word_len", levels=[5, 10, 20, 30], - default_level=1, description="Word length", - attr_type=AttributeType.APPEND, - min_value=3, lower_field_name="min_word_len", upper_field_name="max_word_len", + ensure_interval=True, ), ) diff --git a/reasoning_gym/algorithmic/spiral_matrix.py b/reasoning_gym/algorithmic/spiral_matrix.py index 52bf2785..b5001e64 100644 --- a/reasoning_gym/algorithmic/spiral_matrix.py +++ b/reasoning_gym/algorithmic/spiral_matrix.py @@ -8,7 +8,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """Given a matrix, your job is to generate a list of elements in spiral order, starting from the top-left element. @@ -148,10 +148,7 @@ class SpiralMatrixCurriculum(BaseCurriculum): RangeAttributeDefinition( name="n", levels=[10, 25, 50, 100], - default_level=0, description="Number of rows/cols in the matrix", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_n", upper_field_name="max_n", ) diff --git a/reasoning_gym/algorithmic/string_insertion.py b/reasoning_gym/algorithmic/string_insertion.py index 6b5956c2..02ae4ea1 100644 --- a/reasoning_gym/algorithmic/string_insertion.py +++ b/reasoning_gym/algorithmic/string_insertion.py @@ -7,7 +7,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """Given a string consisting of characters A, B, C, D, and E, your job is to insert a character according to the following pattern: @@ -120,12 +120,10 @@ class StringInsertionCurriculum(BaseCurriculum): RangeAttributeDefinition( name="string_length", levels=[10, 50, 100, 1000], - default_level=1, description="Length of the string", - attr_type=AttributeType.APPEND, - min_value=5, lower_field_name="min_string_length", upper_field_name="max_string_length", + ensure_interval=True, ), ) diff --git a/reasoning_gym/algorithmic/string_manipulation.py b/reasoning_gym/algorithmic/string_manipulation.py index 92125f84..73deb1de 100644 --- a/reasoning_gym/algorithmic/string_manipulation.py +++ b/reasoning_gym/algorithmic/string_manipulation.py @@ -7,7 +7,7 @@ from dataclasses import dataclass from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """Your job is to repeatedly transform a string according to a set of rules until no further transformations can be performed, or a state is repeated. @@ -200,20 +200,14 @@ class StringManipulationCurriculum(BaseCurriculum): RangeAttributeDefinition( name="string_length", levels=[10, 50, 100, 500], - default_level=0, description="Length of the string", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_string_length", upper_field_name="max_string_length", ), RangeAttributeDefinition( name="num_rules", levels=[5, 10, 15, 20], - default_level=0, description="Number of rules to apply", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_num_rules", upper_field_name="max_num_rules", ), diff --git a/reasoning_gym/algorithmic/string_splitting.py b/reasoning_gym/algorithmic/string_splitting.py index 490cfc47..82096175 100644 --- a/reasoning_gym/algorithmic/string_splitting.py +++ b/reasoning_gym/algorithmic/string_splitting.py @@ -7,7 +7,7 @@ from dataclasses import dataclass from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """There is a dismantling engineer who has old machines A, B, and C. @@ -143,12 +143,10 @@ class StringSplittingCurriculum(BaseCurriculum): RangeAttributeDefinition( name="initial_machines", levels=[10, 50, 100, 500], - default_level=1, description="Number of initial machines", - attr_type=AttributeType.APPEND, - min_value=0, lower_field_name="min_initial_machines", upper_field_name="max_initial_machines", + ensure_interval=True, ) ) diff --git a/reasoning_gym/algorithmic/string_synthesis.py b/reasoning_gym/algorithmic/string_synthesis.py index cad98f7f..7742c6d0 100644 --- a/reasoning_gym/algorithmic/string_synthesis.py +++ b/reasoning_gym/algorithmic/string_synthesis.py @@ -7,7 +7,7 @@ from dataclasses import dataclass from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """There are nine different blocks [A] [B] [C] {{A}} {{B}} {{C}} (A) (B) (C) @@ -148,12 +148,10 @@ class StringSynthesisCurriculum(BaseCurriculum): RangeAttributeDefinition( name="initial_blocks", levels=[10, 50, 100, 500], - default_level=1, description="Number of initial blocks", - attr_type=AttributeType.APPEND, - min_value=0, lower_field_name="min_initial_blocks", upper_field_name="max_initial_blocks", + ensure_interval=True, ) ) diff --git a/reasoning_gym/algorithmic/word_ladder.py b/reasoning_gym/algorithmic/word_ladder.py index 7917903d..9d8cb89d 100644 --- a/reasoning_gym/algorithmic/word_ladder.py +++ b/reasoning_gym/algorithmic/word_ladder.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..data import get_data_file_path from ..factory import ProceduralDataset, register_dataset @@ -278,12 +278,10 @@ class WordLadderCurriculum(BaseCurriculum): RangeAttributeDefinition( name="word_length", levels=[3, 4, 5, 6], - default_level=1, description="Length of words in the puzzle", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_word_length", upper_field_name="max_word_length", + ensure_interval=True, ) ) diff --git a/reasoning_gym/algorithmic/word_sequence_reversal.py b/reasoning_gym/algorithmic/word_sequence_reversal.py index 3f120af1..f0b2f68c 100644 --- a/reasoning_gym/algorithmic/word_sequence_reversal.py +++ b/reasoning_gym/algorithmic/word_sequence_reversal.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..data import read_data_file from ..factory import ProceduralDataset, register_dataset @@ -75,12 +75,10 @@ class WordSequenceReversalCurriculum(BaseCurriculum): RangeAttributeDefinition( name="words", levels=[10, 50, 100, 500], - default_level=1, description="Number of words in the list", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_words", upper_field_name="max_words", + ensure_interval=True, ), ) diff --git a/reasoning_gym/algorithmic/word_sorting.py b/reasoning_gym/algorithmic/word_sorting.py index fe29aaa7..51b94946 100644 --- a/reasoning_gym/algorithmic/word_sorting.py +++ b/reasoning_gym/algorithmic/word_sorting.py @@ -6,7 +6,7 @@ from enum import StrEnum from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..data import read_data_file from ..factory import ProceduralDataset, register_dataset @@ -137,20 +137,14 @@ class WordSortingCurriculum(BaseCurriculum): RangeAttributeDefinition( name="num_words", levels=[5, 10, 20, 30], - default_level=0, description="Number of words to sort", - attr_type=AttributeType.APPEND, - min_value=5, lower_field_name="min_words", upper_field_name="max_words", ), RangeAttributeDefinition( name="word_length", levels=[3, 6, 9, 12], - default_level=0, description="Length of words to sort", - attr_type=AttributeType.APPEND, - min_value=3, lower_field_name="min_word_length", upper_field_name="max_word_length", ), diff --git a/reasoning_gym/arc/rearc.py b/reasoning_gym/arc/rearc.py index e84b49fc..4b74c8fa 100644 --- a/reasoning_gym/arc/rearc.py +++ b/reasoning_gym/arc/rearc.py @@ -2,7 +2,7 @@ from dataclasses import dataclass, field from random import Random from typing import Any, Callable, Optional -from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset from .board_format import ARC_PROMPT_TEMPLATE, BoardFormattingOptions, format_board, format_board_pair, parse_board @@ -147,7 +147,6 @@ class ReArcCurriculum(BaseCurriculum): name="pso_difficulty", field_name="pso_difficulty_weights", description="The range of PSO difficulty for the Arc problem", - default_level=0, levels=[ [1, 0, 0, 0, 0, 0, 0, 0], # only sample/generate the easiest tasks wrs PSO difficulty [0, 1, 0, 0, 0, 0, 0, 0], @@ -163,7 +162,6 @@ class ReArcCurriculum(BaseCurriculum): name="rng_difficulty", field_name="rng_difficulty_weights", description="The range of RNG difficulty for the Arc problem", - default_level=0, levels=[ [1, 0, 0, 0, 0, 0, 0, 0], # only sample/generate the easiest tasks wrs RNG difficulty [0, 1, 0, 0, 0, 0, 0, 0], diff --git a/reasoning_gym/arithmetic/basic_arithmetic.py b/reasoning_gym/arithmetic/basic_arithmetic.py index b966e00f..dcffd2fc 100644 --- a/reasoning_gym/arithmetic/basic_arithmetic.py +++ b/reasoning_gym/arithmetic/basic_arithmetic.py @@ -2,7 +2,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Literal, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -240,20 +240,14 @@ class BasicArithmeticCurriculum(BaseCurriculum): RangeAttributeDefinition( name="num_terms", levels=[2, 5, 10, 20], - default_level=0, description="Number of terms in the expression", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_terms", upper_field_name="max_terms", ), RangeAttributeDefinition( name="num_digits", levels=[1, 2, 5, 10], - default_level=0, description="Number of digits in the numbers", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_digits", upper_field_name="max_digits", ), diff --git a/reasoning_gym/arithmetic/bitwise_arithmetic.py b/reasoning_gym/arithmetic/bitwise_arithmetic.py index 8b97221c..7b181ecd 100644 --- a/reasoning_gym/arithmetic/bitwise_arithmetic.py +++ b/reasoning_gym/arithmetic/bitwise_arithmetic.py @@ -2,7 +2,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -186,10 +186,7 @@ class BitwiseArithmeticCurriculum(BaseCurriculum): ScalarAttributeDefinition( name="difficulty", levels=[1, 2, 3, 4], - default_level=0, description="Range of difficulty levels", - attr_type=AttributeType.STATIC, - min_value=1, field_name="difficulty", ), ) diff --git a/reasoning_gym/arithmetic/calendar_arithmetic.py b/reasoning_gym/arithmetic/calendar_arithmetic.py index 9b4e0a2b..fcd1a7ce 100644 --- a/reasoning_gym/arithmetic/calendar_arithmetic.py +++ b/reasoning_gym/arithmetic/calendar_arithmetic.py @@ -6,7 +6,7 @@ from datetime import date, timedelta from enum import Enum, StrEnum, auto from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -511,17 +511,13 @@ class CalendarArithmeticCurriculum(BaseCurriculum): "recurring_event_day", ], ], - default_level=0, description="Controls which calendar tasks are included", - attr_type=AttributeType.STATIC, field_name="tasks", ), ScalarAttributeDefinition( name="date_range", levels=[30, 100, 250, 365], - default_level=0, description="Maximum day range for offset and counting tasks", - attr_type=AttributeType.STATIC, field_name="offset_upper_bound", ), ) diff --git a/reasoning_gym/arithmetic/chain_sum.py b/reasoning_gym/arithmetic/chain_sum.py index 1daffbf9..26e20e68 100644 --- a/reasoning_gym/arithmetic/chain_sum.py +++ b/reasoning_gym/arithmetic/chain_sum.py @@ -4,7 +4,7 @@ from typing import Any, Optional from reasoning_gym import utils -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -126,8 +126,6 @@ class ChainSumCurriculum(BaseCurriculum): levels=list(range(2, 13)), default_level=0, # Start with 2 terms description="Maximum number of terms in the expression", - attr_type=AttributeType.APPEND, - min_value=2, # Ensure at least 2 terms lower_field_name="min_terms", upper_field_name="max_terms", ), @@ -136,8 +134,6 @@ class ChainSumCurriculum(BaseCurriculum): levels=list(range(1, 11)), default_level=0, # Start with 1-digit numbers description="Number of digits in each operand", - attr_type=AttributeType.APPEND, - min_value=1, # Ensure numbers are at least 1 digit lower_field_name="min_digits", upper_field_name="max_digits", ), diff --git a/reasoning_gym/arithmetic/count_bits.py b/reasoning_gym/arithmetic/count_bits.py index 9a386af6..c2a6d61f 100644 --- a/reasoning_gym/arithmetic/count_bits.py +++ b/reasoning_gym/arithmetic/count_bits.py @@ -4,7 +4,7 @@ from dataclasses import dataclass from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """How many 1 bits are there in the binary representation of the number {number}?""" @@ -60,10 +60,7 @@ class CountBitsCurriculum(BaseCurriculum): RangeAttributeDefinition( name="n", levels=[1_000, 1_000_000, 100_000_000, 2**31 - 1], - default_level=0, description="Number to count bits in", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_n", upper_field_name="max_n", ), diff --git a/reasoning_gym/arithmetic/decimal_arithmetic.py b/reasoning_gym/arithmetic/decimal_arithmetic.py index 17b54765..806a442b 100644 --- a/reasoning_gym/arithmetic/decimal_arithmetic.py +++ b/reasoning_gym/arithmetic/decimal_arithmetic.py @@ -4,7 +4,7 @@ from decimal import ROUND_HALF_UP, Decimal, getcontext from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -232,20 +232,14 @@ class DecimalArithmeticCurriculum(BaseCurriculum): RangeAttributeDefinition( name="decimal_places", levels=[3, 5, 8, 10], - default_level=0, description="Number of decimal places of the numbers in problem", - attr_type=AttributeType.APPEND, - min_value=3, lower_field_name="min_num_decimal_places", upper_field_name="max_num_decimal_places", ), RangeAttributeDefinition( name="num_terms", levels=[2, 3, 4, 6], - default_level=0, description="Number of terms in the arithmetic expression", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_terms", upper_field_name="max_terms", ), diff --git a/reasoning_gym/arithmetic/decimal_chain_sum.py b/reasoning_gym/arithmetic/decimal_chain_sum.py index e06444dc..92be2f2b 100644 --- a/reasoning_gym/arithmetic/decimal_chain_sum.py +++ b/reasoning_gym/arithmetic/decimal_chain_sum.py @@ -3,7 +3,7 @@ from dataclasses import dataclass from decimal import Decimal, InvalidOperation from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -170,10 +170,7 @@ class DecimalChainSumCurriculum(BaseCurriculum): RangeAttributeDefinition( name="num_terms", levels=[2, 3, 4, 5], - default_level=0, description="Maximum number of terms in the expression", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_terms", upper_field_name="max_terms", ), @@ -182,18 +179,13 @@ class DecimalChainSumCurriculum(BaseCurriculum): levels=[1, 2, 4, 10], default_level=0, # Start with 1-digit numbers description="Number of digits in each operand", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_digits", upper_field_name="max_digits", ), RangeAttributeDefinition( name="decimal_places", levels=[1, 2, 3, 4], - default_level=0, description="Number of decimal places in each operand", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_decimal_places", upper_field_name="max_decimal_places", ), diff --git a/reasoning_gym/arithmetic/dice.py b/reasoning_gym/arithmetic/dice.py index b68018e0..c3a58fac 100644 --- a/reasoning_gym/arithmetic/dice.py +++ b/reasoning_gym/arithmetic/dice.py @@ -4,7 +4,7 @@ from math import gcd from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -162,19 +162,13 @@ class DiceCurriculum(BaseCurriculum): ScalarAttributeDefinition( name="num_dice", levels=[4, 5, 6, 7], - default_level=0, description="Number of dice to roll", - attr_type=AttributeType.STATIC, - min_value=4, field_name="num_dice", ), ScalarAttributeDefinition( name="max_dice_size", levels=[20, 25, 30, 35], - default_level=0, description="Maximum number of sides on any die", - attr_type=AttributeType.STATIC, - min_value=20, field_name="max_dice_size", ), ) diff --git a/reasoning_gym/arithmetic/fraction_simplification.py b/reasoning_gym/arithmetic/fraction_simplification.py index e06d4519..2b8c8453 100644 --- a/reasoning_gym/arithmetic/fraction_simplification.py +++ b/reasoning_gym/arithmetic/fraction_simplification.py @@ -6,7 +6,7 @@ from math import gcd from random import Random from typing import Any, Optional, Sequence -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = "Simplify the fraction {question_fraction} to its lowest terms. Give only the simplified fraction as your final answer." @@ -166,22 +166,18 @@ class FractionSimplificationCurriculum(BaseCurriculum): RangeAttributeDefinition( name="value", levels=[1, 100, 1000, 10000], - default_level=1, description="Value range for numerator and denominator", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_value", upper_field_name="max_value", + ensure_interval=True, ), RangeAttributeDefinition( name="factor", levels=[1, 10, 100, 1000], - default_level=1, description="Factor range for generating unsimplified fractions", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_factor", upper_field_name="max_factor", + ensure_interval=True, ), ) diff --git a/reasoning_gym/arithmetic/gcd.py b/reasoning_gym/arithmetic/gcd.py index f3a0a61a..c8efba3a 100644 --- a/reasoning_gym/arithmetic/gcd.py +++ b/reasoning_gym/arithmetic/gcd.py @@ -6,7 +6,7 @@ from math import gcd from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -81,20 +81,14 @@ class GCDCurriculum(BaseCurriculum): RangeAttributeDefinition( name="num_terms", levels=[2, 3, 4, 5], - default_level=0, description="number of terms", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_numbers", upper_field_name="max_numbers", ), RangeAttributeDefinition( name="max_value", levels=[100, 1000, 10000, 100000], - default_level=0, description="maximum value", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_value", upper_field_name="max_value", ), diff --git a/reasoning_gym/arithmetic/lcm.py b/reasoning_gym/arithmetic/lcm.py index 464cd0ab..a8f6c5ea 100644 --- a/reasoning_gym/arithmetic/lcm.py +++ b/reasoning_gym/arithmetic/lcm.py @@ -6,7 +6,7 @@ from math import lcm from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -83,22 +83,17 @@ class LCMCurriculum(BaseCurriculum): RangeAttributeDefinition( name="numbers", levels=[2, 4, 6, 8, 10], - default_level=0, description="Number of integers to find LCM of", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_numbers", upper_field_name="max_numbers", ), RangeAttributeDefinition( name="value", levels=[1, 100, 500, 1000, 5000], - default_level=1, description="Range of values for each integer", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_value", upper_field_name="max_value", + ensure_interval=True, ), ) diff --git a/reasoning_gym/arithmetic/leg_counting.py b/reasoning_gym/arithmetic/leg_counting.py index 3733a80f..b2103858 100644 --- a/reasoning_gym/arithmetic/leg_counting.py +++ b/reasoning_gym/arithmetic/leg_counting.py @@ -4,7 +4,7 @@ from dataclasses import dataclass from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset ANIMALS = { @@ -136,20 +136,14 @@ class LegCountingCurriculum(BaseCurriculum): RangeAttributeDefinition( name="num_animals", levels=list(range(1, 20)), - default_level=0, description="Number of animals in question", - attr_type=AttributeType.APPEND, - min_value=1, # Ensure at least 1 animal lower_field_name="min_animals", upper_field_name="max_animals", ), RangeAttributeDefinition( name="num_instances", levels=[2, 4, 8, 16, 32, 64, 128, 256, 512, 1024], - default_level=0, description="Number of instances of each animal", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_instances", upper_field_name="max_instances", ), diff --git a/reasoning_gym/arithmetic/number_format.py b/reasoning_gym/arithmetic/number_format.py index 00a9d732..44515254 100644 --- a/reasoning_gym/arithmetic/number_format.py +++ b/reasoning_gym/arithmetic/number_format.py @@ -4,7 +4,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """Your task is to pick the largest/smallest number out of several options. @@ -115,31 +115,24 @@ class NumberFormatCurriculum(BaseCurriculum): RangeAttributeDefinition( name="num_candidates", levels=[5, 25, 100, 500], - default_level=1, description="Number of candidates", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_num_candidates", upper_field_name="max_num_candidates", + ensure_interval=True, ), RangeAttributeDefinition( name="n", levels=[10, 1_000, 1_000_000, 1_000_000_000], - default_level=1, description="Magnitude of the values", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_n", upper_field_name="max_n", + ensure_interval=True, ), ScalarAttributeDefinition( name="max_delta", field_name="max_delta", levels=[1e1, 1e0, 1e-3, 1e-6], - default_level=0, description="Max delta", - attr_type=AttributeType.STATIC, - min_value=1e-6, ), ) diff --git a/reasoning_gym/arithmetic/power_function.py b/reasoning_gym/arithmetic/power_function.py index aae9fb52..ff32404c 100644 --- a/reasoning_gym/arithmetic/power_function.py +++ b/reasoning_gym/arithmetic/power_function.py @@ -6,7 +6,7 @@ from math import pow from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """Your task is to compute an exponentiation of a number. @@ -84,9 +84,6 @@ class PowerFunctionCurriculum(BaseCurriculum): RangeAttributeDefinition( name="exponent", levels=[2, 4, 6, 10], - default_level=0, - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_exponent", upper_field_name="max_exponent", ), diff --git a/reasoning_gym/arithmetic/prime_factorization.py b/reasoning_gym/arithmetic/prime_factorization.py index 5795fbef..46d05286 100644 --- a/reasoning_gym/arithmetic/prime_factorization.py +++ b/reasoning_gym/arithmetic/prime_factorization.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -96,12 +96,10 @@ class PrimeFactorizationCurriculum(BaseCurriculum): RangeAttributeDefinition( name="value", levels=[10, 1_000, 10_000, 50_000], - default_level=1, description="Number to factorize", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_value", upper_field_name="max_value", + ensure_interval=True, ) ) diff --git a/reasoning_gym/arithmetic/products.py b/reasoning_gym/arithmetic/products.py index c39c4377..4216a96d 100644 --- a/reasoning_gym/arithmetic/products.py +++ b/reasoning_gym/arithmetic/products.py @@ -4,7 +4,7 @@ from typing import Any, Optional from reasoning_gym import utils -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -118,8 +118,6 @@ class ProductsCurriculum(BaseCurriculum): levels=list(range(2, 13)), default_level=0, # Start with 2 terms description="Maximum number of terms in the expression", - attr_type=AttributeType.APPEND, - min_value=2, # Ensure at least 2 terms lower_field_name="min_terms", upper_field_name="max_terms", ), @@ -128,8 +126,6 @@ class ProductsCurriculum(BaseCurriculum): levels=list(range(1, 11)), default_level=0, # Start with 1-digit numbers description="Number of digits in each operand", - attr_type=AttributeType.APPEND, - min_value=1, # Ensure numbers are at least 1 digit lower_field_name="min_digits", upper_field_name="max_digits", ), diff --git a/reasoning_gym/arithmetic/time_intervals.py b/reasoning_gym/arithmetic/time_intervals.py index c08de217..42a6f343 100644 --- a/reasoning_gym/arithmetic/time_intervals.py +++ b/reasoning_gym/arithmetic/time_intervals.py @@ -6,7 +6,7 @@ from typing import Optional import pytz from dateutil import parser -from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -334,19 +334,13 @@ class TimeIntervalsCurriculum(BaseCurriculum): name="max_time_difference_seconds", field_name="max_time_difference_seconds", levels=[60, 24 * 60 * 60, 7 * 24 * 60 * 60, 30 * 24 * 60 * 60, 365 * 24 * 60 * 60], - default_level=0, description="Maximum time difference in seconds", - attr_type=AttributeType.STATIC, - min_value=1, ), ScalarAttributeDefinition( name="max_date_difference_days", field_name="max_date_difference_days", levels=[1, 7, 30, 365, 5 * 365], - default_level=0, description="Maximum date difference in days", - attr_type=AttributeType.STATIC, - min_value=1, ), ) diff --git a/reasoning_gym/coaching/__init__.py b/reasoning_gym/coaching/__init__.py index 4d96bca4..97e89844 100644 --- a/reasoning_gym/coaching/__init__.py +++ b/reasoning_gym/coaching/__init__.py @@ -1,4 +1,4 @@ -from .attributes import AttributeDefinition, AttributeType, RangeAttributeDefinition, ScalarAttributeDefinition +from .attributes import AttributeDefinition, RangeAttributeDefinition, ScalarAttributeDefinition from .base_curriculum import BaseCurriculum from .coach import Coach, GroupedScores, ScoreBoard, ScoreStats diff --git a/reasoning_gym/coaching/attributes.py b/reasoning_gym/coaching/attributes.py index 33fc053b..737d4cb0 100644 --- a/reasoning_gym/coaching/attributes.py +++ b/reasoning_gym/coaching/attributes.py @@ -1,25 +1,13 @@ -from collections import abc from dataclasses import dataclass -from enum import StrEnum from typing import Any, Optional -class AttributeType(StrEnum): - """Defines how attribute levels should be interpreted""" - - STATIC = "static" # Each level is independent - UBOUND = "ubound" # Each level is an upper bound - APPEND = "append" # Each level includes all previous levels - - @dataclass(kw_only=True) class AttributeDefinition: name: str levels: list - default_level: int + default_level: int = 0 description: Optional[str] = None - attr_type: AttributeType = AttributeType.STATIC # Default to static - min_value: Optional[int | float] = None # Minimum value for numeric attributes def validate_level(self, level: int, curriculum: str) -> None: """ @@ -37,7 +25,7 @@ class AttributeDefinition: f"Must be between 0 and {len(self.levels)-1}" ) - def get_level_value(self, level: int, curriculum: str) -> Any: + def get_level_value(self, level: int) -> Any: """ Get the value for an attribute at a specific level based on its type. Args: @@ -46,14 +34,7 @@ class AttributeDefinition: Returns: Value for the attribute based on its level and type """ - if self.attr_type == AttributeType.STATIC: - return self.levels[level] - elif self.attr_type == AttributeType.UBOUND: - return self.levels[level] - elif self.attr_type == AttributeType.APPEND: - return self.levels[: level + 1] - - raise ValueError(f"Unknown attribute type: {self.attr_type} for attribute '{curriculum}.{self.name}'") + return self.levels[level] @dataclass(kw_only=True) @@ -65,9 +46,4 @@ class ScalarAttributeDefinition(AttributeDefinition): class RangeAttributeDefinition(AttributeDefinition): lower_field_name: str upper_field_name: str - - def get_level_value(self, level: int, curriculum: str) -> Any: - v = super().get_level_value(level, curriculum) - if not isinstance(v, abc.Iterable): - return [v] - return v + ensure_interval: bool = False # When True, ensures the range is always an interval between two distinct values diff --git a/reasoning_gym/coaching/base_curriculum.py b/reasoning_gym/coaching/base_curriculum.py index 5b7463c4..15b725cb 100644 --- a/reasoning_gym/coaching/base_curriculum.py +++ b/reasoning_gym/coaching/base_curriculum.py @@ -1,3 +1,6 @@ +import abc +from collections.abc import Iterable +from enum import StrEnum from typing import Any, Optional, TypeVar from .attributes import AttributeDefinition, RangeAttributeDefinition, ScalarAttributeDefinition @@ -5,6 +8,58 @@ from .attributes import AttributeDefinition, RangeAttributeDefinition, ScalarAtt ConfigT = TypeVar("ConfigT") +class CurriculumContext(abc.ABC): + @abc.abstractmethod + def get_attr_value(self, curriculum, attr: AttributeDefinition) -> Any: + pass + + +class RangeAttributeMode(StrEnum): + """Text transformation options""" + + UPPER_BOUND = "upper_bound" # only use the highest range segment + INCLUSIVE = "inclusive" # include all previous levels + + +class DefaultCurriculumContext(CurriculumContext): + def __init__(self, mode: RangeAttributeMode = RangeAttributeMode.INCLUSIVE): + self.mode = mode + + def get_range_attr_value(self, curriculum, attr: RangeAttributeDefinition) -> Any: + level = curriculum.get_attr_level(attr.name) + v = attr.get_level_value(level) + if isinstance(v, Iterable): + return v + + if attr.ensure_interval: + if self.mode == RangeAttributeMode.UPPER_BOUND: + hi_index = min(level + 1, len(attr.levels) - 1) + lo_index = max(0, hi_index - 1) + + elif self.mode == RangeAttributeMode.INCLUSIVE: + lo_index = 0 + hi_index = min(level + 1, len(attr.levels) - 1) + else: + if self.mode == RangeAttributeMode.UPPER_BOUND: + hi_index = min(level, len(attr.levels) - 1) + lo_index = max(0, hi_index) + + elif self.mode == RangeAttributeMode.INCLUSIVE: + lo_index = 0 + hi_index = min(level, len(attr.levels) - 1) + + lo = attr.get_level_value(lo_index) + hi = attr.get_level_value(hi_index) + + return [lo, hi] + + def get_attr_value(self, curriculum, attr: AttributeDefinition) -> Any: + if isinstance(attr, RangeAttributeDefinition): + return self.get_range_attr_value(curriculum, attr) + elif isinstance(attr, ScalarAttributeDefinition): + return curriculum.get_attr_value(attr.name) + + class BaseCurriculum: def __init__(self, name: str, config_cls: ConfigT): self.name = name @@ -12,15 +67,23 @@ class BaseCurriculum: self._attributes: dict[str, AttributeDefinition] = {} self._current_levels: dict[str, int] = {} - def generate_configuration(self, defaults: Optional[dict[str, Any]] = None) -> ConfigT: + def generate_configuration( + self, defaults: Optional[dict[str, Any]] = None, context: Optional[CurriculumContext] = None + ) -> ConfigT: config_args = defaults.copy() if defaults is not None else {} + + if context is None: + context = DefaultCurriculumContext(mode=RangeAttributeMode.INCLUSIVE) + for attr in self._attributes.values(): if isinstance(attr, RangeAttributeDefinition): - vals = self.get_attr_value(attr.name) - config_args[attr.lower_field_name] = min(vals) - config_args[attr.upper_field_name] = max(vals) + v = context.get_attr_value(self, attr) + if not isinstance(v, Iterable): + v = [v] + config_args[attr.lower_field_name] = min(v) + config_args[attr.upper_field_name] = max(v) elif isinstance(attr, ScalarAttributeDefinition): - val = self.get_attr_value(attr.name) + val = context.get_attr_value(self, attr) config_args[attr.field_name] = val return self._config_cls(**config_args) @@ -61,7 +124,7 @@ class BaseCurriculum: """ attr = self.get_attribute(attr_name) level = self.get_attr_level(attr_name) - return attr.get_level_value(level, curriculum=self.name) + return attr.get_level_value(level) def set_attr_level(self, attr_name: str, level: int) -> None: """ diff --git a/reasoning_gym/coaching/experiment.py b/reasoning_gym/coaching/experiment.py index bbb02b88..7b15db8c 100644 --- a/reasoning_gym/coaching/experiment.py +++ b/reasoning_gym/coaching/experiment.py @@ -2,6 +2,8 @@ from typing import Any, Optional +from reasoning_gym.coaching.base_curriculum import CurriculumContext + from ..composite import CompositeConfig, CompositeDataset, DatasetSpec from ..factory import create_curriculum from ..version_manager import DatasetVersionManager @@ -37,7 +39,14 @@ class Experiment: class CurriculumExperiment(Experiment): - def __init__(self, name: str, config: CurriculumExperimentConfig, size: int, seed: Optional[int] = None): + def __init__( + self, + name: str, + config: CurriculumExperimentConfig, + size: int, + context: Optional[CurriculumContext] = None, + seed: Optional[int] = None, + ): """Initialize curriculum experiment with configured datasets and their curricula. Args: @@ -68,7 +77,7 @@ class CurriculumExperiment(Experiment): curriculum.set_attr_level(attr_name, level) # Generate dataset config from curriculum - dataset_config = curriculum.generate_configuration() + dataset_config = curriculum.generate_configuration(context=context) # Create dataset spec spec = DatasetSpec(name=dataset_name, weight=attr_config.weight, config=dataset_config.__dict__) @@ -86,6 +95,7 @@ class CurriculumExperiment(Experiment): # Store curriculum config self.curriculum_config = config + self.context = context def update_difficulty(self): """Update difficulty levels based on performance metrics""" diff --git a/reasoning_gym/code/bf.py b/reasoning_gym/code/bf.py index 076e798c..0599325a 100644 --- a/reasoning_gym/code/bf.py +++ b/reasoning_gym/code/bf.py @@ -4,7 +4,7 @@ from typing import Any, Optional import bfi -from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, ScalarAttributeDefinition from ..data.wordle_words import wordle_words from ..factory import ProceduralDataset, register_dataset from .contrib.bfit.Compiler import Compiler, Minify @@ -154,10 +154,7 @@ class BFCurriculum(BaseCurriculum): name="difficulty", field_name="difficulty", levels=[1, 2, 3], - default_level=0, description="Difficulty level", - attr_type=AttributeType.STATIC, - min_value=1, ) ) diff --git a/reasoning_gym/cognition/color_cube_rotation.py b/reasoning_gym/cognition/color_cube_rotation.py index 997e6a05..1b6e0b68 100644 --- a/reasoning_gym/cognition/color_cube_rotation.py +++ b/reasoning_gym/cognition/color_cube_rotation.py @@ -3,7 +3,7 @@ from dataclasses import dataclass from enum import StrEnum from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -215,12 +215,10 @@ class ColorCubeRotationCurriculum(BaseCurriculum): RangeAttributeDefinition( name="rotations", levels=[1, 5, 10, 50, 100], - default_level=1, description="Number of rotations to perform on the cube", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_rotations", upper_field_name="max_rotations", + ensure_interval=True, ) ) diff --git a/reasoning_gym/cognition/modulo_grid.py b/reasoning_gym/cognition/modulo_grid.py index f2e151d3..45ab2a56 100644 --- a/reasoning_gym/cognition/modulo_grid.py +++ b/reasoning_gym/cognition/modulo_grid.py @@ -3,7 +3,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -158,46 +158,31 @@ class ModuloGridCurriculum(BaseCurriculum): name="size_x", field_name="size_x", levels=[20, 30, 50, 75], - default_level=0, description="Size x", - attr_type=AttributeType.STATIC, - min_value=20, ), ScalarAttributeDefinition( name="size_y", field_name="size_y", levels=[20, 30, 50, 75], - default_level=0, description="Size y", - attr_type=AttributeType.STATIC, - min_value=20, ), ScalarAttributeDefinition( name="max_holes", field_name="max_holes", levels=[1, 2, 3, 5], - default_level=0, description="Max holes", - attr_type=AttributeType.STATIC, - min_value=1, ), ScalarAttributeDefinition( name="max_divisor", field_name="max_divisor", levels=[9, 10, 11, 48], - default_level=0, description="Max divisor", - attr_type=AttributeType.STATIC, - min_value=1, ), ScalarAttributeDefinition( name="max_target", field_name="max_target", levels=[7, 14, 21, 49], - default_level=0, description="Max target", - attr_type=AttributeType.STATIC, - min_value=1, ), ) diff --git a/reasoning_gym/cognition/needle_haystack.py b/reasoning_gym/cognition/needle_haystack.py index 6fe4f55a..179d0657 100644 --- a/reasoning_gym/cognition/needle_haystack.py +++ b/reasoning_gym/cognition/needle_haystack.py @@ -2,7 +2,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -138,12 +138,10 @@ class NeedleHaystackCurriculum(BaseCurriculum): RangeAttributeDefinition( name="num_statements", levels=[10, 100, 1_000, 10_000, 100_000, 1_000_000, 168_386_000], - default_level=1, description="Number of statements in the haystack", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_num_statements", upper_field_name="max_num_statements", + ensure_interval=True, ), ) diff --git a/reasoning_gym/cognition/number_sequences.py b/reasoning_gym/cognition/number_sequences.py index d8ea262b..10f7253c 100644 --- a/reasoning_gym/cognition/number_sequences.py +++ b/reasoning_gym/cognition/number_sequences.py @@ -3,7 +3,7 @@ from enum import StrEnum from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -207,10 +207,7 @@ class NumberSequenceCurriculum(BaseCurriculum): ScalarAttributeDefinition( name="max_complexity", levels=[1, 2, 3, 4], - default_level=0, description="Maximum number of operations to combine", - attr_type=AttributeType.STATIC, - min_value=1, field_name="max_complexity", ), ) diff --git a/reasoning_gym/cognition/rectangle_count.py b/reasoning_gym/cognition/rectangle_count.py index 2318aa47..61a9b76b 100644 --- a/reasoning_gym/cognition/rectangle_count.py +++ b/reasoning_gym/cognition/rectangle_count.py @@ -2,7 +2,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """Your task is to count how many rectangles are present in an ASCII grid. @@ -148,10 +148,7 @@ class RectangleCountCurriculum(BaseCurriculum): ScalarAttributeDefinition( name="max_rectangles", levels=[1, 3, 5, 10], - default_level=0, description="Number of rectangles in the grid", - attr_type=AttributeType.STATIC, - min_value=1, field_name="max_rectangles", ), ) diff --git a/reasoning_gym/cognition/rubiks_cube.py b/reasoning_gym/cognition/rubiks_cube.py index 0f69135f..fb728ea6 100644 --- a/reasoning_gym/cognition/rubiks_cube.py +++ b/reasoning_gym/cognition/rubiks_cube.py @@ -6,7 +6,7 @@ from typing import Any, Optional from magiccube.cube import Cube, CubeMove, CubeMoveType from magiccube.solver.basic.basic_solver import BasicSolver -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -174,20 +174,15 @@ class RubiksCubeCurriculum(BaseCurriculum): name="cube_size", field_name="cube_size", levels=[3, 4, 5, 6, 7], - default_level=0, description="Board size", - attr_type=AttributeType.STATIC, - min_value=3, ), RangeAttributeDefinition( name="scramble_steps", levels=[3, 10, 50, 100, 500, 1000], - default_level=1, description="Number of random moves to scramble the cube", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_scramble_steps", upper_field_name="max_scramble_steps", + ensure_interval=True, ), ) diff --git a/reasoning_gym/games/boxnet.py b/reasoning_gym/games/boxnet.py index b43cdf86..21d77c39 100644 --- a/reasoning_gym/games/boxnet.py +++ b/reasoning_gym/games/boxnet.py @@ -7,7 +7,7 @@ from typing import Any, Optional import numpy as np -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset BOXNET_PROMPT = """ @@ -223,30 +223,24 @@ class BoxnetCurriculum(BaseCurriculum): description="The maximum number of rows in the grid", lower_field_name="min_row_num", upper_field_name="max_row_num", - min_value=1, levels=list(range(1, 10)), - default_level=1, - attr_type=AttributeType.APPEND, + ensure_interval=True, ), RangeAttributeDefinition( name="column_num", description="The maximum number of columns in the grid", lower_field_name="min_column_num", upper_field_name="max_column_num", - min_value=1, levels=list(range(1, 10)), - default_level=1, - attr_type=AttributeType.APPEND, + ensure_interval=True, ), RangeAttributeDefinition( name="box_num", description="The maximum number of boxes in the grid", lower_field_name="min_box_num", upper_field_name="max_box_num", - min_value=1, levels=list(range(1, 10)), - default_level=1, - attr_type=AttributeType.APPEND, + ensure_interval=True, ), ) diff --git a/reasoning_gym/games/emoji_mystery.py b/reasoning_gym/games/emoji_mystery.py index be34b140..f4a12a0e 100644 --- a/reasoning_gym/games/emoji_mystery.py +++ b/reasoning_gym/games/emoji_mystery.py @@ -3,7 +3,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..data import read_data_file from ..factory import ProceduralDataset, register_dataset @@ -249,10 +249,7 @@ class EmojiMysteryCurriculum(BaseCurriculum): RangeAttributeDefinition( name="num_words_in_sentence", levels=[3, 10, 20, 35], - default_level=0, description="Number of words in the sentence", - attr_type=AttributeType.STATIC, - min_value=3, lower_field_name="min_words_in_sentence", upper_field_name="max_words_in_sentence", ), diff --git a/reasoning_gym/games/futoshiki.py b/reasoning_gym/games/futoshiki.py index b5eab54c..4eb18489 100644 --- a/reasoning_gym/games/futoshiki.py +++ b/reasoning_gym/games/futoshiki.py @@ -6,7 +6,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -667,20 +667,14 @@ class FutoshikiCurriculum(BaseCurriculum): RangeAttributeDefinition( name="board_size", levels=[4, 6, 7, 9], - default_level=0, description="Board size", - attr_type=AttributeType.STATIC, - min_value=4, lower_field_name="min_board_size", upper_field_name="max_board_size", ), RangeAttributeDefinition( name="difficulty", levels=[0, 1, 2, 3], - default_level=0, description="Difficulty", - attr_type=AttributeType.STATIC, - min_value=0, lower_field_name="min_difficulty", upper_field_name="max_difficulty", ), diff --git a/reasoning_gym/games/mahjong.py b/reasoning_gym/games/mahjong.py index debe1954..7021df09 100644 --- a/reasoning_gym/games/mahjong.py +++ b/reasoning_gym/games/mahjong.py @@ -8,7 +8,7 @@ from dataclasses import dataclass from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """There are several letter cards, and the game rules are as follows: @@ -136,10 +136,7 @@ class MahjongPuzzleCurriculum(BaseCurriculum): RangeAttributeDefinition( name="num_rounds", levels=[10, 50, 100, 500], - default_level=0, description="Number of rounds in the game", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_num_rounds", upper_field_name="max_num_rounds", ) diff --git a/reasoning_gym/games/maze.py b/reasoning_gym/games/maze.py index 39bf9e9e..e2f4f50e 100644 --- a/reasoning_gym/games/maze.py +++ b/reasoning_gym/games/maze.py @@ -3,7 +3,7 @@ import string from dataclasses import dataclass from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -198,22 +198,18 @@ class MazeCurriculum(BaseCurriculum): RangeAttributeDefinition( name="dist", levels=[10, 25, 50, 100], - default_level=1, description="Distance from start to goal", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_dist", upper_field_name="max_dist", + ensure_interval=True, ), RangeAttributeDefinition( name="grid_size", levels=[10, 25, 50, 100], - default_level=1, description="Size of the square grid", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_grid_size", upper_field_name="max_grid_size", + ensure_interval=True, ), ) diff --git a/reasoning_gym/games/mini_sudoku.py b/reasoning_gym/games/mini_sudoku.py index 16a7032f..ee9ea1a4 100644 --- a/reasoning_gym/games/mini_sudoku.py +++ b/reasoning_gym/games/mini_sudoku.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -249,12 +249,10 @@ class MiniSudokuCurriculum(BaseCurriculum): RangeAttributeDefinition( name="empty", levels=[4, 6, 8, 10], - default_level=1, description="Number of empty cells in the puzzle", - attr_type=AttributeType.APPEND, - min_value=0, lower_field_name="min_empty", upper_field_name="max_empty", + ensure_interval=True, ) ) diff --git a/reasoning_gym/games/n_queens.py b/reasoning_gym/games/n_queens.py index a918b136..d360e5cb 100644 --- a/reasoning_gym/games/n_queens.py +++ b/reasoning_gym/games/n_queens.py @@ -9,7 +9,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset MIN_BOARD_SIZE = 4 @@ -165,18 +165,12 @@ class NQueensCurriculum(BaseCurriculum): name="n", field_name="n", levels=[4, 6, 8, 12], - default_level=0, description="Board size", - attr_type=AttributeType.STATIC, - min_value=4, ), RangeAttributeDefinition( name="num_removed", levels=[2, 4, 6, 10], - default_level=0, description="Number of queens to remove", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_remove", upper_field_name="max_remove", ), diff --git a/reasoning_gym/games/rush_hour.py b/reasoning_gym/games/rush_hour.py index 8e5813ed..1ade0d28 100644 --- a/reasoning_gym/games/rush_hour.py +++ b/reasoning_gym/games/rush_hour.py @@ -8,7 +8,7 @@ import re from dataclasses import dataclass from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..data import get_data_file_path from ..factory import ProceduralDataset, register_dataset @@ -376,12 +376,10 @@ class RushHourCurriculum(BaseCurriculum): RangeAttributeDefinition( name="min_moves", levels=[5, 20, 35, 50], - default_level=1, description="Minimum possible number of moves", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_moves", upper_field_name="max_moves", + ensure_interval=True, ) ) diff --git a/reasoning_gym/games/sokoban.py b/reasoning_gym/games/sokoban.py index 1eff7154..4cdeebdf 100644 --- a/reasoning_gym/games/sokoban.py +++ b/reasoning_gym/games/sokoban.py @@ -4,7 +4,7 @@ from typing import Any, Optional import numpy as np -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -138,22 +138,16 @@ class SokobanCurriculum(BaseCurriculum): RangeAttributeDefinition( name="width", levels=list(range(6, 11)), - default_level=0, description="The width of the Sokoban board", - attr_type=AttributeType.APPEND, lower_field_name="min_w", upper_field_name="max_w", - min_value=6, ), RangeAttributeDefinition( name="height", levels=list(range(6, 11)), - default_level=0, description="The height of the Sokoban board", - attr_type=AttributeType.APPEND, lower_field_name="min_h", upper_field_name="max_h", - min_value=6, ), ) diff --git a/reasoning_gym/games/sudoku.py b/reasoning_gym/games/sudoku.py index 83016cb7..3ad7f3aa 100644 --- a/reasoning_gym/games/sudoku.py +++ b/reasoning_gym/games/sudoku.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -268,12 +268,10 @@ class SudokuCurriculum(BaseCurriculum): RangeAttributeDefinition( name="empty", levels=[20, 30, 40, 50], - default_level=1, description="Number of empty cells in the puzzle", - attr_type=AttributeType.APPEND, - min_value=0, lower_field_name="min_empty", upper_field_name="max_empty", + ensure_interval=True, ) ) diff --git a/reasoning_gym/games/tower_of_hanoi.py b/reasoning_gym/games/tower_of_hanoi.py index ccd1e2fb..e3f3444a 100644 --- a/reasoning_gym/games/tower_of_hanoi.py +++ b/reasoning_gym/games/tower_of_hanoi.py @@ -6,7 +6,7 @@ import re from dataclasses import dataclass from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """Solve the Tower of Hanoi problem with {num_disks} disks and {num_pegs} pegs. @@ -440,9 +440,7 @@ class HanoiCurriculum(BaseCurriculum): RangeAttributeDefinition( name="num_disks", levels=[3, 4, 5, 7], - default_level=0, min_disks=3, - attr_type=AttributeType.APPEND, lower_field_name="min_disks", upper_field_name="max_disks", description="Number of disks in the puzzle", diff --git a/reasoning_gym/games/tsumego.py b/reasoning_gym/games/tsumego.py index 3b77817d..0c1a9461 100644 --- a/reasoning_gym/games/tsumego.py +++ b/reasoning_gym/games/tsumego.py @@ -21,7 +21,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset # Added constant to avoid repetition of adjacent directions @@ -298,9 +298,6 @@ class TsumegoCurriculum(BaseCurriculum): RangeAttributeDefinition( name="board_size", levels=[9, 10, 11, 12], - default_level=0, - min_value=9, - attr_type=AttributeType.APPEND, lower_field_name="min_board_size", upper_field_name="max_board_size", description="The size of the board", diff --git a/reasoning_gym/geometry/advanced_geometry.py b/reasoning_gym/geometry/advanced_geometry.py index ed841731..257cd359 100644 --- a/reasoning_gym/geometry/advanced_geometry.py +++ b/reasoning_gym/geometry/advanced_geometry.py @@ -6,7 +6,7 @@ import numpy as np import sympy from sympy.geometry import Point -from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -284,19 +284,13 @@ class AdvancedGeometryCurriculum(BaseCurriculum): name="min_coord", field_name="min_coord", levels=[-10, -100, -1000, -10000], - default_level=0, description="Minimum x/y coordinate", - attr_type=AttributeType.STATIC, - min_value=-float("inf"), ), ScalarAttributeDefinition( name="max_coord", field_name="max_coord", levels=[10, 100, 1000, 10000], - default_level=0, description="Maximum x/y coordinate", - attr_type=AttributeType.STATIC, - min_value=-float("inf"), ), ) diff --git a/reasoning_gym/geometry/simple_geometry.py b/reasoning_gym/geometry/simple_geometry.py index b6ac5819..ca938318 100644 --- a/reasoning_gym/geometry/simple_geometry.py +++ b/reasoning_gym/geometry/simple_geometry.py @@ -2,7 +2,7 @@ import random from dataclasses import dataclass from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -153,12 +153,10 @@ class SimpleGeometryCurriculum(BaseCurriculum): RangeAttributeDefinition( name="sides", levels=[5, 10, 25, 50], - default_level=1, description="Number of sides in the polygon.", - attr_type=AttributeType.APPEND, - min_value=3, lower_field_name="min_sides", upper_field_name="max_sides", + ensure_interval=True, ) ) diff --git a/reasoning_gym/graphs/course_schedule.py b/reasoning_gym/graphs/course_schedule.py index 4a555e32..0db3e1b4 100644 --- a/reasoning_gym/graphs/course_schedule.py +++ b/reasoning_gym/graphs/course_schedule.py @@ -10,7 +10,7 @@ from dataclasses import dataclass from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """There are a total of {num_courses} courses you have to take, labeled from 0 to {last_index}. @@ -152,8 +152,6 @@ class CourseScheduleCurriculum(BaseCurriculum): levels=[10, 50, 100, 500], default_level=0, # Start with 5 courses description="Number of courses in the schedule", - attr_type=AttributeType.APPEND, - min_value=3, # Ensure at least 3 courses lower_field_name="min_num_courses", upper_field_name="max_num_courses", ), @@ -162,8 +160,6 @@ class CourseScheduleCurriculum(BaseCurriculum): levels=[2, 3, 4, 5], default_level=0, # Start with 2 prerequisites max description="Number of prerequisites per course", - attr_type=AttributeType.APPEND, - min_value=0, lower_field_name="min_num_prerequisites", upper_field_name="max_num_prerequisites", ), @@ -172,8 +168,6 @@ class CourseScheduleCurriculum(BaseCurriculum): levels=[3, 4, 5, 6], default_level=0, # Start with 3 cycle length description="Length of a cycle in the prerequisites", - attr_type=AttributeType.APPEND, - min_value=3, lower_field_name="min_cycle_length", upper_field_name="max_cycle_length", ), diff --git a/reasoning_gym/graphs/family_relationships.py b/reasoning_gym/graphs/family_relationships.py index f22cf7a3..ce8d5fcd 100644 --- a/reasoning_gym/graphs/family_relationships.py +++ b/reasoning_gym/graphs/family_relationships.py @@ -4,7 +4,7 @@ from enum import StrEnum from itertools import count from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -379,9 +379,6 @@ class FamilyRelationshipsCurriculum(BaseCurriculum): RangeAttributeDefinition( name="family_size", description="The size of the family", - min_value=3, - attr_type=AttributeType.APPEND, - default_level=0, levels=list(range(3, 12)), lower_field_name="min_family_size", upper_field_name="max_family_size", diff --git a/reasoning_gym/graphs/largest_island.py b/reasoning_gym/graphs/largest_island.py index 7090497d..acd93912 100644 --- a/reasoning_gym/graphs/largest_island.py +++ b/reasoning_gym/graphs/largest_island.py @@ -9,7 +9,7 @@ from dataclasses import dataclass from random import Random from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """You are given the following {rows} x {cols} binary matrix grid: @@ -159,40 +159,28 @@ class LargestIslandCurriculum(BaseCurriculum): RangeAttributeDefinition( name="rows", levels=[5, 10, 50, 100], - default_level=0, description="Number of rows in the grid", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_rows", upper_field_name="max_rows", ), RangeAttributeDefinition( name="cols", levels=[5, 10, 50, 100], - default_level=0, description="Number of columns in the grid", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_cols", upper_field_name="max_cols", ), RangeAttributeDefinition( name="num_islands", levels=[2, 5, 10, 20], - default_level=0, description="Number of islands in the grid", - attr_type=AttributeType.APPEND, - min_value=0, lower_field_name="min_num_islands", upper_field_name="max_num_islands", ), RangeAttributeDefinition( name="island_size", levels=[5, 10, 20, 30], - default_level=0, description="Size of the islands in the grid", - attr_type=AttributeType.APPEND, - min_value=0, lower_field_name="min_island_size", upper_field_name="max_island_size", ), diff --git a/reasoning_gym/graphs/quantum_lock.py b/reasoning_gym/graphs/quantum_lock.py index 7f0b5431..76b4a30b 100644 --- a/reasoning_gym/graphs/quantum_lock.py +++ b/reasoning_gym/graphs/quantum_lock.py @@ -4,7 +4,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -243,10 +243,7 @@ class QuantumLockCurriculum(BaseCurriculum): name="difficulty", field_name="difficulty", levels=list(range(1, 11)), - default_level=0, - attr_type=AttributeType.STATIC, description="The difficulty of the puzzle", - min_value=1, ) ) diff --git a/reasoning_gym/graphs/shortest_path.py b/reasoning_gym/graphs/shortest_path.py index d083d1a7..0021933d 100644 --- a/reasoning_gym/graphs/shortest_path.py +++ b/reasoning_gym/graphs/shortest_path.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset QUESTION_TEMPLATE = """Your task is to find the shortest path from the start to the destination point in a grid. @@ -178,20 +178,14 @@ class ShortestPathCurriculum(BaseCurriculum): RangeAttributeDefinition( name="rows", levels=[10, 25, 50, 100], - default_level=0, description="Number of rows in the grid", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_rows", upper_field_name="max_rows", ), RangeAttributeDefinition( name="cols", levels=[10, 25, 50, 100], - default_level=0, description="Number of columns in the grid", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_cols", upper_field_name="max_cols", ), diff --git a/reasoning_gym/logic/aiw.py b/reasoning_gym/logic/aiw.py index 5f982249..95e034e1 100644 --- a/reasoning_gym/logic/aiw.py +++ b/reasoning_gym/logic/aiw.py @@ -4,7 +4,7 @@ from random import Random from string import Template from typing import Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -216,7 +216,6 @@ class AliceInWonderlandCurriculum(BaseCurriculum): ScalarAttributeDefinition( name="task_type_weight", field_name="task_type_weights", - attr_type=AttributeType.STATIC, description="The weight of the task type", levels=[ [1.0, 0.0, 0.0], @@ -229,17 +228,12 @@ class AliceInWonderlandCurriculum(BaseCurriculum): [0.2, 0.4, 0.4], [0.1, 0.45, 0.45], ], - min_value=[1.0, 0.0, 0.0], - default_level=0, ), ScalarAttributeDefinition( name="num_entities", field_name="max_entities", - attr_type=AttributeType.STATIC, description="The number of entities in the question", levels=list(range(4, 18, 2)), - min_value=4, - default_level=0, ), ) diff --git a/reasoning_gym/logic/circuit_logic.py b/reasoning_gym/logic/circuit_logic.py index 798d1277..c7868dbb 100644 --- a/reasoning_gym/logic/circuit_logic.py +++ b/reasoning_gym/logic/circuit_logic.py @@ -2,7 +2,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset VERT = "│" @@ -413,22 +413,18 @@ class CircuitLogicCurriculum(BaseCurriculum): RangeAttributeDefinition( name="terms", levels=[3, 5, 10, 20, 30], - default_level=1, description="Number of terms in the expression", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_terms", upper_field_name="max_terms", + ensure_interval=True, ), RangeAttributeDefinition( name="inputs", levels=[2, 4, 6, 8, 10], - default_level=1, description="Number of inputs per term", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_inputs", upper_field_name="max_inputs", + ensure_interval=True, ), ) diff --git a/reasoning_gym/logic/propositional_logic.py b/reasoning_gym/logic/propositional_logic.py index b7033f4a..f80cccdd 100644 --- a/reasoning_gym/logic/propositional_logic.py +++ b/reasoning_gym/logic/propositional_logic.py @@ -6,7 +6,7 @@ from enum import StrEnum from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, RangeAttributeDefinition +from ..coaching import BaseCurriculum, RangeAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -346,30 +346,21 @@ class PropositionalLogicCurriculum(BaseCurriculum): RangeAttributeDefinition( name="vars", levels=[2, 4, 6, 8, 10], - default_level=0, description="Number of variables in the logical expressions", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_vars", upper_field_name="max_vars", ), RangeAttributeDefinition( name="statements", levels=[2, 4, 6, 8, 10], - default_level=0, description="Number of premises in the logical expressions", - attr_type=AttributeType.APPEND, - min_value=2, lower_field_name="min_statements", upper_field_name="max_statements", ), RangeAttributeDefinition( name="complexity", levels=[1, 2, 3, 4, 5], - default_level=0, description="Complexity of the logical expressions", - attr_type=AttributeType.APPEND, - min_value=1, lower_field_name="min_complexity", upper_field_name="max_complexity", ), diff --git a/reasoning_gym/logic/self_reference.py b/reasoning_gym/logic/self_reference.py index 821e74e5..df89c4f2 100644 --- a/reasoning_gym/logic/self_reference.py +++ b/reasoning_gym/logic/self_reference.py @@ -2,7 +2,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -376,10 +376,7 @@ class SelfReferenceCurriculum(BaseCurriculum): name="difficulty", field_name="difficulty", levels=list(range(1, 11)), - default_level=0, description="The difficulty of the puzzle", - attr_type=AttributeType.STATIC, - min_value=1, ) ) diff --git a/reasoning_gym/logic/zebra_puzzles.py b/reasoning_gym/logic/zebra_puzzles.py index e891b760..143f52c7 100644 --- a/reasoning_gym/logic/zebra_puzzles.py +++ b/reasoning_gym/logic/zebra_puzzles.py @@ -2,7 +2,7 @@ from dataclasses import dataclass from random import Random from typing import Any, Optional -from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition +from ..coaching import BaseCurriculum, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset from .contrib.logic_puzzle.generate import generate_puzzle @@ -81,19 +81,13 @@ class ZebraCurriculum(BaseCurriculum): ScalarAttributeDefinition( name="num_people", levels=list(range(2, 8)), - default_level=0, description="The number of people in the Zebra puzzle", - attr_type=AttributeType.STATIC, - min_value=2, field_name="num_people", ), ScalarAttributeDefinition( name="num_characteristics", levels=list(range(2, 8)), - default_level=0, description="The number of characteristics in the Zebra puzzle", - attr_type=AttributeType.STATIC, - min_value=2, field_name="num_characteristics", ), ) diff --git a/scripts/generate_gallery.py b/scripts/generate_gallery.py index 057947f2..0c9e5d28 100755 --- a/scripts/generate_gallery.py +++ b/scripts/generate_gallery.py @@ -17,6 +17,7 @@ def generate_gallery() -> str: # Add index content.append(f"## Available Datasets ({len(DATASETS)})\n") + content.append("Legend: ✅ = Has curriculum, ❌ = No curriculum\n\n") for name in sorted(DATASETS.keys()): # Create anchor link anchor = name.replace(" ", "-").lower() diff --git a/tests/coaching/test_curriculum_experiment.py b/tests/coaching/test_curriculum_experiment.py index 5088d683..49072483 100644 --- a/tests/coaching/test_curriculum_experiment.py +++ b/tests/coaching/test_curriculum_experiment.py @@ -3,6 +3,7 @@ import io import pytest import yaml +from reasoning_gym.coaching.base_curriculum import DefaultCurriculumContext, RangeAttributeMode from reasoning_gym.coaching.curriculum_config import CurriculumAttributeConfig, CurriculumExperimentConfig from reasoning_gym.coaching.experiment import CurriculumExperiment @@ -16,7 +17,13 @@ def test_curriculum_experiment_initialization(): ) # Create experiment - experiment = CurriculumExperiment(name="test_experiment", config=config, size=10, seed=42) + experiment = CurriculumExperiment( + name="test_experiment", + config=config, + context=DefaultCurriculumContext(mode=RangeAttributeMode.INCLUSIVE), + size=10, + seed=42, + ) # Check experiment was created correctly assert experiment.name == "test_experiment" @@ -66,7 +73,8 @@ def test_curriculum_experiment_mixed_levels(): } ) - experiment = CurriculumExperiment(name="test_experiment", config=config, size=10, seed=42) + context = DefaultCurriculumContext(mode=RangeAttributeMode.UPPER_BOUND) + experiment = CurriculumExperiment(name="test_experiment", config=config, context=context, size=10, seed=42) curriculum = experiment.curricula["leg_counting"] assert curriculum.get_attr_level("num_animals") == 4 # Specific override @@ -116,7 +124,8 @@ def test_curriculum_experiment_from_yaml(): assert chain_sum.weight == 0.8 # Create experiment from the loaded config - experiment = CurriculumExperiment(name="yaml_test", config=config, size=10, seed=42) + context = DefaultCurriculumContext(mode=RangeAttributeMode.UPPER_BOUND) + experiment = CurriculumExperiment(name="yaml_test", config=config, context=context, size=10, seed=42) # Verify experiment was created correctly assert "leg_counting" in experiment.curricula diff --git a/tests/test_base_conversion.py b/tests/test_base_conversion.py index 054257d0..1e08840b 100644 --- a/tests/test_base_conversion.py +++ b/tests/test_base_conversion.py @@ -169,7 +169,7 @@ def test_base_conversion_formatting(): assert "use lowercase letters" in item["question"] -def test_base_conversion__curriculum(): +def test_base_conversion_curriculum(): curriculum = BaseConversionCurriculum() base_value = {"size": 150, "seed": 1} @@ -178,17 +178,17 @@ def test_base_conversion__curriculum(): assert base_cfg.seed == 1 assert base_cfg.size == 150 assert base_cfg.min_base == 2 and base_cfg.max_base == 9 - assert base_cfg.min_value == 1000 and base_cfg.max_value == 1000 + assert base_cfg.min_value == 1000 and base_cfg.max_value == 10_000 # test incrementing attribute levels curriculum.increment_attr_level("base") curriculum.increment_attr_level("value") increased_cfg = curriculum.generate_configuration(base_value) assert increased_cfg.min_base == 2 and increased_cfg.max_base == 18 - assert increased_cfg.min_value == 1000 and increased_cfg.max_value == 10000 + assert increased_cfg.min_value == 1000 and increased_cfg.max_value == 100_000 # test decrementing attribute level for base again curriculum.decrement_attr_level("base") partially_decreased_cfg = curriculum.generate_configuration(base_value) assert partially_decreased_cfg.min_base == 2 and partially_decreased_cfg.max_base == 9 - assert partially_decreased_cfg.min_value == 1000 and partially_decreased_cfg.max_value == 10000 + assert partially_decreased_cfg.min_value == 1000 and partially_decreased_cfg.max_value == 100_000 diff --git a/tests/test_cryptarithm.py b/tests/test_cryptarithm.py index 41bd247e..8e8c212d 100644 --- a/tests/test_cryptarithm.py +++ b/tests/test_cryptarithm.py @@ -208,4 +208,4 @@ def test_cryptarithm_curriculum(): curriculum.decrement_attr_level("words") lower_bound_cfg: CryptarithmCurriculum = curriculum.generate_configuration(base_value) assert lower_bound_cfg.min_words == 2 - assert lower_bound_cfg.max_words == 2 + assert lower_bound_cfg.max_words == 5 diff --git a/tests/test_emoji_mystery.py b/tests/test_emoji_mystery.py index 4d754f45..d1bb7161 100644 --- a/tests/test_emoji_mystery.py +++ b/tests/test_emoji_mystery.py @@ -2,6 +2,7 @@ from random import Random import pytest +from reasoning_gym.coaching.base_curriculum import DefaultCurriculumContext, RangeAttributeMode from reasoning_gym.games.emoji_mystery import EmojiMysteryConfig, EmojiMysteryCurriculum, EmojiMysteryDataset @@ -110,7 +111,8 @@ def test_emoji_mystery_curriculum(): base_value = {"size": 150, "seed": 1} # Test base configuration - base_cfg: EmojiMysteryConfig = curriculum.generate_configuration(base_value) + context = DefaultCurriculumContext(mode=RangeAttributeMode.UPPER_BOUND) + base_cfg: EmojiMysteryConfig = curriculum.generate_configuration(base_value, context=context) assert base_cfg.seed == 1 assert base_cfg.size == 150 assert base_cfg.min_words_in_sentence == 3 @@ -118,18 +120,18 @@ def test_emoji_mystery_curriculum(): # Test incrementing attribute level curriculum.increment_attr_level("num_words_in_sentence") - increased_cfg = curriculum.generate_configuration(base_value) + increased_cfg = curriculum.generate_configuration(base_value, context=context) assert increased_cfg.min_words_in_sentence == 10 assert increased_cfg.max_words_in_sentence == 10 # Test incrementing attribute level again curriculum.increment_attr_level("num_words_in_sentence") - double_increased_cfg = curriculum.generate_configuration(base_value) + double_increased_cfg = curriculum.generate_configuration(base_value, context=context) assert double_increased_cfg.min_words_in_sentence == 20 assert double_increased_cfg.max_words_in_sentence == 20 # Test decrementing attribute level curriculum.decrement_attr_level("num_words_in_sentence") - decreased_cfg = curriculum.generate_configuration(base_value) + decreased_cfg = curriculum.generate_configuration(base_value, context=context) assert decreased_cfg.min_words_in_sentence == 10 assert decreased_cfg.max_words_in_sentence == 10 diff --git a/tests/test_futoshiki.py b/tests/test_futoshiki.py index aebf9dc7..dd89a61c 100644 --- a/tests/test_futoshiki.py +++ b/tests/test_futoshiki.py @@ -1,5 +1,6 @@ import pytest +from reasoning_gym.coaching.base_curriculum import DefaultCurriculumContext, RangeAttributeMode from reasoning_gym.games import FutoshikiConfig, FutoshikiDataset @@ -196,7 +197,8 @@ def test_futoshiki_curriculum(): base_value = {"size": 150, "seed": 1} - base_cfg: FutoshikiConfig = curriculum.generate_configuration(base_value) + context = DefaultCurriculumContext(mode=RangeAttributeMode.UPPER_BOUND) + base_cfg: FutoshikiConfig = curriculum.generate_configuration(base_value, context=context) assert base_cfg.seed == 1 assert base_cfg.size == 150 assert base_cfg.min_board_size == 4 and base_cfg.max_board_size == 4 @@ -205,46 +207,46 @@ def test_futoshiki_curriculum(): # Test incrementing attribute levels curriculum.increment_attr_level("board_size") curriculum.increment_attr_level("difficulty") - increased_cfg = curriculum.generate_configuration(base_value) + increased_cfg = curriculum.generate_configuration(base_value, context=context) assert increased_cfg.min_board_size == 6 and increased_cfg.max_board_size == 6 assert increased_cfg.min_difficulty == 1 and increased_cfg.max_difficulty == 1 # Test incrementing again curriculum.increment_attr_level("board_size") curriculum.increment_attr_level("difficulty") - increased_cfg2 = curriculum.generate_configuration(base_value) + increased_cfg2 = curriculum.generate_configuration(base_value, context=context) assert increased_cfg2.min_board_size == 7 and increased_cfg2.max_board_size == 7 assert increased_cfg2.min_difficulty == 2 and increased_cfg2.max_difficulty == 2 # Test incrementing to max levels curriculum.increment_attr_level("board_size") curriculum.increment_attr_level("difficulty") - max_cfg = curriculum.generate_configuration(base_value) + max_cfg = curriculum.generate_configuration(base_value, context=context) assert max_cfg.min_board_size == 9 and max_cfg.max_board_size == 9 assert max_cfg.min_difficulty == 3 and max_cfg.max_difficulty == 3 # Test that we can't go beyond max levels assert not curriculum.increment_attr_level("board_size") assert not curriculum.increment_attr_level("difficulty") - still_max_cfg = curriculum.generate_configuration(base_value) + still_max_cfg = curriculum.generate_configuration(base_value, context=context) assert still_max_cfg.min_board_size == 9 and still_max_cfg.max_board_size == 9 assert still_max_cfg.min_difficulty == 3 and still_max_cfg.max_difficulty == 3 # Test decrementing attribute levels curriculum.decrement_attr_level("board_size") curriculum.decrement_attr_level("difficulty") - decreased_cfg = curriculum.generate_configuration(base_value) + decreased_cfg = curriculum.generate_configuration(base_value, context=context) assert decreased_cfg.min_board_size == 7 and decreased_cfg.max_board_size == 7 assert decreased_cfg.min_difficulty == 2 and decreased_cfg.max_difficulty == 2 # Test global level setting curriculum.set_global_level(0) - global_lvl0_cfg = curriculum.generate_configuration(base_value) + global_lvl0_cfg = curriculum.generate_configuration(base_value, context=context) assert global_lvl0_cfg.min_board_size == 4 and global_lvl0_cfg.max_board_size == 4 assert global_lvl0_cfg.min_difficulty == 0 and global_lvl0_cfg.max_difficulty == 0 # Test global level increment curriculum.increment_global_level() - global_lvl1_cfg = curriculum.generate_configuration(base_value) + global_lvl1_cfg = curriculum.generate_configuration(base_value, context=context) assert global_lvl1_cfg.min_board_size == 6 and global_lvl1_cfg.max_board_size == 6 assert global_lvl1_cfg.min_difficulty == 1 and global_lvl1_cfg.max_difficulty == 1 diff --git a/tests/test_graph_color.py b/tests/test_graph_color.py index 7b81842c..1ca27e2b 100644 --- a/tests/test_graph_color.py +++ b/tests/test_graph_color.py @@ -3,6 +3,7 @@ import json import pytest from reasoning_gym.algorithmic.graph_color import GraphColorConfig, GraphColorCurriculum, GraphColorDataset +from reasoning_gym.coaching.base_curriculum import DefaultCurriculumContext, RangeAttributeMode def test_graph_color(): @@ -79,14 +80,15 @@ def test_graph_color_curriculum(): base_value = {"size": 150, "seed": 1} - base_cfg: GraphColorConfig = curriculum.generate_configuration(base_value) + context = DefaultCurriculumContext(mode=RangeAttributeMode.UPPER_BOUND) + base_cfg: GraphColorConfig = curriculum.generate_configuration(base_value, context=context) assert base_cfg.size == 150 assert base_cfg.seed == 1 assert base_cfg.min_num_vertices == base_cfg.max_num_vertices == 10 assert base_cfg.num_colors == base_cfg.num_colors == 5 curriculum.increment_attr_level("num_vertices") - cfg = curriculum.generate_configuration(base_value) + cfg = curriculum.generate_configuration(base_value, context=context) assert cfg.min_num_vertices == 20 curriculum.increment_attr_level("num_colors")