Struct programinduction::lambda::Language [] [src]

pub struct Language {
    pub primitives: Vec<(String, TypeSchema, f64)>,
    pub invented: Vec<(Expression, TypeSchema, f64)>,
    pub variable_logprob: f64,
}

(representation) A Language is a registry for primitive and invented expressions in a polymorphically-typed lambda calculus with corresponding production log-probabilities.

Fields

Methods

impl Language
[src]

[src]

A uniform distribution over primitives and invented expressions, as well as the abstraction operation.

[src]

Infer the type of an Expression.

Examples

let mut dsl = Language::uniform(vec![
        ("singleton", ptp!(0; @arrow[tp!(0), tp!(list(tp!(0)))])),
        (">=", ptp!(@arrow[tp!(int), tp!(int), tp!(bool)])),
        ("+", ptp!(@arrow[tp!(int), tp!(int), tp!(int)])),
        ("0", ptp!(int)),
        ("1", ptp!(int)),
]);
dsl.invent(
    Expression::Application( // (+ 1)
        Box::new(Expression::Primitive(2)),
        Box::new(Expression::Primitive(4)),
    ),
    0f64,
);
let expr = dsl.parse("(singleton ((λ (>= $0 1)) (#(+ 1) 0)))")
    .unwrap();
assert_eq!(dsl.infer(&expr).unwrap(), ptp!(list(tp!(bool))));

Important traits for Box<W>
[src]

Enumerate expressions for a request type (including log-probabilities and appropriately instantiated Types):

Examples

use programinduction::lambda::{Expression, Language};

let dsl = Language::uniform(vec![
    ("0", ptp!(int)),
    ("1", ptp!(int)),
    ("+", ptp!(@arrow[tp!(int), tp!(int), tp!(int)])),
    (">", ptp!(@arrow[tp!(int), tp!(int), tp!(bool)])),
]);
let exprs: Vec<Expression> = dsl.enumerate(ptp!(int))
    .take(8)
    .map(|(expr, _log_prior)| expr)
    .collect();

assert_eq!(
    exprs,
    vec![
        Expression::Primitive(0),
        Expression::Primitive(1),
        dsl.parse("(+ 0 0)").unwrap(),
        dsl.parse("(+ 0 1)").unwrap(),
        dsl.parse("(+ 1 0)").unwrap(),
        dsl.parse("(+ 1 1)").unwrap(),
        dsl.parse("(+ 0 (+ 0 0))").unwrap(),
        dsl.parse("(+ 0 (+ 0 1))").unwrap(),
    ]
);

[src]

Update production probabilities and induce new primitives, with the guarantee that any changes to the language yield net lower prior probability for expressions in the frontier.

Primitives are induced using an approach similar to Cohn et. al. in the 2010 JMLR paper Inducing Tree-Substitution Grammars and in Tim O'Donnell's Fragment Grammars detailed in his 2015 MIT Press book, Productivity and Reuse in Language: A Theory of Linguistic Computation and Storage. However, instead of using Bayesian non-parametrics, we fully evaluate posteriors under each non-trivial fragment (because we already have a tractible space of expressions — the frontiers). We repeatedly select the best fragment and re-evaluate the posteriors until the DSL does not improve.

Examples

use programinduction::domains::circuits;
use programinduction::{lambda, ECParams, EC};

let dsl = circuits::dsl();
let tasks = circuits::make_tasks(100);
let ec_params = ECParams {
    frontier_limit: 5,
    search_limit_timeout: Some(std::time::Duration::new(2, 0)),
    search_limit_description_length: None,
};
let params = lambda::CompressionParams::default();

// this is equivalent to one iteration of EC:
let frontiers = dsl.explore(&ec_params, &tasks);
let (dsl, _frontiers) = dsl.compress(&params, &tasks, frontiers);

// there should have been inventions because we started with a non-expressive DSL:
assert!(!dsl.invented.is_empty());

[src]

Evaluate an expressions based on an input/output pair.

Inputs are given as a sequence representing sequentially applied arguments.

Examples

use programinduction::lambda::{Language, SimpleEvaluator};

fn evaluate(name: &str, inps: &[i32]) -> i32 {
    match name {
        "0" => 0,
        "1" => 1,
        "+" => inps[0] + inps[1],
        _ => unreachable!(),
    }
}

let dsl = Language::uniform(vec![
    ("0", ptp!(int)),
    ("1", ptp!(int)),
    ("+", ptp!(@arrow[tp!(int), tp!(int), tp!(int)])),
]);
let eval = SimpleEvaluator::of(evaluate);
let expr = dsl.parse("(λ (λ (+ (+ 1 $0) $1)))").unwrap();
let inps = vec![2, 5];
let evaluated = dsl.eval(&expr, eval, &inps).unwrap();
assert_eq!(evaluated, 8);

[src]

Like eval, but useful in settings with a shared evaluator.

[src]

Get the log-likelihood of an expression normalized with other expressions with the given request type.

Examples

let dsl = Language::uniform(vec![
    ("0", ptp!(int)),
    ("1", ptp!(int)),
    ("+", ptp!(@arrow[tp!(int), tp!(int), tp!(int)])),
]);
let req = ptp!(@arrow[tp!(int), tp!(int), tp!(int)]);

let expr = dsl.parse("(λ (λ (+ $0 $1)))").unwrap();
assert_eq!(dsl.likelihood(&req, &expr), -5.545177444479561);

let expr = dsl.parse("(λ (λ (+ (+ $0 1) $1)))").unwrap();
assert_eq!(dsl.likelihood(&req, &expr), -8.317766166719343);

[src]

Register a new invented expression. If it has a valid type, this will be Ok(num).

Examples

let mut dsl = Language::uniform(vec![
    ("0", ptp!(int)),
    ("1", ptp!(int)),
    ("+", ptp!(@arrow[tp!(int), tp!(int), tp!(int)])),
]);
let expr = dsl.parse("(+ 1)").unwrap();
dsl.invent(expr.clone(), -0.5).unwrap();
assert_eq!(
    dsl.invented.get(0),
    Some(&(expr, ptp!(@arrow[tp!(int), tp!(int)]), -0.5))
);

[src]

Remove all invented expressions by pulling out their underlying expressions.

[src]

The inverse of display.

Lambda expressions take the form (lambda BODY) or (λ BODY), where BODY is an expression that may use a corresponding De Bruijn Index.

[src]

The inverse of parse.

[src]

Like display, but in a format ready for lisp interpretation.

Trait Implementations

impl Debug for Language
[src]

[src]

Formats the value using the given formatter. Read more

impl Clone for Language
[src]

[src]

Returns a copy of the value. Read more

1.0.0
[src]

Performs copy-assignment from source. Read more

impl EC for Language
[src]

An Expression is a sentence in the representation. Tasks are solved by Expressions.

Many representations have some parameters for compression. They belong here.

Important traits for Box<W>
[src]

Get an iterator over [Expression]s for a given type and corresponding log-priors. This enumeration should be best-first: the log-prior of enumerated expressions should generally increase, so simple expressions are enumerated first. Read more

[src]

Update the representation based on findings of expressions that solve [Task]s. Read more

[src]

The entry point for one iteration of the EC algorithm. Read more

[src]

The entry point for one iteration of the EC algorithm with a recognizer, very similar to [ec]. Read more

Important traits for Vec<u8>
[src]

Enumerate solutions for the given tasks. Read more

Important traits for Vec<u8>
[src]

Like [explore], but with specific "recognized" representations for each task. Read more

Auto Trait Implementations

impl Send for Language

impl Sync for Language