/// <summary>
/// Call relax() for each arc going out of the given node.
/// </summary>
public void Traverse(int n1, int n2, float cost, int trail_index)
{
//logger.format("traversing %d %d", n1, n2);
Intarray o1 = fst1.Outputs(n1);
Intarray i1 = fst1.Inputs(n1);
Intarray t1 = fst1.Targets(n1);
Floatarray c1 = fst1.Costs(n1);
Intarray o2 = fst2.Outputs(n2);
Intarray i2 = fst2.Inputs(n2);
Intarray t2 = fst2.Targets(n2);
Floatarray c2 = fst2.Costs(n2);
// for optimization
int[] O1 = o1.data;
int[] O2 = o2.data;
int[] I1 = i1.data;
int[] I2 = i2.data;
int[] T1 = t1.data;
int[] T2 = t2.data;
float[] C1 = c1.data;
float[] C2 = c2.data;
// Relax outbound arcs in the composition
int k1, k2;
// relaxing fst1 RHO moves
// these can be rho->rho or x->rho moves
for (k1 = 0; k1 < o1.Length() && O1[k1] == FstUtil.L_RHO; k1++)
{
for (int j = 0; j < o2.Length(); j++)
{
if (I2[j] <= FstUtil.L_EPSILON)
{
continue;
}
// if it's rho->rho, then pick up the label,
// if it's x->rho leave it alone
int inn = I1[k1] == FstUtil.L_RHO ? I2[j] : I1[k1];
Relax(n1, n2, // from pair
T1[k1], T2[j], // to pair
C1[k1] + C2[j], // cost
k1, j, // arc ids
inn, I2[j], O2[j], // input, intermediate, output
cost, trail_index);
}
}
// relaxing fst2 RHO moves
// these can be rho->rho or rho->x moves
for (k2 = 0; k2 < o2.Length() && I2[k2] == FstUtil.L_RHO; k2++)
{
for (int j = 0; j < o1.Length(); j++)
{
if (O1[j] <= FstUtil.L_EPSILON)
{
continue;
}
// if it's rho->rho, then pick up the label,
// if it's rho->x leave it alone
int outn = O2[k2] == FstUtil.L_RHO ? O1[j] : O2[k2];
Relax(n1, n2, // from pair
T1[j], T2[k2], // to pair
C1[j] + C2[k2], // cost
j, k2, // arc ids
I1[j], O1[j], outn, // input, intermediate, output
cost, trail_index);
}
}
// relaxing fst1 EPSILON moves
for (k1 = 0; k1 < o1.Length() && O1[k1] == FstUtil.L_EPSILON; k1++)
{
Relax(n1, n2, // from pair
T1[k1], n2, // to pair
C1[k1], // cost
k1, -1, // arc ids
I1[k1], 0, 0, // input, intermediate, output
cost, trail_index);
}
// relaxing fst2 EPSILON moves
for (k2 = 0; k2 < o2.Length() && I2[k2] == FstUtil.L_EPSILON; k2++)
{
Relax(n1, n2, // from pair
n1, T2[k2], // to pair
C2[k2], // cost
-1, k2, // arc ids
0, 0, O2[k2], // input, intermediate, output
cost, trail_index);
}
// relaxing non-epsilon moves
while (k1 < o1.Length() && k2 < i2.Length())
{
while (k1 < o1.Length() && O1[k1] < I2[k2])
{
k1++;
}
if (k1 >= o1.Length())
{
break;
}
while (k2 < i2.Length() && O1[k1] > I2[k2])
{
k2++;
}
while (k1 < o1.Length() && k2 < i2.Length() && O1[k1] == I2[k2])
{
for (int j = k2; j < i2.Length() && O1[k1] == I2[j]; j++)
{
Relax(n1, n2, // from pair
T1[k1], T2[j], // to pair
C1[k1] + C2[j], // cost
k1, j, // arc ids
I1[k1], O1[k1], O2[j], // input, intermediate, output
cost, trail_index);
}
k1++;
}
}
}