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

Python interface for more parsing factors #25

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions ad3/Factor.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ class Factor {

void SetAdditionalLogPotentials(
const vector<double> &additional_log_potentials) {
CheckAdditionalLogPotentials(additional_log_potentials);
additional_log_potentials_ = additional_log_potentials;
}

Expand Down Expand Up @@ -218,6 +219,13 @@ class Factor {
&additional_posteriors_last_);
}

// check whether the given potentials are valid and raise an exception
// if they are not
virtual const void CheckAdditionalLogPotentials(
const vector<double> &additional_log_potentials){
return;
}

private:
int id_; // Factor id.

Expand Down
8 changes: 7 additions & 1 deletion ad3_multi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -570,8 +570,11 @@ int LoadGraph(ifstream &file_graph,
vector<vector<int> > index_siblings(length, vector<int>(length+1, -1));
int total = 0;
vector<Sibling*> siblings;
vector<Arc*> arcs;
vector<double> additional_scores;
for (int m = 0; m < length; ++m) {
Arc *arc = new Arc(0, m);
arcs.push_back(arc);
for (int s = m+1; s <= length; ++s) {
// Create a fake sibling.
Sibling *sibling = new Sibling(0, m, s);
Expand All @@ -584,10 +587,13 @@ int LoadGraph(ifstream &file_graph,
}
factor = new FactorHeadAutomaton;
factor_graph->DeclareFactor(factor, binary_variables, true);
static_cast<FactorHeadAutomaton*>(factor)->Initialize(length, siblings);
static_cast<FactorHeadAutomaton*>(factor)->Initialize(arcs, siblings);
for (int r = 0; r < siblings.size(); ++r) {
delete siblings[r];
}
for (int r = 0; r < arcs.size(); ++r) {
delete arcs[r];
}
factor->SetAdditionalLogPotentials(additional_scores);
num_factor_log_potentials += additional_scores.size();
cout << "Read head automaton factor." << endl;
Expand Down
165 changes: 164 additions & 1 deletion examples/cpp/parsing/FactorGrandparentHeadAutomaton.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,23 @@ class Grandparent {
int m_;
};

class Grandsibling {
public:
Grandsibling(int g, int h, int m, int s) : g_(g), h_(h), m_(m), s_(s) {}
~Grandsibling() {}

int grandparent() { return g_; }
int head() { return h_; }
int modifier() { return m_; }
int sibling() { return s_; }

private:
int g_;
int h_;
int m_;
int s_;
};

class FactorGrandparentHeadAutomaton : public GenericFactor {
public:
FactorGrandparentHeadAutomaton () {}
Expand Down Expand Up @@ -80,6 +97,10 @@ class FactorGrandparentHeadAutomaton : public GenericFactor {
for (int j = 0; j < m; ++j) {
int index = index_siblings_[j][m];
double score = values[m-1][j] + additional_log_potentials[index];
if (use_grandsiblings_) {
index = index_grandsiblings_[g][j][m];
if (index >= 0) score += additional_log_potentials[index];
}
if (path[m][m] < 0 || score > values[m][m]) {
values[m][m] = score;
path[m][m] = j;
Expand All @@ -96,6 +117,10 @@ class FactorGrandparentHeadAutomaton : public GenericFactor {
for (int j = 0; j < length; ++j) {
int index = index_siblings_[j][length];
double score = values[length-1][j] + additional_log_potentials[index];
if (use_grandsiblings_) {
index = index_grandsiblings_[g][j][length];
if (index >= 0) score += additional_log_potentials[index];
}
if (best_last_state < 0 || score > best_score) {
best_score = score;
best_last_state = j;
Expand Down Expand Up @@ -149,13 +174,21 @@ class FactorGrandparentHeadAutomaton : public GenericFactor {
*value += variable_log_potentials[num_grandparents+s-1];
int index = index_siblings_[m][s];
*value += additional_log_potentials[index];
if (use_grandsiblings_) {
index = index_grandsiblings_[g][m][s];
if (index >= 0) *value += additional_log_potentials[index];
}
m = s;
index = index_grandparents_[g][m];
*value += additional_log_potentials[index];
}
int s = index_siblings_.size();
int index = index_siblings_[m][s];
*value += additional_log_potentials[index];
if (use_grandsiblings_) {
index = index_grandsiblings_[g][m][s];
if (index >= 0) *value += additional_log_potentials[index];
}
}

// Given a configuration with a probability (weight),
Expand All @@ -176,13 +209,21 @@ class FactorGrandparentHeadAutomaton : public GenericFactor {
(*variable_posteriors)[num_grandparents+s-1] += weight;
int index = index_siblings_[m][s];
(*additional_posteriors)[index] += weight;
if (use_grandsiblings_) {
index = index_grandsiblings_[g][m][s];
if (index >= 0) (*additional_posteriors)[index] += weight;
}
m = s;
index = index_grandparents_[g][m];
(*additional_posteriors)[index] += weight;
}
int s = index_siblings_.size();
int index = index_siblings_[m][s];
(*additional_posteriors)[index] += weight;
if (use_grandsiblings_) {
index = index_grandsiblings_[g][m][s];
if (index >= 0) (*additional_posteriors)[index] += weight;
}
}

// Count how many common values two configurations have.
Expand Down Expand Up @@ -233,9 +274,129 @@ class FactorGrandparentHeadAutomaton : public GenericFactor {
}

public:
// length is relative to the head position.
// Incoming arcs are of the form (g,h) for each g.
// Outgoing arcs are of the form (h,m) for each m.
// The variables linked to this factor must be in the same order as
// the incoming arcs, followed by the outgoing arcs.
// The incoming arcs must be sorted by grandparent, from smallest to
// biggest index.
// The outgoing arcs must be sorted from the closest to the farthest
// away from the root.
// Grandparent parts (g, h, m) must include cases where g = m.
// Factors without incoming arcs must not be created.
void Initialize(const vector<Arc*> &incoming_arcs,
const vector<Arc*> &outgoing_arcs,
const vector<Grandparent*> &grandparents,
const vector<Sibling*> &siblings) {
vector<Grandsibling*> grandsiblings;
Initialize(incoming_arcs, outgoing_arcs, grandparents, siblings,
grandsiblings);
}

void Initialize(const vector<Arc*> &incoming_arcs,
const vector<Arc*> &outgoing_arcs,
const vector<Grandparent*> &grandparents,
const vector<Sibling*> &siblings,
const vector<Grandsibling*> &grandsiblings) {
// length is relative to the head position.
// E.g. for a right automaton with h=3 and instance_length=10,
// length = 7. For a left automaton, it would be length = 3.
use_grandsiblings_ = (grandsiblings.size() > 0);
int num_grandparents = incoming_arcs.size();
length_ = outgoing_arcs.size() + 1;
index_grandparents_.assign(num_grandparents, vector<int>(length_, -1));
index_siblings_.assign(length_, vector<int>(length_ + 1, -1));
if (use_grandsiblings_) {
index_grandsiblings_.assign(num_grandparents,
vector<vector<int> >(length_,
vector<int>(length_ + 1, -1)));
}

// Create a temporary index of modifiers.
int h = (outgoing_arcs.size() > 0) ? outgoing_arcs[0]->head() : -1;
int m = (outgoing_arcs.size() > 0) ? outgoing_arcs[0]->modifier() : -1;
vector<int> index_modifiers(1, 0);
bool right = (h < m) ? true : false;
for (int k = 0; k < outgoing_arcs.size(); ++k) {
int previous_modifier = m;
m = outgoing_arcs[k]->modifier();

int position = right ? m - h : h - m;
index_modifiers.resize(position + 1, -1);
index_modifiers[position] = k + 1;
}

// Construct index of siblings.
for (int k = 0; k < siblings.size(); ++k) {
h = siblings[k]->head();
m = siblings[k]->modifier();
int s = siblings[k]->sibling();
// cout << "sibling " << h << " -> " << m << " -> " << s << endl;
right = (s > h) ? true : false;
int position_modifier = right ? m - h : h - m;
int position_sibling = right ? s - h : h - s;
int index_modifier = index_modifiers[position_modifier];
int index_sibling = (position_sibling < index_modifiers.size()) ?
index_modifiers[position_sibling] : length_;

// Add an offset to save room for the grandparents.
index_siblings_[index_modifier][index_sibling] =
grandparents.size() + k;
}

// Create a temporary index of grandparents.
int g = (incoming_arcs.size() > 0) ? incoming_arcs[0]->head() : -1;
h = (incoming_arcs.size() > 0) ? incoming_arcs[0]->modifier() : -1;
vector<int> index_incoming;
for (int k = 0; k < incoming_arcs.size(); ++k) {
g = incoming_arcs[k]->head();
// Allow for the case where g is -1 (the head being the root
// in this case). To handle this, set the position to g+1.
int position = g + 1;
index_incoming.resize(position + 1, -1);
index_incoming[position] = k;
}

// Construct index of grandparents.
for (int k = 0; k < grandparents.size(); ++k) {
int g = grandparents[k]->grandparent();
h = grandparents[k]->head();
m = grandparents[k]->modifier();
//cout << "grandparent " << g << " -> " << h << " -> " << m << endl;

right = (m > h) ? true : false;
int position_modifier = right ? m - h : h - m;
int position_grandparent = g + 1;
int index_modifier = index_modifiers[position_modifier];
int index_grandparent = index_incoming[position_grandparent];
index_grandparents_[index_grandparent][index_modifier] = k;
}

// Construct index of grandsiblings.
for (int k = 0; k < grandsiblings.size(); ++k) {
int g = grandsiblings[k]->grandparent();
h = grandsiblings[k]->head();
m = grandsiblings[k]->modifier();
int s = grandsiblings[k]->sibling();

right = (s > h) ? true : false;
int position_grandparent = g + 1;
int position_modifier = right ? m - h : h - m;
int position_sibling = right ? s - h : h - s;
int index_grandparent = index_incoming[position_grandparent];
int index_modifier = index_modifiers[position_modifier];
int index_sibling = (position_sibling < index_modifiers.size()) ?
index_modifiers[position_sibling] : length_;

// Add an offset to save room for the grandparents and siblings.
index_grandsiblings_[index_grandparent][index_modifier][index_sibling] =
siblings.size() + grandparents.size() + k;
}
}
// length is relative to the head position.
// E.g. for a right automaton with h=3 and instance_length=10,
// length = 7. For a left automaton, it would be length = 3.
// (DEPRECATED)
void Initialize(int length,
int num_grandparents,
const vector<Sibling*> &siblings,
Expand Down Expand Up @@ -271,9 +432,11 @@ class FactorGrandparentHeadAutomaton : public GenericFactor {
}

private:
bool use_grandsiblings_;
int length_;
vector<vector<int> > index_siblings_;
vector<vector<int> > index_grandparents_;
vector<vector<vector<int> > > index_grandsiblings_;
};

} // namespace AD3
Expand Down
66 changes: 64 additions & 2 deletions examples/cpp/parsing/FactorHeadAutomaton.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#define FACTOR_HEAD_AUTOMATON

#include "ad3/GenericFactor.h"
#include "FactorTree.h"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this import needed? what for?


namespace AD3 {

Expand All @@ -40,7 +41,10 @@ class Sibling {

class FactorHeadAutomaton : public GenericFactor {
public:
FactorHeadAutomaton () {}
FactorHeadAutomaton () {
num_siblings_ = -1;
length_ = -1;
}
virtual ~FactorHeadAutomaton() { ClearActiveSet(); }

// Compute the score of a given assignment.
Expand Down Expand Up @@ -192,9 +196,18 @@ class FactorHeadAutomaton : public GenericFactor {
}

public:
// return the number of arc variables constrained by this factor
// (only should be called after Initialize)
int GetNumVariables(){
return length_ - 1;
}

// length is relative to the head position.
// E.g. for a right automaton with h=3 and instance_length=10,
// length = 7. For a left automaton, it would be length = 3.
// This function assumes that all possible arcs exist; i.e.,
// there was no pruning. If that's not the case, use the Initialize
// that receives a vector of arcs.
void Initialize(int length, const vector<Sibling*> &siblings) {
length_ = length;
index_siblings_.assign(length, vector<int>(length+1, -1));
Expand All @@ -213,8 +226,57 @@ class FactorHeadAutomaton : public GenericFactor {
}
}

// If the arcs are to the left of a head token, they must be sorted by increasing
// modifier indices. If they are to the right, by decreasing indices.
// This function should be used when some arcs were pruned.
void Initialize(const vector<Arc*> &arcs, const vector<Sibling*> &siblings) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we maybe use overloading to keep the old API valid too? To avoid breaking code that relies on this.

Same goes for the python wrapper.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both functions kept for overloading

length_ = arcs.size() + 1;
num_siblings_ = siblings.size();
index_siblings_.assign(length_, vector<int>(length_ + 1, -1));

// in case the given vector of arcs doesn't contain all possible arcs
// (in case some were pruned), map the given ones to a sequence
int h = (arcs.size() > 0) ? arcs[0]->head() : -1;
int m = (arcs.size() > 0) ? arcs[0]->modifier() : -1;
vector<int> index_modifiers(1, 0);
bool right = (h < m) ? true : false;
for (int k = 0; k < arcs.size(); ++k) {
int previous_modifier = m;
m = arcs[k]->modifier();

int position = right ? m - h : h - m;
index_modifiers.resize(position + 1, -1);
index_modifiers[position] = k + 1;
}

for (int k = 0; k < siblings.size(); ++k) {
h = siblings[k]->head();
m = siblings[k]->modifier();
int s = siblings[k]->sibling();
right = (s > h) ? true : false;
int position_modifier = right ? m - h : h - m;
int position_sibling = right ? s - h : h - s;
int index_modifier = index_modifiers[position_modifier];
int index_sibling = (position_sibling < index_modifiers.size()) ?
index_modifiers[position_sibling] : length_;
index_siblings_[index_modifier][index_sibling] = k;
}
}

virtual const void CheckAdditionalLogPotentials
(const vector<double> &additional_log_potentials){
// the number of additional potentials should be equal to the number of
// sibling parts
if(num_siblings_ == -1){
throw logic_error("Factor not initialized");
}else if(additional_log_potentials.size() != num_siblings_){
throw invalid_argument("Number of additional potentials different from the number of siblings");
}
}

private:
int length_;
int length_; // number of arc parts in the factor + 1
int num_siblings_; // number of sibling parts in the factor
vector<vector<int> > index_siblings_;
};

Expand Down
Loading