Skip to content

Turing complete expressions #123

New issue

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

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

Already on GitHub? # to your account

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

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

Successfully merging this pull request may close these issues.

1 participant