Struct programinduction::trs::Lexicon
source · pub struct Lexicon(/* private fields */);
Expand description
(representation) Manages the syntax of a term rewriting system.
Implementations§
source§impl Lexicon
impl Lexicon
sourcepub fn new(
operators: Vec<(u32, Option<String>, TypeScheme)>,
deterministic: bool,
ctx: TypeContext
) -> Lexicon
pub fn new( operators: Vec<(u32, Option<String>, TypeScheme)>, deterministic: bool, ctx: TypeContext ) -> Lexicon
Construct a Lexicon
with only background term_rewriting::Operator
s.
Example
See polytype::ptp
for details on constructing polytype::TypeScheme
s.
use polytype::{ptp, tp, Context as TypeContext};
use programinduction::trs::Lexicon;
let operators = vec![
(2, Some("PLUS".to_string()), ptp![@arrow[tp!(int), tp!(int), tp!(int)]]),
(1, Some("SUCC".to_string()), ptp![@arrow[tp!(int), tp!(int)]]),
(0, Some("ZERO".to_string()), ptp![int]),
];
let deterministic = false;
let lexicon = Lexicon::new(operators, deterministic, TypeContext::default());
sourcepub fn from_signature(
signature: Signature,
ops: Vec<TypeScheme>,
vars: Vec<TypeScheme>,
background: Vec<Rule>,
templates: Vec<RuleContext>,
deterministic: bool,
ctx: TypeContext
) -> Lexicon
pub fn from_signature( signature: Signature, ops: Vec<TypeScheme>, vars: Vec<TypeScheme>, background: Vec<Rule>, templates: Vec<RuleContext>, deterministic: bool, ctx: TypeContext ) -> Lexicon
Convert a term_rewriting::Signature
into a Lexicon
:
ops
are types for theterm_rewriting::Operator
svars
are types for theterm_rewriting::Variable
s,background
areterm_rewriting::Rule
s that never changetemplates
areterm_rewriting::RuleContext
s that can serve as templates during learning
Example
See polytype::ptp
for details on constructing polytype::TypeScheme
s.
use polytype::{ptp, tp, Context as TypeContext};
use programinduction::trs::Lexicon;
use term_rewriting::{Signature, parse_rule, parse_rulecontext};
let mut sig = Signature::default();
let vars = vec![];
let mut ops = vec![];
sig.new_op(2, Some("PLUS".to_string()));
ops.push(ptp![@arrow[tp!(int), tp!(int), tp!(int)]]);
sig.new_op(1, Some("SUCC".to_string()));
ops.push(ptp![@arrow[tp!(int), tp!(int)]]);
sig.new_op(0, Some("ZERO".to_string()));
ops.push(ptp![int]);
let background = vec![
parse_rule(&mut sig, "PLUS(x_ ZERO) = x_").expect("parsed rule"),
parse_rule(&mut sig, "PLUS(x_ SUCC(y_)) = SUCC(PLUS(x_ y_))").expect("parsed rule"),
];
let templates = vec![
parse_rulecontext(&mut sig, "[!] = [!]").expect("parsed rulecontext"),
];
let deterministic = false;
let lexicon = Lexicon::from_signature(sig, ops, vars, background, templates, deterministic, TypeContext::default());
sourcepub fn has_op(&self, name: Option<&str>, arity: u32) -> Option<Operator>
pub fn has_op(&self, name: Option<&str>, arity: u32) -> Option<Operator>
Return the specified operator if possible.
pub fn context(&self) -> TypeContext
sourcepub fn infer_context(
&self,
context: &Context,
ctx: &mut TypeContext
) -> Result<TypeScheme, TypeError>
pub fn infer_context( &self, context: &Context, ctx: &mut TypeContext ) -> Result<TypeScheme, TypeError>
Infer the polytype::TypeScheme
associated with a term_rewriting::Context
.
Example
use polytype::{ptp, tp, Context as TypeContext};
use programinduction::trs::Lexicon;
use term_rewriting::{Context, Signature, parse_rule};
let mut sig = Signature::default();
let vars = vec![];
let mut ops = vec![];
sig.new_op(2, Some("PLUS".to_string()));
ops.push(ptp![@arrow[tp!(int), tp!(int), tp!(int)]]);
let succ = sig.new_op(1, Some("SUCC".to_string()));
ops.push(ptp![@arrow[tp!(int), tp!(int)]]);
sig.new_op(0, Some("ZERO".to_string()));
ops.push(ptp![int]);
let background = vec![];
let templates = vec![];
let deterministic = false;
let lexicon = Lexicon::from_signature(sig, ops, vars, background, templates, deterministic, TypeContext::default());
let context = Context::Application {
op: succ,
args: vec![Context::Hole]
};
let mut ctx = lexicon.context();
let inferred_scheme = lexicon.infer_context(&context, &mut ctx).unwrap();
assert_eq!(inferred_scheme, ptp![int]);
sourcepub fn infer_rulecontext(
&self,
context: &RuleContext,
ctx: &mut TypeContext
) -> Result<TypeScheme, TypeError>
pub fn infer_rulecontext( &self, context: &RuleContext, ctx: &mut TypeContext ) -> Result<TypeScheme, TypeError>
Infer the TypeScheme
associated with a RuleContext
.
sourcepub fn infer_rule(
&self,
rule: &Rule,
ctx: &mut TypeContext
) -> Result<TypeScheme, TypeError>
pub fn infer_rule( &self, rule: &Rule, ctx: &mut TypeContext ) -> Result<TypeScheme, TypeError>
Infer the TypeScheme
associated with a Rule
.
sourcepub fn infer_rules(
&self,
rules: &[Rule],
ctx: &mut TypeContext
) -> Result<TypeScheme, TypeError>
pub fn infer_rules( &self, rules: &[Rule], ctx: &mut TypeContext ) -> Result<TypeScheme, TypeError>
Infer the TypeScheme
associated with a collection of Rules
.
sourcepub fn infer_op(&self, op: &Operator) -> Result<TypeScheme, TypeError>
pub fn infer_op(&self, op: &Operator) -> Result<TypeScheme, TypeError>
Infer the TypeScheme
associated with a Rule
.
sourcepub fn sample_term<R: Rng>(
&mut self,
rng: &mut R,
scheme: &TypeScheme,
ctx: &mut TypeContext,
atom_weights: (f64, f64, f64),
invent: bool,
variable: bool,
max_size: usize
) -> Result<Term, SampleError>
pub fn sample_term<R: Rng>( &mut self, rng: &mut R, scheme: &TypeScheme, ctx: &mut TypeContext, atom_weights: (f64, f64, f64), invent: bool, variable: bool, max_size: usize ) -> Result<Term, SampleError>
Sample a term_rewriting::Term
.
Example
use polytype::{ptp, tp, Context as TypeContext};
use programinduction::trs::Lexicon;
use rand::{rngs::SmallRng, SeedableRng};
let operators = vec![
(2, Some("PLUS".to_string()), ptp![@arrow[tp!(int), tp!(int), tp!(int)]]),
(1, Some("SUCC".to_string()), ptp![@arrow[tp!(int), tp!(int)]]),
(0, Some("ZERO".to_string()), ptp![int]),
];
let deterministic = false;
let mut lexicon = Lexicon::new(operators, deterministic, TypeContext::default());
let scheme = ptp![int];
let mut ctx = lexicon.context();
let invent = true;
let variable = true;
let atom_weights = (0.5, 0.25, 0.25);
let max_size = 50;
let rng = &mut SmallRng::from_seed([1u8; 32]);
let term = lexicon.sample_term(rng, &scheme, &mut ctx, atom_weights, invent, variable, max_size).unwrap();
sourcepub fn sample_term_from_context<R: Rng>(
&mut self,
rng: &mut R,
context: &Context,
ctx: &mut TypeContext,
atom_weights: (f64, f64, f64),
invent: bool,
variable: bool,
max_size: usize
) -> Result<Term, SampleError>
pub fn sample_term_from_context<R: Rng>( &mut self, rng: &mut R, context: &Context, ctx: &mut TypeContext, atom_weights: (f64, f64, f64), invent: bool, variable: bool, max_size: usize ) -> Result<Term, SampleError>
Sample a Term
conditioned on a Context
rather than a TypeScheme
.
sourcepub fn sample_rule<R: Rng>(
&mut self,
rng: &mut R,
scheme: &TypeScheme,
ctx: &mut TypeContext,
atom_weights: (f64, f64, f64),
invent: bool,
max_size: usize
) -> Result<Rule, SampleError>
pub fn sample_rule<R: Rng>( &mut self, rng: &mut R, scheme: &TypeScheme, ctx: &mut TypeContext, atom_weights: (f64, f64, f64), invent: bool, max_size: usize ) -> Result<Rule, SampleError>
Sample a Rule
.
sourcepub fn sample_rule_from_context<R: Rng>(
&mut self,
rng: &mut R,
context: RuleContext,
ctx: &mut TypeContext,
atom_weights: (f64, f64, f64),
invent: bool,
max_size: usize
) -> Result<Rule, SampleError>
pub fn sample_rule_from_context<R: Rng>( &mut self, rng: &mut R, context: RuleContext, ctx: &mut TypeContext, atom_weights: (f64, f64, f64), invent: bool, max_size: usize ) -> Result<Rule, SampleError>
Sample a Rule
conditioned on a Context
rather than a TypeScheme
.
sourcepub fn logprior_term(
&self,
term: &Term,
scheme: &TypeScheme,
ctx: &mut TypeContext,
atom_weights: (f64, f64, f64),
invent: bool
) -> Result<f64, SampleError>
pub fn logprior_term( &self, term: &Term, scheme: &TypeScheme, ctx: &mut TypeContext, atom_weights: (f64, f64, f64), invent: bool ) -> Result<f64, SampleError>
Give the log probability of sampling a Term.
sourcepub fn logprior_rule(
&self,
rule: &Rule,
scheme: &TypeScheme,
ctx: &mut TypeContext,
atom_weights: (f64, f64, f64),
invent: bool
) -> Result<f64, SampleError>
pub fn logprior_rule( &self, rule: &Rule, scheme: &TypeScheme, ctx: &mut TypeContext, atom_weights: (f64, f64, f64), invent: bool ) -> Result<f64, SampleError>
Give the log probability of sampling a Rule.
sourcepub fn logprior_utrs(
&self,
utrs: &UntypedTRS,
schemes: &[TypeScheme],
p_rule: f64,
ctx: &mut TypeContext,
atom_weights: (f64, f64, f64),
invent: bool
) -> Result<f64, SampleError>
pub fn logprior_utrs( &self, utrs: &UntypedTRS, schemes: &[TypeScheme], p_rule: f64, ctx: &mut TypeContext, atom_weights: (f64, f64, f64), invent: bool ) -> Result<f64, SampleError>
Give the log probability of sampling a TRS.
Trait Implementations§
source§impl GP<[Rule]> for Lexicon
impl GP<[Rule]> for Lexicon
§type Expression = TRS
type Expression = TRS
§type Params = GeneticParams
type Params = GeneticParams
source§fn genesis<R: Rng>(
&self,
params: &Self::Params,
rng: &mut R,
pop_size: usize,
_tp: &TypeScheme
) -> Vec<Self::Expression>
fn genesis<R: Rng>( &self, params: &Self::Params, rng: &mut R, pop_size: usize, _tp: &TypeScheme ) -> Vec<Self::Expression>
source§fn mutate<R: Rng>(
&self,
params: &Self::Params,
rng: &mut R,
trs: &Self::Expression,
_obs: &[Rule]
) -> Vec<Self::Expression>
fn mutate<R: Rng>( &self, params: &Self::Params, rng: &mut R, trs: &Self::Expression, _obs: &[Rule] ) -> Vec<Self::Expression>
source§fn crossover<R: Rng>(
&self,
params: &Self::Params,
rng: &mut R,
parent1: &Self::Expression,
parent2: &Self::Expression,
_obs: &[Rule]
) -> Vec<Self::Expression>
fn crossover<R: Rng>( &self, params: &Self::Params, rng: &mut R, parent1: &Self::Expression, parent2: &Self::Expression, _obs: &[Rule] ) -> Vec<Self::Expression>
source§fn validate_offspring(
&self,
_params: &Self::Params,
population: &[(Self::Expression, f64)],
children: &[Self::Expression],
offspring: &mut Vec<Self::Expression>
)
fn validate_offspring( &self, _params: &Self::Params, population: &[(Self::Expression, f64)], children: &[Self::Expression], offspring: &mut Vec<Self::Expression> )
offspring
. The intended
semantics is that validate_offspring
reduces the set of newly created
individuals in offspring
to just those viable for consideration as
part of the total population
, taking into account other children
that are part of the current generation. This allows you to do things
like ensure a population of unique individuals.source§fn tournament<'a, R: Rng>(
&self,
rng: &mut R,
tournament_size: usize,
population: &'a [(Self::Expression, f64)]
) -> &'a Self::Expression
fn tournament<'a, R: Rng>( &self, rng: &mut R, tournament_size: usize, population: &'a [(Self::Expression, f64)] ) -> &'a Self::Expression
source§fn init<R: Rng>(
&self,
params: &Self::Params,
rng: &mut R,
gpparams: &GPParams,
task: &impl Task<Observation, Representation = Self, Expression = Self::Expression>
) -> Vec<(Self::Expression, f64)>
fn init<R: Rng>( &self, params: &Self::Params, rng: &mut R, gpparams: &GPParams, task: &impl Task<Observation, Representation = Self, Expression = Self::Expression> ) -> Vec<(Self::Expression, f64)>
source§fn evolve<R: Rng>(
&self,
params: &Self::Params,
rng: &mut R,
gpparams: &GPParams,
task: &impl Task<Observation, Representation = Self, Expression = Self::Expression>,
population: &mut Vec<(Self::Expression, f64)>
)
fn evolve<R: Rng>( &self, params: &Self::Params, rng: &mut R, gpparams: &GPParams, task: &impl Task<Observation, Representation = Self, Expression = Self::Expression>, population: &mut Vec<(Self::Expression, f64)> )
mutation_prob
and perform mutation or crossover depending on the outcome until
n_delta
expressions are determined.