diff --git a/reasoning_gym/algebra/__init__.py b/reasoning_gym/algebra/__init__.py index 9ed7c5b1..c5a5b9b4 100644 --- a/reasoning_gym/algebra/__init__.py +++ b/reasoning_gym/algebra/__init__.py @@ -1,13 +1,18 @@ -from .complex_arithmetic import ComplexArithmeticConfig, ComplexArithmeticDataset +from .complex_arithmetic import ComplexArithmeticConfig, ComplexArithmeticCurriculum, ComplexArithmeticDataset from .intermediate_integration import IntermediateIntegrationConfig, IntermediateIntegrationDataset from .polynomial_equations import PolynomialEquationsConfig, PolynomialEquationsCurriculum, PolynomialEquationsDataset -from .polynomial_multiplication import PolynomialMultiplicationConfig, PolynomialMultiplicationDataset +from .polynomial_multiplication import ( + PolynomialMultiplicationConfig, + PolynomialMultiplicationCurriculum, + PolynomialMultiplicationDataset, +) from .simple_equations import SimpleEquationsConfig, SimpleEquationsDataset from .simple_integration import SimpleIntegrationConfig, SimpleIntegrationCurriculum, SimpleIntegrationDataset __all__ = [ "ComplexArithmeticConfig", "ComplexArithmeticDataset", + "ComplexArithmeticCurriculum", "IntermediateIntegrationConfig", "IntermediateIntegrationDataset", "PolynomialEquationsConfig", @@ -20,4 +25,5 @@ __all__ = [ "SimpleIntegrationDataset", "PolynomialMultiplicationConfig", "PolynomialMultiplicationDataset", + "PolynomialMultiplicationCurriculum", ] diff --git a/reasoning_gym/algebra/polynomial_multiplication.py b/reasoning_gym/algebra/polynomial_multiplication.py index 9a0d51dd..8c913203 100644 --- a/reasoning_gym/algebra/polynomial_multiplication.py +++ b/reasoning_gym/algebra/polynomial_multiplication.py @@ -5,6 +5,7 @@ from typing import Any, Optional import sympy as sp from sympy.polys.monomials import itermonomials +from ..coaching import AttributeType, BaseCurriculum, ScalarAttributeDefinition from ..factory import ProceduralDataset, register_dataset @@ -110,6 +111,16 @@ When performing calculations, please follow these guidelines: "metadata": { "polynomial_expr": str(polynomial_expr), "variables": list(product.free_symbols), + "difficulty": { + "min_terms": self.config.min_terms, + "max_terms": self.config.max_terms, + "min_value": self.config.min_value, + "max_value": self.config.max_value, + "min_degree": self.config.min_degree, + "max_degree": self.config.max_degree, + "min_polynomials": self.config.min_polynomials, + "max_polynomials": self.config.max_polynomials, + }, }, } @@ -159,4 +170,92 @@ When performing calculations, please follow these guidelines: return reward -register_dataset("polynomial_multiplication", PolynomialMultiplicationDataset, PolynomialMultiplicationConfig) +class PolynomialMultiplicationCurriculum(BaseCurriculum): + """Curriculum for complex number arithmetic problems.""" + + def __init__(self): + super().__init__(PolynomialMultiplicationCurriculum.__name__, PolynomialMultiplicationConfig) + + # Define attributes + self._define_attributes( + ScalarAttributeDefinition( + 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, + ), + ) + + +register_dataset( + "polynomial_multiplication", + PolynomialMultiplicationDataset, + PolynomialMultiplicationConfig, + PolynomialMultiplicationCurriculum, +) diff --git a/tests/test_polynomial_multiplication.py b/tests/test_polynomial_multiplication.py index 0ddf334a..05567c78 100644 --- a/tests/test_polynomial_multiplication.py +++ b/tests/test_polynomial_multiplication.py @@ -6,6 +6,7 @@ import sympy as sp from reasoning_gym import create_dataset from reasoning_gym.algebra.polynomial_multiplication import ( PolynomialMultiplicationConfig, + PolynomialMultiplicationCurriculum, PolynomialMultiplicationDataset, ) @@ -236,3 +237,102 @@ def test_score_function(): assert ds.score_answer(None, item) == 0.0 assert ds.score_answer("Not a polynomial", item) == 0.0 assert ds.score_answer("x**4", item) == 0.0 + + +def test_polynomial_multiplication_curriculum(): + """Test curriculum for polynomial multiplication.""" + curriculum = PolynomialMultiplicationCurriculum() + base_value = {"size": 150, "seed": 1} + + base_cfg: PolynomialMultiplicationCurriculum = curriculum.generate_configuration(base_value) + + assert base_cfg.seed == 1 + assert base_cfg.size == 150 + assert base_cfg.min_terms == 2 + assert base_cfg.max_terms == 4 + assert base_cfg.min_value == 1 + assert base_cfg.max_value == 100 + assert base_cfg.min_degree == 0 + assert base_cfg.max_degree == 2 + assert base_cfg.min_polynomials == 2 + assert base_cfg.max_polynomials == 4 + + # Increase and validate increase in level + curriculum.increment_attr_level("min_terms") + curriculum.increment_attr_level("max_terms") + curriculum.increment_attr_level("min_value") + curriculum.increment_attr_level("max_value") + curriculum.increment_attr_level("min_degree") + curriculum.increment_attr_level("max_degree") + curriculum.increment_attr_level("min_polynomials") + curriculum.increment_attr_level("max_polynomials") + + increased_cfg: PolynomialMultiplicationCurriculum = curriculum.generate_configuration(base_value) + assert increased_cfg.min_terms == 4 + assert increased_cfg.max_terms == 8 + assert increased_cfg.min_value == 10 + assert increased_cfg.max_value == 10000 + assert increased_cfg.min_degree == 1 + assert increased_cfg.max_degree == 4 + assert increased_cfg.min_polynomials == 3 + assert increased_cfg.max_polynomials == 6 + + # Decrease and validate decrease in level + curriculum.decrement_attr_level("min_terms") + curriculum.decrement_attr_level("max_terms") + curriculum.decrement_attr_level("min_value") + curriculum.decrement_attr_level("max_value") + curriculum.decrement_attr_level("min_degree") + curriculum.decrement_attr_level("max_degree") + curriculum.decrement_attr_level("min_polynomials") + curriculum.decrement_attr_level("max_polynomials") + + decreased_cfg: PolynomialMultiplicationCurriculum = curriculum.generate_configuration(base_value) + assert decreased_cfg.min_terms == 2 + assert decreased_cfg.max_terms == 4 + assert decreased_cfg.min_value == 1 + assert decreased_cfg.max_value == 100 + assert decreased_cfg.min_degree == 0 + assert decreased_cfg.max_degree == 2 + assert decreased_cfg.min_polynomials == 2 + assert decreased_cfg.max_polynomials == 4 + + # Test upper bound boundary condition + for _ in range(10): + curriculum.increment_attr_level("min_terms") + curriculum.increment_attr_level("max_terms") + curriculum.increment_attr_level("min_value") + curriculum.increment_attr_level("max_value") + curriculum.increment_attr_level("min_degree") + curriculum.increment_attr_level("max_degree") + curriculum.increment_attr_level("min_polynomials") + curriculum.increment_attr_level("max_polynomials") + upper_bound_cfg: PolynomialMultiplicationCurriculum = curriculum.generate_configuration(base_value) + assert upper_bound_cfg.min_terms == 8 + assert upper_bound_cfg.max_terms == 16 + assert upper_bound_cfg.min_value == 1000 + assert upper_bound_cfg.max_value == 100000000 + assert upper_bound_cfg.min_degree == 3 + assert upper_bound_cfg.max_degree == 10 + assert upper_bound_cfg.min_polynomials == 5 + assert upper_bound_cfg.max_polynomials == 10 + + # Test lower bound boundary condition + for _ in range(10): + curriculum.decrement_attr_level("min_terms") + curriculum.decrement_attr_level("max_terms") + curriculum.decrement_attr_level("min_value") + curriculum.decrement_attr_level("max_value") + curriculum.decrement_attr_level("min_degree") + curriculum.decrement_attr_level("max_degree") + curriculum.decrement_attr_level("min_polynomials") + curriculum.decrement_attr_level("max_polynomials") + lower_bound_cfg: PolynomialMultiplicationCurriculum = curriculum.generate_configuration(base_value) + assert lower_bound_cfg.min_terms == 2 + assert lower_bound_cfg.max_terms == 4 + assert lower_bound_cfg.min_value == 1 + assert lower_bound_cfg.max_value == 100 + assert lower_bound_cfg.min_degree == 0 + assert lower_bound_cfg.max_degree == 2 + assert lower_bound_cfg.min_polynomials == 2 + assert lower_bound_cfg.max_polynomials == 4