#ifndef __GUIDING_HPP__
#define __GUIDING_HPP__
#include <vector>
#include "minisat/core/Solver.h"
#undef assert
#include "util.hpp"
extern "C"
{
#include "api-structures.h" // For definition of Sentence
}
#ifndef HAVE_SETPOLARITY_BOOL // setPolarity has lbool argument, not bool
#define setPolarity(v, b) setPolarity(v, toLbool(b))
#endif
using namespace Minisat;
// This class represents different guiding strategies of LinkParser SAT search
class Guiding {
public:
struct SATParameters {
/* Should the variable with the given number be used as a decision
variable during the SAT search? */
bool isDecision;
/* What is the decision priority of the variable with the given number
during the SAT search? */
double priority;
/* What is the preferred polarity of the variable with the given number
during the SAT search? */
double polarity;
};
Guiding(Sentence sent)
: _sent(sent) {
}
virtual ~Guiding() {}
/* Abstract functions that calculate params for each type of variable */
/* string variables */
virtual void setStringParameters (int var, const char* str)
{
bool isDecision = false;
setParameters(var, isDecision, 0.0, 0.0);
}
virtual void setStringParameters (int var, const char* str, double cost) = 0;
/* epsilon variables */
virtual void setEpsilonParameters (int var)
{
bool isDecision = false;
setParameters(var, isDecision, 0.0, 0.0);
}
/* link_cc variables */
virtual void setLinkParameters (int var, int wi, const char* ci, int wj, const char* cj, const char* label) = 0;
virtual void setLinkParameters (int var, int wi, const char* ci, int wj, const char* cj, const char* label,
double cost) = 0;
/* linked_variables */
virtual void setLinkedParameters (int var, int wi, int wj)
{
bool isDecision = false;
setParameters(var, isDecision, 0.0, 0.0);
}
virtual void setLinkedMinMaxParameters (int var, int wi, int wj)
{
bool isDecision = false;
setParameters(var, isDecision, 0.0, 0.0);
}
/* link_cw_variables */
virtual void setLinkCWParameters (int var, int wi, int wj, const char* cj) {
bool isDecision = false;
setParameters(var, isDecision, 0.0, 0.0);
}
/* link_top_cw variables */
virtual void setLinkTopCWParameters (int var, int wi, int wj, const char* cj) {
bool isDecision = false;
setParameters(var, isDecision, 0.0, 0.0);
}
/* link_top_ww variables */
virtual void setLinkTopWWParameters (int var, int wi, int wj) {
bool isDecision = false;
setParameters(var, isDecision, 0.0, 0.0);
}
/* Pass SAT search parameters to the MiniSAT solver */
void passParametersToSolver(Solver* solver) {
for (size_t v = 0; v < _parameters.size(); v++) {
solver->setDecisionVar(v, _parameters[v].isDecision);
if (_parameters[v].isDecision) {
/* The following setActivity() call may significantly damage
* the performance (timeit -r 6 -n 6):
* -30% for en/4.0.fixes.batch.
* -5% for en/4.0.batch.
* ~0% for ru/4.0.fixes.batch (i.e. it doesn't matter).
* It still damages the performance also when producing all the
* linkages (tested with !limit=10000).
* The link cost influences the priority (set_cost()), but the
* produced linkages using it are not according to cost order anyway.
* Most probably it should be removed (its is not supported
* anyway in Minisat >= 2.2). */
//solver->setActivity(v, _parameters[v].priority);
/* TODO: make polarity double instead of boolean*/
solver->setPolarity(v, _parameters[v].polarity > 0.0);
}
}
}
protected:
/* Set the parameters for the given variable to given values */
void setParameters(size_t var, bool isDecision, double priority, double polarity) {
if (var >= _parameters.size())
_parameters.resize(var + 1);
_parameters[var].isDecision = isDecision;
_parameters[var].priority = priority;
_parameters[var].polarity = polarity;
//printf("Set: %zu %s .%g. .%g.\n", var, isDecision ? "true" : "false", priority, polarity);
}
/* Sentence that is being parsed */
Sentence _sent;
/* Parameters for each variable */
std::vector<SATParameters> _parameters;
};
////////////////////////////////////////////////////////////////////////////
class CostDistanceGuiding : public Guiding
{
public:
double cost2priority(double cost) const {
return cost == 0.0 ? 0.0 : ((double)(_sent->length) + cost);
}
CostDistanceGuiding(Sentence sent)
: Guiding(sent) {
}
virtual void setStringParameters(int var, const char* str, double cost)
{
bool isDecision = cost > 0.0;
double priority = cost2priority(cost);
double polarity = 0.0;
setParameters(var, isDecision, priority, polarity);
}
virtual void setLinkParameters(int var, int wi, const char* ci, int wj, const char* cj, const char* label)
{
bool isDecision = true;
double priority = 0.0;
double polarity = 0.0;
setParameters(var, isDecision, priority, polarity);
}
virtual void setLinkParameters(int var, int i, const char* ci, int j, const char* cj, const char* label,
double cost)
{
bool isDecision = true;
double priority = cost2priority(cost);
double polarity = 0.0;
setParameters(var, isDecision, priority, polarity);
}
#if 0
void setThinLinkParameters(int var, int i, int j)
{
bool isDecision = true;
double priority = (double)(j - i);
// XXX this is wrong, isEndingInterpunction is just wrong, and
// must be killed FIXME I think that this is just looking for the
// one single long link from left-wall to right-punctuation.
// seems like a hack, why is such an exception needed???
double polarity = j - i == 1 ? 1.0 : 0.0;
if (i == 0 && j == (int) _sent->length - 2 &&
isEndingInterpunction(_sent->word[j].alternatives[0])) {
polarity = 1.0;
}
if (i == 0 && j == (int) _sent->length - 1 &&
!isEndingInterpunction(_sent->word[j - 1].alternatives[0])) {
polarity = 1.0;
}
setParameters(var, isDecision, priority, polarity);
}
#endif
};
////////////////////////////////////////////////////////////////////////////
class CostDistanceGuidingOnlyLink : public Guiding
{
public:
double cost2priority(int cost) const {
return cost == 0 ? 0.0 : (double)(_sent->length + cost);
}
CostDistanceGuidingOnlyLink(Sentence sent)
: Guiding(sent) {
}
virtual void setStringParameters (int var, const char* str, double cost)
{
bool isDecision = cost > 0.0;
double priority = cost2priority(cost);
double polarity = 0.0;
setParameters(var, isDecision, priority, polarity);
}
virtual void setLinkParameters (int var, int wi, const char* ci, int wj, const char* cj, const char* label)
{
bool isDecision = true;
double priority = _sent->length - (wj - wi);
double polarity = wj - wi <= 3 ? 1.0 : 0.0;;
setParameters(var, isDecision, priority, polarity);
}
virtual void setLinkParameters(int var, int wi, const char* ci, int wj, const char* cj, const char* label,
double cost)
{
bool isDecision = true;
double priority = cost > 0.0 ? cost2priority(cost) : wj - wi;
double polarity = wj - wi <= 3 ? 1.0 : 0.0;
setParameters(var, isDecision, priority, polarity);
}
#if 0
void setThinLinkParameters(int var, int i, int j) {
bool isDecision = false;
setParameters(var, isDecision, 0.0, 0.0);
}
#endif
};
#endif