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

Secrets #268

Merged
merged 15 commits into from Jun 5, 2016

Conversation

@bvssvni
Copy link
Member

commented Jun 5, 2016

See #266

This PR adds optional "secret" information in bool and f64 that is automatically derived from any composition of /all and /any with min/max loops.

What is a "secret"?

A secret is when a bool or f64 contains additional information that explains the reason why it has the current value. It allows you to write shorter algorithms with the same expressiveness as a longer algorithm.

For example, this is normally how you would solve something:

fn main() {
    // Find where 3 is in 2D array
    data := [[1, 2], [3, 4]]
    hit := []
    x := any i, j {
        // remember the indices for later
        hit = clone([i, j])
        data[i][j] == 3
    }
    println(x) // prints `true`
    if x {
        println(hit) // prints `[1, 0]`
    }
}

When using a secret, you only need to look up the data and then unlock the secret with why:

fn main() {
    // Find where 3 is in 2D array
    data := [[1, 2], [3, 4]]
    x := any i, j { data[i][j] == 3 }
    println(x) // prints `true`
    if x {
        println(why(x)) // prints `[1, 0]`
    }
}

How to use secrets

Dyon will not tell you a secret unless you ask. There are two questions you can ask:

  • why(bool) - why has this expression a true value?
  • where(f64) - where does this number come from?

The secret contains the answer to any meaningful question you can ask within the Dyon syntax. There are some questions that do not have meaning, but an error message will help you if it is wrong.

You can add information to a secret:

  • explain_why(bool, any)
  • explain_where(f64, any)

For example, we want to find "the top soccer player who scored most goals in a season where no player scored more than 50 goals":

fn main() {
    seasons := [
        season(players: ["Ronaldo", "Hughes", "Solskjear"], goals: [20, 30, 40]),
        season(players: ["Ronaldo", "Solskjear", "Beckham"], goals: [30, 5, 60])
    ]
    top_players := []
    loop {
        top := any j {
            // Skip seasons we already have.
            if any i {top_players[i].season == j} {continue}
            max k {
                // Add name of player to secret.
                explain_where(seasons[j].goals[k], seasons[j].players[k])
            } <= 50
        }
        if top {
            player := why(top) // `[season, player_index, player_name]`
            season := player[0]
            name := player[2]
            push(mut top_players, {name: name, season: season})
        } else {
            break
        }
    }

    top_all_time := max i {
        explain_where(sum j, k {
            if seasons[j].players[k] != top_players[i].name {continue}
            seasons[j].goals[k]
        }, top_players[i].name)
    }
    println(top_all_time)
    player := where(top_all_time) // `[top_player_index, name]`
    name := player[1]
    println(link {
        "***** TOP PLAYER OF ALL TIME *****\n"
        "(in a season where no one scored more than 50 goals)\n"
        "name: "name"\n"
        "total goals: "top_all_time
    })
}

fn season_players_goals(players: [Player str], goals: [Goal f64]) -> Season {} {
    return {players: clone(players), goals: clone(goals)}
}

For detail information on usage, see #266.

Performance

About the same performance as before.

Secrets use unused memory on the stack for bool and f64, which just adds noise in the CPU in the old design. Now this memory is used for something useful instead.

> cargo bench --no-default-features

Before:
test tests::bench_add           ... bench:  37,717,453 ns/iter (+/- 1,614,769)
test tests::bench_add_n         ... bench:  14,616,886 ns/iter (+/- 1,285,910)
test tests::bench_array         ... bench:  17,695,557 ns/iter (+/- 1,337,122)
test tests::bench_call          ... bench:  14,572,437 ns/iter (+/- 1,140,259)
test tests::bench_len           ... bench:   4,364,858 ns/iter (+/- 61,915)
test tests::bench_main          ... bench:   2,811,989 ns/iter (+/- 620,300)
test tests::bench_min           ... bench:  19,331,742 ns/iter (+/- 8,734,349)
test tests::bench_min_fn        ... bench:  68,351,184 ns/iter (+/- 2,318,444)
test tests::bench_n_body        ... bench:  77,586,475 ns/iter (+/- 2,799,391)
test tests::bench_object        ... bench:  25,001,941 ns/iter (+/- 1,325,744)
test tests::bench_primes        ... bench:  44,836,037 ns/iter (+/- 2,023,154)
test tests::bench_primes_trad   ... bench:  41,716,035 ns/iter (+/- 3,406,816)
test tests::bench_push_array    ... bench:  30,177,673 ns/iter (+/- 1,751,569)
test tests::bench_push_link     ... bench:  18,765,024 ns/iter (+/- 1,434,006)
test tests::bench_push_link_go  ... bench:  16,362,509 ns/iter (+/- 1,312,540)
test tests::bench_push_str      ... bench:  58,795,158 ns/iter (+/- 2,405,857)
test tests::bench_sum           ... bench:   7,702,345 ns/iter (+/- 147,142)
test tests::bench_threads_go    ... bench:  37,036,660 ns/iter (+/- 8,532,265)
test tests::bench_threads_no_go ... bench:  41,122,474 ns/iter (+/- 2,521,186)

After:
test tests::bench_add           ... bench:  38,682,841 ns/iter (+/- 3,022,350)
test tests::bench_add_n         ... bench:  14,829,879 ns/iter (+/- 1,179,044)
test tests::bench_array         ... bench:  17,882,145 ns/iter (+/- 2,030,805)
test tests::bench_call          ... bench:  14,515,100 ns/iter (+/- 283,567)
test tests::bench_len           ... bench:   4,373,537 ns/iter (+/- 215,369)
test tests::bench_main          ... bench:   2,714,065 ns/iter (+/- 91,400)
test tests::bench_min           ... bench:  17,690,083 ns/iter (+/- 1,343,964)
test tests::bench_min_fn        ... bench:  70,413,785 ns/iter (+/- 2,478,823)
test tests::bench_n_body        ... bench:  77,278,631 ns/iter (+/- 3,117,824)
test tests::bench_object        ... bench:  25,243,269 ns/iter (+/- 1,255,676)
test tests::bench_primes        ... bench:  45,571,669 ns/iter (+/- 1,689,668)
test tests::bench_primes_trad   ... bench:  42,000,813 ns/iter (+/- 2,374,243)
test tests::bench_push_array    ... bench:  30,159,983 ns/iter (+/- 1,332,921)
test tests::bench_push_link     ... bench:  18,659,780 ns/iter (+/- 1,210,232)
test tests::bench_push_link_go  ... bench:  16,285,420 ns/iter (+/- 1,042,156)
test tests::bench_push_str      ... bench:  59,548,442 ns/iter (+/- 3,023,884)
test tests::bench_sum           ... bench:   7,836,280 ns/iter (+/- 539,327)
test tests::bench_threads_go    ... bench:  41,566,087 ns/iter (+/- 11,508,861)
test tests::bench_threads_no_go ... bench:  41,338,040 ns/iter (+/- 3,806,221)

@bvssvni bvssvni referenced this pull request Jun 5, 2016

Closed

Release v0.8 #269

7 of 7 tasks complete
@bvssvni

This comment has been minimized.

Copy link
Member Author

commented Jun 5, 2016

Merging 🎉

@bvssvni bvssvni merged commit a0fb1d5 into PistonDevelopers:master Jun 5, 2016

@bvssvni bvssvni deleted the bvssvni:secrets branch Jun 5, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
1 participant
You can’t perform that action at this time.