Commit 1fa24546 by Lauri Himanen

### Getting close to working implementation.

parent d86abfde
This diff is collapsed.
 ... @@ -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!