Commit 1fa24546 authored by Lauri Himanen's avatar Lauri Himanen
Browse files

Getting close to working implementation.

parent d86abfde
This diff is collapsed.
window.nomadEnv = { window.nomadEnv = {
//apiRoot: "https://nomad-lab.eu/dev/nomad/enc-search/api/encyclopedia/", //apiRoot: "https://nomad-lab.eu/dev/nomad/enc-search/api/encyclopedia/",
//apiRoot: "https://nomad-lab.eu/dev/rae/enc-search/api/encyclopedia/", apiRoot: "https://nomad-lab.eu/dev/rae/enc-search/api/encyclopedia/",
apiRoot: "https://nomad-lab.eu/prod/rae/beta/api/encyclopedia/", //apiRoot: "https://nomad-lab.eu/prod/rae/beta/api/encyclopedia/",
//apiRoot: "https://nomad-lab.eu/prod/rae/api/encyclopedia/", //apiRoot: "https://nomad-lab.eu/prod/rae/api/encyclopedia/",
......
...@@ -362,7 +362,7 @@ class NewSearchMod { ...@@ -362,7 +362,7 @@ class NewSearchMod {
sendQuery(){ sendQuery(){
//**** The optimade query must be formed from the search box and the properties selected //**** The optimade query must be formed from the search box and the properties selected
const searchBoxOptimadeQuery = this.searchBox.getOptimadeQuery(this.allowOtherElementsCheckbox.checked); const searchBoxOptimadeQuery = this.searchBox.getOptimadeQuery2(this.allowOtherElementsCheckbox.checked);
const propsOptimadeQuery = getOptimadeQueryFromProps(this.filterPanel.getValues()); const propsOptimadeQuery = getOptimadeQueryFromProps(this.filterPanel.getValues());
const sep = (searchBoxOptimadeQuery !== '' && propsOptimadeQuery !== '' ? ' AND ' : ''); const sep = (searchBoxOptimadeQuery !== '' && propsOptimadeQuery !== '' ? ' AND ' : '');
......
...@@ -81,17 +81,17 @@ class SearchBox{ ...@@ -81,17 +81,17 @@ class SearchBox{
} }
/** getOptimadeQuery2(allowOtherElements) {
* Given the final query, this function uses boolean algebra to reduce it let query = [...this.searchQuery];
* into a flattened list of sets combined with AND or OR. let types = [...this.queryTypes];
*/
reduceQuery(query, types) {
// For combining elements connected by AND into a list // For combining elements connected by AND into a list
function combineANDIn(query, types) { function combineANDIn(query, types) {
const newQuery = [] const newQuery = []
const newTypes = [] const newTypes = []
for (let i=0; i < query.length;) { for (let i=0; i < query.length;) {
const q0 = query[i-1];
const t0 = types[i-1];
const q1 = query[i]; const q1 = query[i];
const t1 = types[i]; const t1 = types[i];
const q2 = query[i+1]; const q2 = query[i+1];
...@@ -99,7 +99,7 @@ class SearchBox{ ...@@ -99,7 +99,7 @@ class SearchBox{
const q3 = query[i+2]; const q3 = query[i+2];
const t3 = types[i+2]; const t3 = types[i+2];
if ((t1 === "E" || t1 === "EL" ) && (t3 === "E" || t3 === "EL" ) && q2 === "AND") { if ((t1 === "E" || t1 === "EL" ) && (t3 === "E" || t3 === "EL" ) && q2 === "AND" && q0 !== "NOT") {
let active = true let active = true
let elements = [q1, q3] let elements = [q1, q3]
i = i + 3 i = i + 3
...@@ -126,16 +126,16 @@ class SearchBox{ ...@@ -126,16 +126,16 @@ class SearchBox{
return [newQuery, newTypes] return [newQuery, newTypes]
} }
// For removing unnecessary quotes // For finding parenthesis pairs
function removeParenthesis(query, types) { function findPairs(query, types) {
//console.log(query) const pairs = new Map();
//console.log(types)
// Find list of indices where parenthesis should be removed
let removed = [] let removed = []
for (let i=0; i < query.length; ++i) { for (let i=0; i < query.length; ++i) {
const q1 = query[i]; const q1 = query[i];
const t1 = types[i]; const t1 = types[i];
if (q1 === "(") { if (q1 === "(") {
//console.log("Start found!")
let index = 0; let index = 0;
for (let j=i+1; j < query.length; ++j) { for (let j=i+1; j < query.length; ++j) {
const q2 = query[j]; const q2 = query[j];
...@@ -144,51 +144,89 @@ class SearchBox{ ...@@ -144,51 +144,89 @@ class SearchBox{
index += 1; index += 1;
} }
if (q2 === ")") { if (q2 === ")") {
//console.log("End found!")
if (index != 0) { if (index != 0) {
index -= 1; index -= 1;
} else { } else {
const contents = query.slice(i+1, j) pairs.set(i, j)
//console.log("PARENTHESIS VALUES") pairs.set(j, i)
//console.log(contents) break
//console.log(i+1, j) }
const tp = types.slice(i+1, j) }
//console.log("PARENTHESIS TYPES") }
//console.log(tp) }
let noop = true }
for (let t of tp) { return pairs;
if (t === "S") { }
noop = false
break // For removing unnecessary parenthesis
} function removeParenthesis(query, types) {
}
if (noop) { // Find list of indices where parenthesis should be removed
removed.push(j) const pairs = findPairs(query, types)
removed.push(i) let removed = []
} for (let i=0; i < query.length; ++i) {
const q1 = query[i];
const t1 = types[i];
if (q1 === "(") {
let p = pairs.get(i)
// Remove outer parentheses
if (i === 0 && p == query.length-1) {
removed.push(p)
removed.push(i)
// Remove parentheses that do not contain multiple operations
} else {
const contents = query.slice(i+1, p)
const tp = types.slice(i+1, p)
let noop = true
for (let t of tp) {
if (t === "S") {
noop = false
break break
} }
} }
if (noop) {
removed.push(p)
removed.push(i)
}
}
}
}
// Find repeated quotes and reduce them to single one
for (let i=0; i < query.length; ++i) {
const q1 = query[i];
const t1 = types[i];
const q2 = query[i+1];
const t2 = types[i+1];
if (q1 === "(" && q1 === "(") {
let p1 = pairs.get(i)
let p2 = pairs.get(i+1)
if (p2 == p1 - 1) {
removed.push(i)
removed.push(p1)
} }
} }
} }
// Remove found parentheses // Remove found parentheses
removed = removed.sort((a, b) => b - a); removed = removed.sort((a, b) => b - a);
//console.log(query.join(" "));
//console.log(removed);
for (let j=0; j < removed.length; ++j) { for (let j=0; j < removed.length; ++j) {
query.splice(removed[j], 1); query.splice(removed[j], 1);
types.splice(removed[j], 1); types.splice(removed[j], 1);
} }
//console.log(query.join(" "));
return [query, types] return [query, types]
} }
// For combining elements connected by AND into a list // Combines AND statements where either one or both of the statements has a
// parenthesis. These statements are refactored using distributive laws of
// set theory:
// A AND (B OR C) == (A AND B) OR (A AND C)
// in order to see if there are lists of elements that should be joined.
function combineANDOut(query, types) { function combineANDOut(query, types) {
let newQuery = query let newQuery = query
let newTypes = types let newTypes = types
const pairs = findPairs(query, types)
let combined = false let combined = false
for (let i=0; i < query.length; ++i) { for (let i=0; i < query.length; ++i) {
...@@ -208,17 +246,37 @@ class SearchBox{ ...@@ -208,17 +246,37 @@ class SearchBox{
let lhsT let lhsT
let rhsQ let rhsQ
let rhsT let rhsT
lhsQ = query.slice(0, i+1) let rhsEnd
lhsT = types.slice(0, i+1) let lhsStart
if (q1 !== ")") { if (q1 === ")") {
lhsStart = pairs.get(i)
lhsQ = query.slice(lhsStart, i+1)
lhsT = types.slice(lhsStart, i+1)
} else {
if (query[i-1] === "NOT") {
lhsStart = i-1
} else {
lhsStart = i
}
lhsQ = query.slice(lhsStart, i+1)
lhsT = types.slice(lhsStart, i+1)
lhsQ.unshift("(") lhsQ.unshift("(")
lhsT.unshift("P") lhsT.unshift("P")
lhsQ.push(")") lhsQ.push(")")
lhsT.push("P") lhsT.push("P")
} }
rhsQ = query.slice(i+2, query.length) if (q3 === "(") {
rhsT = types.slice(i+2, query.length) rhsEnd = pairs.get(i+2)+1
if (q3 !== "(") { rhsQ = query.slice(i+2, rhsEnd)
rhsT = types.slice(i+2, rhsEnd)
} else {
if (query[i+2] === "NOT") {
rhsEnd = i+4
} else {
rhsEnd = i+3
}
rhsQ = query.slice(i+2, rhsEnd)
rhsT = types.slice(i+2, rhsEnd)
rhsQ.unshift("(") rhsQ.unshift("(")
rhsT.unshift("P") rhsT.unshift("P")
rhsQ.push(")") rhsQ.push(")")
...@@ -272,8 +330,12 @@ class SearchBox{ ...@@ -272,8 +330,12 @@ class SearchBox{
comboT.push("P") comboT.push("P")
} }
} }
newQuery = comboQ comboQ.unshift("(")
newTypes = comboT comboT.unshift("P")
comboQ.push(")")
comboT.push("P")
newQuery = query.slice(0, lhsStart).concat(comboQ).concat(query.slice(rhsEnd, query.length))
newTypes = types.slice(0, lhsStart).concat(comboT).concat(types.slice(rhsEnd, query.length))
break break
} }
} }
...@@ -283,11 +345,11 @@ class SearchBox{ ...@@ -283,11 +345,11 @@ class SearchBox{
// Merge // Merge
function merge(query, types) { function merge(query, types) {
// Remove unnecessary parenthesis // Remove unnecessary parenthesis, combine all elements connected with
// AND, and remove unnecessary parenthesis again.
[query, types] = removeParenthesis(query, types); [query, types] = removeParenthesis(query, types);
// Combined all elements connected with AND
[query, types] = combineANDIn(query, types); [query, types] = combineANDIn(query, types);
[query, types] = removeParenthesis(query, types);
// Combine parenthesis statements // Combine parenthesis statements
let combined let combined
...@@ -297,21 +359,71 @@ class SearchBox{ ...@@ -297,21 +359,71 @@ class SearchBox{
// done // done
if (combined) { if (combined) {
[query, types] = merge(query, types) [query, types] = merge(query, types)
// After the last step perform on final cleanup
} else { } else {
[query, types] = removeParenthesis(query, types); [query, types] = removeParenthesis(query, types);
[query, types] = combineANDIn(query, types); [query, types] = combineANDIn(query, types);
[query, types] = removeParenthesis(query, types);
} }
return [query, types] return [query, types]
} }
// Add escaped quotes to all elements
for (let i=0; i < query.length; ++i) {
let q = query[i];
let t = types[i];
if (t === "E") {
query[i] = `\"${q}\"`
}
}
// Add escaped quotes to formulas
for (let i=0; i < query.length; ++i) {
let q = query[i];
let t = types[i];
if (t === "F") {
const formula = new Formula(q)
const fragments = []
formula.formulaMap.forEach( (number, element)=> {
const fragment = '"' + element + (number === 1 ? '' : +number) + '"';
fragments.push(fragment)
})
query[i] = fragments.join(', ')
}
}
// Construct the reduced expression
[query, types] = merge(query, types); [query, types] = merge(query, types);
console.log(query.join(" "));
// Convert into optimade syntax
for (let i=0; i < query.length; ++i) {
let q = query[i];
let t = types[i];
if (t === "E" || t === "EL") {
if (allowOtherElements) {
q = "elements HAS ALL " + q
} else {
q = "elements HAS ONLY " + q
}
} else if (t === "F") {
if (allowOtherElements) {
q = "formula HAS ALL " + q
} else {
q = "formula HAS ONLY " + q
}
}
query[i] = q;
}
let res = query.join(" ")
console.log("FINAL OPTIMADE QUERY:")
console.log(res)
return res
} }
getOptimadeQuery(allowOtherElements){ getOptimadeQuery(allowOtherElements){
this.reduceQuery(this.searchQuery, this.queryTypes)
console.log('getOptimadeQuery this.searchQuery', this.searchQuery) console.log('getOptimadeQuery this.searchQuery', this.searchQuery)
if (this.searchQuery.length === 0 || if (this.searchQuery.length === 0 ||
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment