changeset 5f35f461245c in sao:default
details: https://hg.tryton.org/sao?cmd=changeset&node=5f35f461245c
description:
Deduplicate entries in domain inversion's simplify
issue11248
review397301002
diffstat:
src/common.js | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
tests/sao.js | 67 ++++++++++++++++++++++++++++++++++++++++--------
2 files changed, 125 insertions(+), 23 deletions(-)
diffs (193 lines):
diff -r b426134f663b -r 5f35f461245c src/common.js
--- a/src/common.js Sat Mar 26 13:00:03 2022 +0100
+++ b/src/common.js Wed Mar 30 19:20:31 2022 +0200
@@ -2571,22 +2571,79 @@
return models;
}
},
+ _bool_operator: function(domain) {
+ var bool_op = 'AND';
+ if ((domain.length > 0) &&
+ ((domain[0] == 'AND') || (domain[0] == 'OR'))) {
+ bool_op = domain[0];
+ }
+ return bool_op;
+ },
+ simplify_nested: function(domain) {
+ if (!domain.length) {
+ return [];
+ } else if (this.is_leaf(domain)) {
+ return [domain];
+ } else if ((domain == 'AND') || (domain == 'OR')) {
+ return [domain];
+ } else if ((domain instanceof Array) && (domain.length == 1)) {
+ return this.simplify_nested(domain[0]);
+ } else {
+ var simplified = [];
+ var domain_op = this._bool_operator(domain);
+ for (var branch of domain) {
+ var simplified_branch = this.simplify_nested(branch);
+ if ((this._bool_operator(branch) == domain_op) ||
+ (simplified_branch.length == 1)) {
+ simplified.push(...simplified_branch);
+ } else {
+ simplified.push(simplified_branch);
+ }
+ }
+ return simplified;
+ }
+ },
+ simplify_duplicate: function(domain) {
+ var dedup_branches = [];
+ var bool_op = null;
+ if (~['AND', 'OR'].indexOf(domain[0])) {
+ bool_op = domain[0];
+ domain = domain.slice(1);
+ }
+ for (var branch of domain) {
+ var simplified_branch = this.simplify(branch);
+ if (simplified_branch.length == 0) {
+ if (bool_op === 'OR') {
+ return [];
+ } else {
+ continue;
+ }
+ }
+ var found_branch = false;
+ for (var duped_branch of dedup_branches) {
+ if (Sao.common.compare(
+ simplified_branch, duped_branch)) {
+ found_branch = true;
+ break;
+ }
+ }
+ if (!found_branch) {
+ dedup_branches.push(simplified_branch);
+ }
+ }
+
+ if (bool_op && (dedup_branches.length > 1)) {
+ dedup_branches.unshift(bool_op);
+ }
+ return dedup_branches;
+ },
simplify: function(domain) {
if (this.is_leaf(domain)) {
- return domain;
- } else if (~['OR', 'AND'].indexOf(domain)) {
- return domain;
- } else if ((domain instanceof Array) && (domain.length == 1) &&
- (~['OR', 'AND'].indexOf(domain[0]))) {
+ return [domain];
+ } else if (!domain.length) {
return [];
- } else if ((domain instanceof Array) && (domain.length == 1) &&
- (!this.is_leaf(domain[0]))) {
- return this.simplify(domain[0]);
- } else if ((domain instanceof Array) && (domain.length == 2) &&
- ~['AND', 'OR'].indexOf(domain[0])) {
- return [this.simplify(domain[1])];
} else {
- return domain.map(this.simplify.bind(this));
+ return this.simplify_nested(this.simplify_duplicate(domain));
}
},
merge: function(domain, domoperator) {
diff -r b426134f663b -r 5f35f461245c tests/sao.js
--- a/tests/sao.js Sat Mar 26 13:00:03 2022 +0100
+++ b/tests/sao.js Wed Mar 30 19:20:31 2022 +0200
@@ -2574,7 +2574,7 @@
JSON.stringify(context) + ')');
context = {y: 4, z: 'b'};
QUnit.ok(compare(domain_inversion(domain, 'x', context),
- ['OR', [['x', '=', 3]], [['x', '=', 2]]]),
+ ['OR', ['x', '=', 3], ['x', '=', 2]]),
'domain_inversion(' + JSON.stringify(domain) + ', \'x\', ' +
JSON.stringify(context) + ')');
});
@@ -2600,15 +2600,25 @@
var compare = Sao.common.compare;
[
- [[['x', '=', 3]], [['x', '=', 3]]],
- [[[['x', '=', 3]]], [['x', '=', 3]]],
- [['OR', ['x', '=', 3]], [['x', '=', 3]]],
- [['OR', [['x', '=', 3]], [['y', '=', 5]]],
- ['OR', [['x', '=', 3]], [['y', '=', 5]]]],
- [['OR', ['x', '=', 3], ['AND', ['y', '=', 5]]],
- ['OR', ['x', '=', 3], [['y', '=', 5]]]],
- [['AND'], []],
- [['OR'], []]
+ [[['x', '=', 3]], [['x', '=', 3]]],
+ [[[['x', '=', 3]]], [['x', '=', 3]]],
+ [
+ [[['x', '=', 3], ['y', '=', 4]]],
+ [['x', '=', 3], ['y', '=', 4]]],
+ [['OR', ['x', '=', 3]], [['x', '=', 3]]],
+ [
+ ['OR', [['x', '=', 3]], [['y', '=', 5]]],
+ ['OR', ['x', '=', 3], ['y', '=', 5]]],
+ [
+ ['OR', ['x', '=', 3], ['AND', ['y', '=', 5]]],
+ ['OR', ['x', '=', 3], ['y', '=', 5]]],
+ [[['x', '=', 3], ['OR']], [['x', '=', 3]]],
+ [['OR', ['x', '=', 3], []], []],
+ [['OR', ['x', '=', 3], ['OR']], []],
+ [[['x', '=', 3], []], [['x', '=', 3]]],
+ [[['x', '=', 3], ['AND']], [['x', '=', 3]]],
+ [['AND'], []],
+ [['OR'], []]
].forEach(function(test) {
var domain = test[0];
var result = test[1];
@@ -2617,6 +2627,41 @@
});
});
+ QUnit.test('DomainInversion simplify deduplicate', function() {
+ var domain_inversion = new Sao.common.DomainInversion();
+ var simplify = domain_inversion.simplify.bind(domain_inversion);
+ var compare = Sao.common.compare;
+
+ var clause = ['x', '=', 3];
+ var another = ['y', '=', 4];
+ var third = ['z', '=', 5];
+ [
+ [[], []],
+ [['OR', []], []],
+ [['AND', []], []],
+ [[clause], [clause]],
+ [['OR', clause], [clause]],
+ [[clause, clause], [clause]],
+ [['OR', clause, clause], [clause]],
+ [[clause, [clause, clause]], [clause]],
+ [[clause, another], [clause, another]],
+ [['OR', clause, another], ['OR', clause, another]],
+ [[clause, clause, another], [clause, another]],
+ [[clause, [clause, clause], another], [clause, another]],
+ [[clause, clause, another, another], [clause, another]],
+ [[clause, another, clause, another], [clause, another]],
+ [
+ ['AND', ['OR', clause, another], third],
+ ['AND', ['OR', clause, another], third]],
+ ].forEach(function(test) {
+ var domain = test[0];
+ var result = test[1];
+ QUnit.ok(compare(simplify(domain), result),
+ 'simplify(' + JSON.stringify(domain) + ')');
+ });
+
+ });
+
QUnit.test('DomainInversion merge', function() {
var domain_inversion = new Sao.common.DomainInversion();
var merge = domain_inversion.merge.bind(domain_inversion);
@@ -2669,7 +2714,7 @@
QUnit.ok(compare(concat([[], []]), []),
'compare(' + JSON.stringify([[], []]) + ')');
QUnit.ok(compare(concat([domain1, domain2], 'OR'),
- ['OR', [['a', '=', 1]], [['b', '=', 2]]]),
+ ['OR', ['a', '=', 1], ['b', '=', 2]]),
'compare(' + JSON.stringify([domain1, domain2]) + ', \'OR\')');
});