// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Copyright 2005-2010 Google, Inc.
// Author: jpr@google.com (Jake Ratkiewicz)
#ifndef FST_SCRIPT_SHORTEST_PATH_H_
#define FST_SCRIPT_SHORTEST_PATH_H_
#include <vector>
using std::vector;
#include <fst/script/arg-packs.h>
#include <fst/script/fst-class.h>
#include <fst/script/weight-class.h>
#include <fst/shortest-path.h>
#include <fst/script/shortest-distance.h> // for ShortestDistanceOptions
namespace fst {
namespace script {
struct ShortestPathOptions
: public fst::script::ShortestDistanceOptions {
const size_t nshortest;
const bool unique;
const bool has_distance;
const bool first_path;
const WeightClass weight_threshold;
const int64 state_threshold;
ShortestPathOptions(QueueType qt, size_t n = 1,
bool u = false, bool hasdist = false,
float d = fst::kDelta, bool fp = false,
WeightClass w = fst::script::WeightClass::Zero(),
int64 s = fst::kNoStateId)
: ShortestDistanceOptions(qt, ANY_ARC_FILTER, kNoStateId, d),
nshortest(n), unique(u), has_distance(hasdist), first_path(fp),
weight_threshold(w), state_threshold(s) { }
};
typedef args::Package<const FstClass &, MutableFstClass *,
vector<WeightClass> *, const ShortestPathOptions &>
ShortestPathArgs1;
template<class Arc>
void ShortestPath(ShortestPathArgs1 *args) {
const Fst<Arc> &ifst = *(args->arg1.GetFst<Arc>());
MutableFst<Arc> *ofst = args->arg2->GetMutableFst<Arc>();
const ShortestPathOptions &opts = args->arg4;
typedef typename Arc::StateId StateId;
typedef typename Arc::Weight Weight;
typedef AnyArcFilter<Arc> ArcFilter;
vector<typename Arc::Weight> weights;
typename Arc::Weight weight_threshold =
*(opts.weight_threshold.GetWeight<Weight>());
switch (opts.queue_type) {
case AUTO_QUEUE: {
typedef AutoQueue<StateId> Queue;
Queue *queue = QueueConstructor<Queue, Arc,
ArcFilter>::Construct(ifst, &weights);
fst::ShortestPathOptions<Arc, Queue, ArcFilter> spopts(
queue, ArcFilter(), opts.nshortest, opts.unique,
opts.has_distance, opts.delta, opts.first_path,
weight_threshold, opts.state_threshold);
ShortestPath(ifst, ofst, &weights, spopts);
delete queue;
return;
}
case FIFO_QUEUE: {
typedef FifoQueue<StateId> Queue;
Queue *queue = QueueConstructor<Queue, Arc,
ArcFilter>::Construct(ifst, &weights);
fst::ShortestPathOptions<Arc, Queue, ArcFilter> spopts(
queue, ArcFilter(), opts.nshortest, opts.unique,
opts.has_distance, opts.delta, opts.first_path,
weight_threshold, opts.state_threshold);
ShortestPath(ifst, ofst, &weights, spopts);
delete queue;
return;
}
case LIFO_QUEUE: {
typedef LifoQueue<StateId> Queue;
Queue *queue = QueueConstructor<Queue, Arc,
ArcFilter >::Construct(ifst, &weights);
fst::ShortestPathOptions<Arc, Queue, ArcFilter> spopts(
queue, ArcFilter(), opts.nshortest, opts.unique,
opts.has_distance, opts.delta, opts.first_path,
weight_threshold, opts.state_threshold);
ShortestPath(ifst, ofst, &weights, spopts);
delete queue;
return;
}
case SHORTEST_FIRST_QUEUE: {
typedef NaturalShortestFirstQueue<StateId, Weight> Queue;
Queue *queue = QueueConstructor<Queue, Arc,
ArcFilter>::Construct(ifst, &weights);
fst::ShortestPathOptions<Arc, Queue, ArcFilter> spopts(
queue, ArcFilter(), opts.nshortest, opts.unique,
opts.has_distance, opts.delta, opts.first_path,
weight_threshold, opts.state_threshold);
ShortestPath(ifst, ofst, &weights, spopts);
delete queue;
return;
}
case STATE_ORDER_QUEUE: {
typedef StateOrderQueue<StateId> Queue;
Queue *queue = QueueConstructor<Queue, Arc,
ArcFilter>::Construct(ifst, &weights);
fst::ShortestPathOptions<Arc, Queue, ArcFilter> spopts(
queue, ArcFilter(), opts.nshortest, opts.unique,
opts.has_distance, opts.delta, opts.first_path,
weight_threshold, opts.state_threshold);
ShortestPath(ifst, ofst, &weights, spopts);
delete queue;
return;
}
case TOP_ORDER_QUEUE: {
typedef TopOrderQueue<StateId> Queue;
Queue *queue = QueueConstructor<Queue, Arc,
ArcFilter>::Construct(ifst, &weights);
fst::ShortestPathOptions<Arc, Queue, ArcFilter> spopts(
queue, ArcFilter(), opts.nshortest, opts.unique,
opts.has_distance, opts.delta, opts.first_path,
weight_threshold, opts.state_threshold);
ShortestPath(ifst, ofst, &weights, spopts);
delete queue;
return;
}
default:
FSTERROR() << "Unknown queue type: " << opts.queue_type;
ofst->SetProperties(kError, kError);
}
// Copy the weights back
args->arg3->resize(weights.size());
for (unsigned i = 0; i < weights.size(); ++i) {
(*args->arg3)[i] = WeightClass(weights[i]);
}
}
// 2
typedef args::Package<const FstClass &, MutableFstClass *,
size_t, bool, bool, WeightClass,
int64> ShortestPathArgs2;
template<class Arc>
void ShortestPath(ShortestPathArgs2 *args) {
const Fst<Arc> &ifst = *(args->arg1.GetFst<Arc>());
MutableFst<Arc> *ofst = args->arg2->GetMutableFst<Arc>();
typename Arc::Weight weight_threshold =
*(args->arg6.GetWeight<typename Arc::Weight>());
ShortestPath(ifst, ofst, args->arg3, args->arg4, args->arg5,
weight_threshold, args->arg7);
}
// 1
void ShortestPath(const FstClass &ifst, MutableFstClass *ofst,
vector<WeightClass> *distance,
const ShortestPathOptions &opts);
// 2
void ShortestPath(const FstClass &ifst, MutableFstClass *ofst,
size_t n = 1, bool unique = false,
bool first_path = false,
WeightClass weight_threshold =
fst::script::WeightClass::Zero(),
int64 state_threshold = fst::kNoStateId);
} // namespace script
} // namespace fst
#endif // FST_SCRIPT_SHORTEST_PATH_H_