prose-js
Version:
Natural language-to-pseudocode compiler.
258 lines (243 loc) • 6.93 kB
JavaScript
/**
* Classifier module.
* @exports Classifier
*/
var StringUtils = require('./string-utils');
function Classifier() {
var _self = this;
var wordDistanceTolerance = 0;
var minimumClassificationValue = 0.21; // 42 is indeed the answer for everything.
var documents = [
{
docs: [
'es igual a',
'es igual a',
'es igual a',
'es igual a',
'es igual a',
'es igual que',
'es igual que',
'es igual que',
'es igual que',
'es igual que'
// 'si q es igual a q',
// 'si qq es igual a qq',
// 'si qqq es igual a qqq',
// 'si qqqq es igual a qqqq',
// 'si qqqqq es igual a qqqqq',
// 'si q es igual que q',
// 'si qq es igual que qq',
// 'si qqq es igual que qqq',
// 'si qqqq es igual que qqqq',
// 'se tiene que x es igual a x',
// 'se tiene que x es igual que x',
// 'se sabe que x es igual a x',
// 'se sabe que x es igual que x'
],
meaning: '='
},
{
docs: [
'es mayor o igual a',
'es mayor o igual a',
'es mayor o igual a',
'es mayor o igual a',
'es mayor o igual a',
'es mayor o igual que',
'es mayor o igual que',
'es mayor o igual que',
'es mayor o igual que',
'es mayor o igual que'
// 'si q es mayor o igual a q',
// 'si qq es mayor o igual a qq',
// 'si qqq es mayor o igual a qqq',
// 'si qqqq es mayor o igual a qqqq',
// 'si qqqqq es mayor o igual a qqqqq',
// 'si q es mayor o igual que q',
// 'si qq es mayor o igual que qq',
// 'si qqq es mayor o igual que qqq',
// 'si qqqq es mayor o igual que qqqq',
// 'se tiene que x es mayor o igual a x',
// 'se tiene que x es mayor o igual que x',
// 'se sabe que x es mayor o igual a x',
// 'se sabe que x es mayor o igual que x'
],
meaning: '>='
},
{
docs: [
'es menor o igual a',
'es menor o igual a',
'es menor o igual a',
'es menor o igual a',
'es menor o igual a',
'es menor o igual que',
'es menor o igual que',
'es menor o igual que',
'es menor o igual que',
'es menor o igual que'
// 'si q es menor o igual a q',
// 'si qq es menor o igual a qq',
// 'si qqq es menor o igual a qqq',
// 'si qqqq es menor o igual a qqqq',
// 'si qqqqq es menor o igual a qqqqq',
// 'si q es menor o igual que q',
// 'si qq es menor o igual que qq',
// 'si qqq es menor o igual que qqq',
// 'si qqqq es menor o igual que qqqq',
// 'se tiene que x es menor o igual a x',
// 'se tiene que x es menor o igual que x',
// 'se sabe que x es menor o igual a x',
// 'se sabe que x es menor o igual que x'
],
meaning: '<='
},
{
docs: [
'es mayor a',
'es mayor a',
'es mayor a',
'es mayor a',
'es mayor a',
'es mayor que',
'es mayor que',
'es mayor que',
'es mayor que',
'es mayor que'
// 'si q es mayor a q',
// 'si qq es mayor a qq',
// 'si qqq es mayor a qqq',
// 'si qqqq es mayor a qqqq',
// 'si qqqqq es mayor a qqqqq',
// 'si q es mayor que q',
// 'si qq es mayor que qq',
// 'si qqq es mayor que qqq',
// 'si qqqq es mayor que qqqq',
// 'se tiene que x es mayor a x',
// 'se tiene que x es mayor que x',
// 'se sabe que x es mayor a x',
// 'se sabe que x es mayor que x'
],
meaning: '>'
},
{
docs: [
'es menor a',
'es menor a',
'es menor a',
'es menor a',
'es menor a',
'es menor que',
'es menor que',
'es menor que',
'es menor que',
'es menor que'
// 'si q es menor a q',
// 'si qq es menor a qq',
// 'si qqq es menor a qqq',
// 'si qqqq es menor a qqqq',
// 'si qqqqq es menor a qqqqq',
// 'si q es menor que q',
// 'si qq es menor que qq',
// 'si qqq es menor que qqq',
// 'si qqqq es menor que qqqq',
// 'se tiene que x es menor a x',
// 'se tiene que x es menor que x',
// 'se sabe que x es menor a x',
// 'se sabe que x es menor que x'
],
meaning: '<'
}
];
var stringUtils = new StringUtils();
var classifier = stringUtils.getClassifier();
var tagger = stringUtils.getTagger();
for (var i = 0; i < documents.length; i++) {
for (var j = 0; j < documents[i].docs.length; j++) {
classifier.addDocument(documents[i].docs[j], documents[i].meaning);
}
}
classifier.train();
/*
* Returns the text with matching expressions replaced
* by relevant equivalents after proper classification
*
* @private
* @param {string} text - Text to classify.
*/
this.classify = function(text) {
for (var i = 0; i < documents.length; i++) {
var strings = stringUtils.split(text);
var tags = tag(strings);
for (var j = 0; j < documents[i].docs.length; j++) {
text = classifyExpression(strings, tags, documents[i].docs[j], documents[i].meaning);
strings = stringUtils.split(text);
tags = tag(strings);
}
}
return text.replace(/\ +/g, ' ');
}
function classifyExpression(strings, tags, expression, meaning) {
var expressionTags = tag(stringUtils.split(expression));
if (expressionTags.length <= tags.length) {
for (var i = 0; i < tags.length - expressionTags.length; i++) {
if (tags[i] == expressionTags[0]) {
var isBroken = false;
for (var k = i + 1; k < expressionTags.length - 1; k++) {
if (tags[i + k] == '.') {
console.log(strings[i + k]);
i += k;
isBroken = true;
break;
}
}
if (isBroken) {
break;
}
for (var j = expressionTags.length - 1; j < expressionTags.length + wordDistanceTolerance; j++) {
if (tags[i + j] == '.' && strings[i + j].trim() !== '') {
i += j;
break;
} else if (tags[i + j] == expressionTags[expressionTags.length - 1]) {
var matchingExpression = stringUtils.join(strings.slice(i, i + j + 1));
if (!(containsPunctuation(matchingExpression) && !containsPunctuation(expression))) {
var classifications = classifier.getClassifications(matchingExpression);
for (var k = 0; k < classifications.length; k++) {
if (
(
classifications[k].value >= minimumClassificationValue
|| matchingExpression === expression
)
&& classifications[k].label === meaning
) {
var text =
stringUtils.join(
strings.slice(0, i)
.concat(classifications[k].label)
.concat(strings.slice(i + j + 1, strings.length))
);
return _self.classify(text);
}
}
}
}
}
}
}
}
return stringUtils.join(strings);
}
function tag(text) {
var tags = tagger.tag(text);
for (var i = 0; i < tags.length; i++) {
if (tags[i] == 'NUM') {
tags[i] = 'NOUN';
}
}
return tags;
}
function containsPunctuation(string) {
return string.indexOf('.') > -1;
}
}
module.exports = Classifier;