Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turing complete expressions #123

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open

Turing complete expressions #123

wants to merge 12 commits into from

Conversation

MilesCranmer
Copy link
Member

This adds special operators that extend the expressions to be turing complete. There is AssignOperator(; target_register) which assigns the argument to a specific feature of X, and WhileOperator(; max_iters) which is a binary operator consisting of a condition expression (> 0 => continue) and a body expression that is executed each time, and returned at completion.

cc @atharvas - want to take a look?

e.g., here's test code that uses a while loop and assignment to compute the Fibonacci sequence up to any input n:

    # Define operators
    while_op = WhileOperator(; max_iters=100)
    assign_ops = [AssignOperator(; target_register=i) for i in 1:5]
    operators = OperatorEnum(;
        binary_operators=[+, -, *, /, while_op], unary_operators=assign_ops
    )
    variable_names = ["x1", "x2", "x3", "x4", "x5"]

    # Test data - x2=5 (counter), x3=0 (F(0)), x4=1 (F(1))
    X = zeros(Float64, 5, 4)
    # Set different Fibonacci sequence positions to calculate
    X[2, :] = [3.0, 5.0, 7.0, 10.0]  # Calculate F(3), F(5), F(7), F(10)

    # Initialize all rows with F(0)=0, F(1)=1
    X[3, :] .= 0.0  # x3 = 0.0 (F(0))
    X[4, :] .= 1.0  # x4 = 1.0 (F(1))

    xs = [Expression(Node(; feature=i); operators, variable_names) for i in 1:5]

    # Build expression: 
    condition = xs[2]  # WhileOperator implicitly checks if > 0
    body =
        assign_ops[5](xs[3]) +
        assign_ops[3](xs[4]) +
        assign_ops[4](xs[5] + xs[4]) +
        assign_ops[2](xs[2] - 1.0)
    expr = (while_op(condition, body) * 0.0) + xs[3]

    @test string_tree(expr) ==
        "(while(x2, (((x5 ← (x3)) + (x3 ← (x4))) + (x4 ← (x5 + x4))) + (x2 ← (x2 - 1.0))) * 0.0) + x3"

    result, completed = eval_tree_array(expr, X)
    @test completed == true

    # Test each Fibonacci number is correctly calculated
    @test result  [2.0, 5.0, 13.0, 55.0]  # F(3)=2, F(5)=5, F(7)=13, F(10)=55

Copy link
Contributor

github-actions bot commented Mar 2, 2025

Benchmark Results

