blob: 0ab4c547ce62e4c802c37df36d024ea7627d0b07 [file] [log] [blame]
/*
EGYPT Toolkit for Statistical Machine Translation
Written by Yaser Al-Onaizan, Jan Curin, Michael Jahr, Kevin Knight, John Lafferty, Dan Melamed, David Purdy, Franz Och, Noah Smith, and David Yarowsky.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.
*/
/*--
transpair_model3: representation of a translation pair for model3 training
allowing for fast access (esp. to t table).
Franz Josef Och (30/07/99)
--*/
#include "transpair_model3.h"
#include <algorithm>
transpair_model3::transpair_model3(const Vector<WordIndex>&es, const Vector<WordIndex>&fs, tmodel<COUNT, PROB>&tTable, amodel<PROB>&aTable, amodel<PROB>&dTable, nmodel<PROB>&nTable, double _p1, double _p0, void*)
: transpair_model2(es,fs,tTable,aTable),d(es.size(), fs.size()),n(es.size(), MAX_FERTILITY+1), p0(_p0), p1(_p1)
{
WordIndex l=es.size()-1,m=fs.size()-1;
for(WordIndex i=0;i<=l;i++)
{
for(WordIndex j=1;j<=m;j++)
d(i, j)=dTable.getValue(j, i, l, m);
if( i>0 )
{
for(WordIndex f=0;f<MAX_FERTILITY;f++)
n(i, f)=nTable.getValue(es[i], f);
n(i,MAX_FERTILITY)=PROB_SMOOTH;
}
}
}
LogProb transpair_model3::scoreOfMove(const alignment&a, WordIndex new_i, WordIndex j, double,bool forModel3)const
{
LogProb change;
const WordIndex old_i=a(j);
WordIndex f0=a.fert(0);
if (old_i == new_i)
change=1.0;
else if (old_i == 0)
change=((double)p0*p0/p1) *
(( (DeficientDistortionForEmptyWord?(max(2,int(m))/DeficientDistortionForEmptyWord):f0)*(m-f0+1.0)) / ((m-2*f0+1)*(m-2*f0+2.0))) *
((PROB)(forModel3?(a.fert(new_i)+1.0):1.0)) *
(get_fertility(new_i, a.fert(new_i)+1) / get_fertility(new_i, a.fert(new_i)))*
(t(new_i, j)/t(old_i, j))*
(forModel3?d(new_i, j):1.0);
else if (new_i == 0)
change=(double(p1) / (p0*p0)) *
(double((m-2*f0)*(m-2*f0-1))/( (DeficientDistortionForEmptyWord?(max(2,int(m))/DeficientDistortionForEmptyWord):(1+f0))*(m-f0))) *
(forModel3?(1.0/a.fert(old_i)):1.0) *
(get_fertility(old_i, a.fert(old_i)-1) /get_fertility(old_i, a.fert(old_i)))*
(t(new_i, j) /t(old_i, j)) *
(forModel3?(1.0 / d(old_i, j)):1.0);
else
change=(forModel3?((a.fert(new_i)+1.0)/a.fert(old_i)):1.0) *
(get_fertility(old_i,a.fert(old_i)-1) / get_fertility(old_i,a.fert(old_i))) *
(get_fertility(new_i,a.fert(new_i)+1) /get_fertility(new_i,a.fert(new_i))) *
(t(new_i,j)/t(old_i,j)) *
(forModel3?(d(new_i,j)/d(old_i,j)):1.0);
return change;
}
LogProb transpair_model3::scoreOfSwap(const alignment&a, WordIndex j1, WordIndex j2, double,bool forModel3)const
{
PROB score=1;
assert(j1<j2);
WordIndex i1=a(j1), i2=a(j2);
if (i1!=i2)
{
score=(t(i2, j1)/t(i1, j1))*(t(i1, j2)/t(i2, j2));
if( forModel3 )
{
if (i1)
score *= d(i1, j2)/d(i1, j1);
if (i2)
score *= d(i2, j1)/d(i2, j2);
}
}
return score;
}
ostream&operator<<(ostream&out, const transpair_model3&m)
{
for(WordIndex i=0;i<=m.get_l();i++)
{
out << "EF-I:"<<i<<' ';
for(WordIndex j=1;j<=m.get_m();j++)
out << "("<<m.t(i,j)<<","<<m.d(i,j)<<")";
for(WordIndex j=1;j<MAX_FERTILITY;j++)
if( i>0 )
out << "(fert:"<<m.get_fertility(i,j)<<")";
out << '\n';
}
out << "T:" << m.t << "D:" << m.d << "A:" << m.a << "N:" << m.n << m.p0 << m.p1 << '\n';
return out;
}
LogProb transpair_model3::_scoreOfMove(const alignment&a, WordIndex new_i, WordIndex j,double)const
{
alignment b(a);
b.set(j, new_i);
LogProb a_prob=prob_of_target_and_alignment_given_source(a);
LogProb b_prob=prob_of_target_and_alignment_given_source(b);
if( a_prob )
return b_prob/a_prob;
else if( b_prob )
return 1e20;
else
return 1.0;
}
LogProb transpair_model3::_scoreOfSwap(const alignment&a, WordIndex j1, WordIndex j2,double thisValue)const
{
alignment b(a);
b.set(j1, a(j2));
b.set(j2, a(j1));
LogProb a_prob=thisValue;
if( a_prob<0.0 )
a_prob=prob_of_target_and_alignment_given_source(a);
massert(a_prob==prob_of_target_and_alignment_given_source(a));
LogProb b_prob=prob_of_target_and_alignment_given_source(b);
if( a_prob )
return b_prob/a_prob;
else if( b_prob )
return 1e20;
else
return 1.0;
}
LogProb transpair_model3::prob_of_target_and_alignment_given_source(const alignment&al,bool verb)const
{
LogProb total = 1.0 ;
static const LogProb zero = 1E-299 ;
total *= pow(double(1-p1), m-2.0 * al.fert(0)) * pow(double(p1), double(al.fert(0)));
if( verb) cerr << "IBM-3: (1-p1)^(m-2 f0)*p1^f0: " << total << '\n';
for (WordIndex i = 1 ; i <= al.fert(0) ; i++)
total *= double(m - al.fert(0) - i + 1) / (double(DeficientDistortionForEmptyWord?(max(2,int(m))/DeficientDistortionForEmptyWord):i)) ;
if( verb) cerr << "IBM-3: +NULL:binomial+distortion " << total << '\n';
for (WordIndex i = 1 ; i <= l ; i++)
{
total *= get_fertility(i, al.fert(i)) * (LogProb) factorial(al.fert(i));
if( verb) cerr << "IBM-3: fertility of " << i << " with factorial " << get_fertility(i, al.fert(i)) * (LogProb) factorial(al.fert(i)) << " -> " << total << '\n';
}
for (WordIndex j = 1 ; j <= m ; j++)
{
total*= get_t(al(j), j) ;
massert( get_t(al(j), j)>=PROB_SMOOTH );
if( verb) cerr << "IBM-3: t of " << j << " " << al(j) << ": " << get_t(al(j), j) << " -> " << total << '\n';
if (al(j))
{
total *= get_d(al(j), j);
if( verb) cerr << "IBM-3: d of " << j << ": " << get_d(al(j), j) << " -> " << total << '\n';
}
}
return total?total:zero;
}
void transpair_model3::computeScores(const alignment&al,vector<double>&d)const
{
LogProb total1 = 1.0,total2=1.0,total3=1.0,total4=1.0 ;
total1 *= pow(double(1-p1), m-2.0 * al.fert(0)) * pow(double(p1), double(al.fert(0)));
for (WordIndex i = 1 ; i <= al.fert(0) ; i++)
total1 *= double(m - al.fert(0) - i + 1) / (double(DeficientDistortionForEmptyWord?(max(2,int(m))/DeficientDistortionForEmptyWord):i)) ;
for (WordIndex i = 1 ; i <= l ; i++)
{
total2 *= get_fertility(i, al.fert(i)) * (LogProb) factorial(al.fert(i));
}
for (WordIndex j = 1 ; j <= m ; j++)
{
total3*= get_t(al(j), j) ;
massert( get_t(al(j), j)>=PROB_SMOOTH );
if (al(j))
{
total4 *= get_d(al(j), j);
}
}
d.push_back(total1);//5
d.push_back(total2);//6
d.push_back(total3);//7
d.push_back(total4);//8
}