8 #include <unordered_map> 43 template<
typename this_t,
46 typename data_t=std::vector<datum_t>,
61 using LL_t = std::unordered_map<typename datum_t::data_t*, std::vector<Vector> >;
89 std::shared_ptr<Matrix>
C;
90 std::shared_ptr<LL_t>
LL;
92 std::shared_ptr<Predict_t>
P;
158 size_t ndata()
const {
return which_data->size(); }
161 [[nodiscard]]
static this_t
sample(std::vector<HYP>& hypotheses,
const data_t* human_data) {
163 auto h = this_t(hypotheses, human_data);
175 which_data = std::addressof(human_data);
176 which_hypotheses = std::addressof(hypotheses);
179 grammar = hypotheses.at(0).get_grammar();
180 for(
auto& h: hypotheses) {
181 assert(h.get_grammar() == grammar &&
"*** It's bad news for GrammarHypothesis if your hypotheses don't all have the same grammar.");
184 if(logA.
size() != grammar->count_rules()) {
185 if(logA.
size() > 0)
print(
"*** Warning: resizing and zeroing logA");
186 logA.
set_size(grammar->count_rules());
190 COUT "# Computing prior counts" ENDL;
192 COUT "# Computing model predictions" ENDL;
194 COUT "# Computing incremental likelihoods " ENDL;
196 COUT "# Computing decayedLikelihood" ENDL;
211 if(
logA(i) != 0.0) {
CERR "# Warning, set_can_propose is setting false to logA(" <<
str(i) <<
") != 0.0 (this is untransformed space)" ENDL; }
218 for(
size_t i=0;i<logA.
size();i++) {
237 assert(hypotheses.size() > 0);
239 size_t nRules = hypotheses[0].get_grammar()->count_rules();
241 C.reset(
new Matrix(hypotheses.size(), nRules));
243 const auto indexer = grammar->get_rule_indexer();
244 const auto R = grammar->count_rules();
246 #pragma omp parallel for 247 for(
size_t i=0;i<hypotheses.size();i++) {
248 assert(hypotheses[i].get_grammar() == grammar);
251 Vector cv = Vector::Zero(R);
253 auto c = grammar->get_counts(hypotheses[i].get_value(), indexer);
254 for(
size_t r=0;r<R;r++)
258 C->row(i) = std::move(cv);
261 assert( (
size_t)C->rows() == hypotheses.size());
271 virtual void recompute_LL(std::vector<HYP>& hypotheses,
const data_t& human_data) {
272 assert(which_data == std::addressof(human_data));
276 std::unordered_map<typename datum_t::data_t*, size_t> max_sizes;
277 for(
auto& d : human_data) {
278 if( (not max_sizes.contains(d.data)) or max_sizes[d.data] < d.ndata) {
279 max_sizes[d.data] = d.ndata;
283 auto a = this->alpha.
get();
285 LL.reset(
new LL_t());
286 LL->reserve(max_sizes.size());
289 for(
const auto& [dptr, sz] : max_sizes) {
294 #pragma omp parallel for 298 Vector data_lls = Vector::Zero(sz);
301 for(
size_t i=0;i<max_sizes[dptr];i++) {
312 data_lls(i) = hypotheses[h].compute_likelihood(d);
316 assert(not std::isnan(data_lls(i)));
321 LL->at(dptr)[h] = std::move(data_lls);
344 assert(which_data == std::addressof(human_data));
351 for(
auto& di : human_data) {
352 MX = std::max(MX, di.decay_index+1);
358 Vector powers = Vector::Ones(MX);
360 for(
int i=1;i<MX;i++) {
361 powers(i) = powf(i,-dc);
365 #pragma omp parallel for 367 for(
int di=0;di<(int)human_data.size();di++) {
368 const datum_t& d = human_data[di];
369 const Vector& v = LL->at(d.data)[h];
372 for(
size_t k=0;k<d.ndata;k++) {
373 dl += v(k) * powers(d.decay_index - d.decay_position->at(k));
378 assert(not std::isnan(dl));
379 (*decayedLikelihood)(h,di) = dl;
390 virtual void recompute_P(std::vector<HYP>& hypotheses,
const data_t& human_data) = 0;
399 virtual std::map<typename HYP::output_t, double>
compute_model_predictions(
const data_t& human_data,
const size_t i,
const Matrix& hposterior)
const = 0;
407 for(
int h=0;h<hposterior.rows();h++) {
408 if(hposterior(h,di) > best_score) {
410 best_score = hposterior(h,di);
413 return std::ref(which_hypotheses->at(best_idx));
423 return log(hd.chance);
446 const auto hlikelihood = (*decayedLikelihood );
447 Matrix hposterior = hlikelihood.colwise() + hprior;
451 #pragma omp parallel for 452 for(
int di=0;di<hposterior.cols();di++) {
455 const Vector& v = hposterior.col(di);
462 hposterior.col(di) = lv;
477 if(which_data != std::addressof(human_data)) {
478 CERR "*** You are computing likelihood on a dataset that the BaseGrammarHypothesis was not constructed with." ENDL 479 CERR " You must call set_hypotheses_and_data before calling this likelihood, but note that when you" ENDL 480 CERR " do that, it will need to recompute everything (which might take a while)." ENDL;
489 if constexpr(std::is_same<std::vector<std::pair<typename HYP::output_t,size_t>>,
typename datum_t::response_t>::value) {
497 const auto log_1malpha = log(1.0-
get_alpha());
499 #pragma omp parallel for 500 for(
size_t i=0;i<human_data.size();i++) {
506 auto& di = human_data[i];
507 for(
const auto& [r,cnt] : di.responses) {
509 log_alpha + log(
get(model_predictions, r, 0.0)));
519 assert(
false &&
"*** If you use BaseGrammarHypothesis with non-default types, you need to overwrite compute_likelihood so it does the right thing.");
524 [[nodiscard]]
virtual this_t
restart()
const override {
525 this_t out(*static_cast<const this_t*>(
this));
529 out.set_alpha(alpha.
restart());
530 out.set_decay(decay.
restart());
545 [[nodiscard]]
virtual std::optional<std::pair<this_t,double>>
propose()
const override {
550 this_t out(*static_cast<const this_t*>(
this));
552 if(flat_prior or
flip(0.15)){
560 auto [ v, fb ] = p.value();
568 auto [ v, fb ] = p.value();
573 return std::make_pair(out, myfb);
578 auto [ v, fb ] = p.value();
580 return std::make_pair(out, fb);
592 return Vector::Zero(C->rows());
605 return (*C) * (-logA.
value);
652 return (C == h.C and LL == h.LL and P == h.P) and
654 (alpha == h.alpha) and
664 virtual std::string
string(std::string prefix=
"")
const override {
667 std::string out =
"";
670 out += prefix +
"-1\tposterior.score" +
"\t"+
str(this->
posterior) +
"\n";
671 out += prefix +
"-1\tparameter.prior" +
"\t"+
str(this->
prior) +
"\n";
672 out += prefix +
"-1\thuman.likelihood" +
"\t"+
str(this->
likelihood) +
"\n";
673 out += prefix +
"-1\talpha" +
"\t"+
str(
get_alpha()) +
"\n";
676 out += prefix +
"-1\tdecay" +
"\t"+
str(
get_decay()) +
"\n";
680 for(
auto& r : *grammar) {
682 std::string rs = r.format;
683 rs = std::regex_replace(rs, std::regex(
"\\%s"),
"X");
684 out += prefix +
str(r.nt) +
"\t" +
QQ(rs) +
"\t" +
str(flat_prior ? 0.0 :
logA(xi)) +
"\n";
688 out.erase(out.size()-1,1);
697 virtual void show(std::string prefix=
"")
override {
698 print(
string(prefix));
701 virtual size_t hash()
const override {
702 size_t output = logA.
hash();
703 hash_combine(output, alpha.
hash(), decay.
hash());
std::vector< bool > random_nonempty_subset(const size_t n, const double p)
Returns a random nonempty subset of n elements, as a vector<bool> of length n with trues for elements...
Definition: Random.h:220
virtual double compute_prior() override
Definition: VectorHalfNormalHypothesis.h:65
std::shared_ptr< LL_t > LL
Definition: BaseGrammarHypothesis.h:90
virtual const HYP & computeMAP(const size_t di, const Matrix &hposterior) const
Definition: BaseGrammarHypothesis.h:402
std::string QQ(const std::string &x)
Definition: Strings.h:190
virtual Matrix compute_normalized_posterior() const
This returns a matrix hposterior[h,di] giving the posterior on the h'th element. NOTE: not output is ...
Definition: BaseGrammarHypothesis.h:440
double likelihood
Definition: Bayesable.h:43
float get_untransformed()
Definition: TNormalVariable.h:45
std::shared_ptr< Matrix > decayedLikelihood
Definition: BaseGrammarHypothesis.h:96
virtual void recompute_decayedLikelihood(const data_t &human_data)
Recomputes the decayed likelihood (e.g. at the given decay level, the total ll for each data point...
Definition: BaseGrammarHypothesis.h:343
virtual void recompute_LL(std::vector< HYP > &hypotheses, const data_t &human_data)
Recompute LL[h,di] a hypothesis from each hypothesis and data point to a vector of prior responses...
Definition: BaseGrammarHypothesis.h:271
virtual std::optional< std::pair< this_t, double > > propose() const override
Propose to the hypothesis. The sometimes does grammar parameters and sometimes other parameters...
Definition: BaseGrammarHypothesis.h:545
A little trick here to force bools to act like chars and have normal std::vector iterators etc...
virtual void recompute_P(std::vector< HYP > &hypotheses, const data_t &human_data)=0
Recompute the predictions for the hypotheses and data.
void copy_parameters(const BaseGrammarHypothesis &h)
Definition: BaseGrammarHypothesis.h:144
Definition: MCMCable.h:14
virtual void set_hypotheses_and_data(std::vector< HYP > &hypotheses, const data_t &human_data)
This is the primary function for setting hypothese and data on construction.
Definition: BaseGrammarHypothesis.h:172
virtual double compute_likelihood(const data_t &human_data, const double breakout=-infinity) override
This computes the likelihood of the human data.
Definition: BaseGrammarHypothesis.h:474
virtual std::string string(std::string prefix="") const override
This returns a string for this hypothesis. Defaulty, now, just in tidy format with all the parameters...
Definition: BaseGrammarHypothesis.h:664
ExponentialVariable decay
Definition: BaseGrammarHypothesis.h:79
virtual self_t restart() const override
Definition: VectorHalfNormalHypothesis.h:107
virtual void show(std::string prefix="") override
Need to override print since it will print in a different format.
Definition: BaseGrammarHypothesis.h:697
void set_alpha(const UniformVariable &a)
Definition: BaseGrammarHypothesis.h:131
size_t ndata() const
Definition: BaseGrammarHypothesis.h:158
virtual size_t hash() const override
Definition: BaseGrammarHypothesis.h:701
Half-normal hypothese are bounded at zero, normal proposals wrap around.
VectorHalfNormalHypothesis logA
Definition: BaseGrammarHypothesis.h:73
virtual void set_can_propose(size_t i, bool b)
Set whether I can propose to a value in logA – this is handled by VectorNormalHypothesis Here...
Definition: BaseGrammarHypothesis.h:208
Definition: Serializable.h:4
void set_can_propose(size_t i, bool b)
Set whether we can propose to each element of b or not.
Definition: VectorHalfNormalHypothesis.h:46
Eigen::MatrixXf Matrix
Definition: EigenLib.h:18
float get_alpha() const
Definition: BaseGrammarHypothesis.h:155
double prior
Definition: Bayesable.h:42
virtual double human_chance_lp(const typename datum_t::output_t &r, const datum_t &hd) const
Get the chance probability of response r in hd (i.e. of a human response). This may typically be pret...
Definition: BaseGrammarHypothesis.h:422
bool flip(float p=0.5)
Definition: Random.h:25
Definition: TNormalVariable.h:17
std::string str(BindingTree *t)
Definition: BindingTree.h:195
double posterior
Definition: Bayesable.h:44
Definition: BaseGrammarHypothesis.h:48
virtual bool operator==(const this_t &h) const override
Definition: BaseGrammarHypothesis.h:651
void set_untransformed(const T v)
Definition: TNormalVariable.h:38
virtual size_t nhypotheses() const
A convenient function that uses C to say how many hypotheses.
Definition: BaseGrammarHypothesis.h:228
we don't need inputs/outputs for out MyHypothesis
Definition: MyHypothesis.h:6
volatile sig_atomic_t CTRL_C
T logplusexp_full(const T a, const T b)
logsumexp with no shortcuts for precision
Definition: Numerics.h:163
virtual void recompute_C(const std::vector< HYP > &hypotheses)
Computes our matrix C[h,r] of hypotheses (rows) by counts of each grammar rule. (requires that each h...
Definition: BaseGrammarHypothesis.h:235
static this_t deserialize(const std::string &s)
Definition: BaseGrammarHypothesis.h:708
void print(FIRST f, ARGS... args)
Lock output_lock and print to std:cout.
Definition: IO.h:53
virtual std::optional< std::pair< self_t, double > > propose() const override
Definition: VectorHalfNormalHypothesis.h:82
constexpr double infinity
Definition: Numerics.h:20
void set_alpha_untransformed(double v)
Definition: BaseGrammarHypothesis.h:137
A TNormalVariable encapsulates MCMC operations on a single real number with a standard normal prior...
Definition: HumanDatum.h:19
virtual std::map< typename HYP::output_t, double > compute_model_predictions(const data_t &human_data, const size_t i, const Matrix &hposterior) const =0
This uses hposterior (computed via this->compute_normalized_posterior()) to compute the model predict...
std::shared_ptr< Matrix > C
Definition: BaseGrammarHypothesis.h:89
virtual self_t restart() const override
Definition: TNormalVariable.h:76
virtual double compute_prior() override
Definition: TNormalVariable.h:56
#define CERR
Definition: IO.h:23
Args... datum_t
Definition: Bayesable.h:38
std::vector< HYP > * which_hypotheses
Definition: BaseGrammarHypothesis.h:100
std::shared_ptr< Predict_t > P
Definition: BaseGrammarHypothesis.h:92
virtual std::optional< std::pair< self_t, double > > propose() const override
Definition: TNormalVariable.h:67
Just a little wrapper to allow vectors to be handled as 2D arrays, which simplifie some stuff in Gram...
Definition: Vector2D.h:14
BaseGrammarHypothesis()
Definition: BaseGrammarHypothesis.h:103
virtual Vector hypothesis_prior() const
Compute a vector of the prior (one for each hypothesis) using the given counts matrix (hypotheses x r...
Definition: BaseGrammarHypothesis.h:589
#define ENDL
Definition: IO.h:21
A LOTHypothesis is the basic unit for doing LOT models. It store a Node as its value, and handles all of the proposing and computing priors, likelihoods, etc. It compiles this Node into a "program" which is used to make function calls, which means that the value should only be changed via LOTHypothesis::set_value.
virtual size_t hash() const override
Definition: VectorHalfNormalHypothesis.h:117
This stores a distribution from values of T to log probabilities. It is used as the return value from...
bool flat_prior
Definition: BaseGrammarHypothesis.h:70
const data_t * which_data
Definition: BaseGrammarHypothesis.h:99
float get_decay() const
Definition: BaseGrammarHypothesis.h:156
std::vector< Args... > data_t
Definition: Bayesable.h:39
virtual this_t restart() const override
Definition: BaseGrammarHypothesis.h:524
void set_decay_untransformed(double v)
Definition: BaseGrammarHypothesis.h:124
std::unordered_map< typename MyHumanDatum ::std::vector< MyHumanDatum > *, std::vector< Vector > > LL_t
Definition: BaseGrammarHypothesis.h:61
Distribution on half-normals. Man, it was a pain to try to make this inherit from VectorNormalHypothe...
Vector value
Definition: VectorHalfNormalHypothesis.h:24
std::vector< bool > can_propose
Definition: VectorHalfNormalHypothesis.h:28
UniformVariable alpha
Definition: BaseGrammarHypothesis.h:78
HYP::Grammar_t * grammar
Definition: BaseGrammarHypothesis.h:63
Definition: VectorHalfNormalHypothesis.h:13
static this_t sample(std::vector< HYP > &hypotheses, const data_t *human_data)
Definition: BaseGrammarHypothesis.h:161
void set_decay(const ExponentialVariable &ev)
Definition: BaseGrammarHypothesis.h:117
BaseGrammarHypothesis(std::vector< HYP > &hypotheses, const data_t *human_data)
Definition: BaseGrammarHypothesis.h:108
#define COUT
Definition: IO.h:24
void set_flat_prior(bool fp)
Definition: BaseGrammarHypothesis.h:215
void set_size(size_t n)
Definition: VectorHalfNormalHypothesis.h:56
This represents an MCMC hain on a hypothesis of type HYP. It uses HYP::propose and HYP::compute_poste...
Vector lognormalize(const Vector &v)
Definition: EigenLib.h:35
A human data series contains a list of human data points, some of which may be presented at the same ...
This class has all the information for running MCMC or MCTS in a little package. It defaultly constru...
Eigen::VectorXf Vector
Definition: EigenLib.h:17
virtual std::string serialize() const override
Definition: BaseGrammarHypothesis.h:707
float get() const
Get interfaces to the transformed variable.
Definition: TNormalVariable.h:52
virtual double compute_prior() override
Definition: BaseGrammarHypothesis.h:427
A grammar stores all of the rules associated with any kind of nonterminal and permits us to sample as...
virtual size_t hash() const override
Definition: TNormalVariable.h:87
void set(int i, double v)
Definition: VectorHalfNormalHypothesis.h:38
size_t size() const
Definition: VectorHalfNormalHypothesis.h:61