master 6267f5e... master / 6267f5e...
eval/ComplexF32/evaluation 7.34 ± 0.66 ms 7.32 ± 0.68 ms 1
eval/ComplexF64/evaluation 10.8 ± 1.2 ms 10.8 ± 0.95 ms 1.01
eval/Float32/derivative 12.3 ± 1.6 ms 12.6 ± 1.6 ms 0.973
eval/Float32/derivative_turbo 12.5 ± 1.7 ms 12.6 ± 1.7 ms 0.989
eval/Float32/evaluation 2.78 ± 0.26 ms 2.75 ± 0.26 ms 1.01
eval/Float32/evaluation_bumper 0.615 ± 0.015 ms 0.588 ± 0.016 ms 1.05
eval/Float32/evaluation_turbo 0.571 ± 0.028 ms 0.578 ± 0.029 ms 0.986
eval/Float32/evaluation_turbo_bumper 0.612 ± 0.015 ms 0.586 ± 0.015 ms 1.04
eval/Float64/derivative 16 ± 0.96 ms 15.7 ± 0.88 ms 1.02
eval/Float64/derivative_turbo 15.8 ± 0.83 ms 15.7 ± 0.92 ms 1.01
eval/Float64/evaluation 3.21 ± 0.34 ms 3.22 ± 0.33 ms 0.999
eval/Float64/evaluation_bumper 1.28 ± 0.044 ms 1.21 ± 0.048 ms 1.06
eval/Float64/evaluation_turbo 1.07 ± 0.061 ms 1.08 ± 0.063 ms 0.993
eval/Float64/evaluation_turbo_bumper 1.27 ± 0.047 ms 1.21 ± 0.046 ms 1.05
utils/combine_operators/break_sharing 0.0391 ± 0.00046 ms 0.0387 ± 0.00068 ms 1.01
utils/convert/break_sharing 27.4 ± 2.5 μs 27.6 ± 3.5 μs 0.991
utils/convert/preserve_sharing 0.0989 ± 0.0057 ms 0.101 ± 0.006 ms 0.983
utils/copy/break_sharing 28 ± 2.7 μs 28.3 ± 3 μs 0.99
utils/copy/preserve_sharing 0.0996 ± 0.0048 ms 0.101 ± 0.0059 ms 0.985
utils/count_constant_nodes/break_sharing 8.56 ± 0.18 μs 8.42 ± 0.27 μs 1.02
utils/count_constant_nodes/preserve_sharing 0.0889 ± 0.0054 ms 0.0868 ± 0.0051 ms 1.02
utils/count_depth/break_sharing 9.77 ± 0.27 μs 9.46 ± 0.29 μs 1.03
utils/count_nodes/break_sharing 8.46 ± 0.19 μs 8.42 ± 0.28 μs 1
utils/count_nodes/preserve_sharing 0.0856 ± 0.0041 ms 0.0877 ± 0.0048 ms 0.976
utils/get_set_constants!/break_sharing 0.0346 ± 0.0025 ms 0.0331 ± 0.0021 ms 1.04
utils/get_set_constants!/preserve_sharing 0.177 ± 0.0088 ms 0.18 ± 0.0093 ms 0.986
utils/get_set_constants_parametric 0.0452 ± 0.0028 ms 0.0451 ± 0.003 ms 1
utils/has_constants/break_sharing 4.27 ± 0.15 μs 4.38 ± 0.19 μs 0.976
utils/has_operators/break_sharing 2.23 ± 0.079 μs 1.7 ± 0.081 μs 1.31
utils/hash/break_sharing 23.4 ± 0.77 μs 23.2 ± 0.8 μs 1.01
utils/hash/preserve_sharing 0.098 ± 0.0054 ms 0.0991 ± 0.0057 ms 0.989
utils/index_constant_nodes/break_sharing 25.6 ± 1.1 μs 25 ± 1.3 μs 1.02
utils/index_constant_nodes/preserve_sharing 0.1 ± 0.004 ms 0.0999 ± 0.0055 ms 1
utils/is_constant/break_sharing 3.9 ± 0.15 μs 4.36 ± 0.18 μs 0.896
utils/simplify_tree/break_sharing 0.168 ± 0.0058 ms 0.166 ± 0.0071 ms 1.01
utils/simplify_tree/preserve_sharing 0.216 ± 0.0094 ms 0.226 ± 0.01 ms 0.956
utils/string_tree/break_sharing 0.473 ± 0.018 ms 0.498 ± 0.02 ms 0.95
utils/string_tree/preserve_sharing 0.572 ± 0.02 ms 0.614 ± 0.022 ms 0.931
time_to_load 0.217 ± 0.001 s 0.218 ± 0.005 s 0.993

Copy link
Contributor

github-actions bot commented Mar 2, 2025

Pull Request Test Coverage Report for Build 13611835520

Details

  • 89 of 91 (97.8%) changed or added relevant lines in 4 files are covered.
  • 4 unchanged lines in 1 file lost coverage.
  • Overall coverage increased (+0.08%) to 95.657%

Changes Missing Coverage Covered Lines Changed/Added Lines %
src/SpecialOperators.jl 40 42 95.24%
Files with Coverage Reduction New Missed Lines %
src/Strings.jl 4 95.28%
Totals Coverage Status
Change from base Build 13595867267: 0.08%
Covered Lines: 2643
Relevant Lines: 2763

💛 - Coveralls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant