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 = {
//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/prod/rae/beta/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/api/encyclopedia/",
......
......@@ -362,7 +362,7 @@ class NewSearchMod {
sendQuery(){
//**** 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 sep = (searchBoxOptimadeQuery !== '' && propsOptimadeQuery !== '' ? ' AND ' : '');
......
......@@ -81,17 +81,17 @@ class SearchBox{
}
/**
* Given the final query, this function uses boolean algebra to reduce it
* into a flattened list of sets combined with AND or OR.
*/
reduceQuery(query, types) {
getOptimadeQuery2(allowOtherElements) {
let query = [...this.searchQuery];
let types = [...this.queryTypes];
// For combining elements connected by AND into a list
function combineANDIn(query, types) {
const newQuery = []
const newTypes = []
for (let i=0; i < query.length;) {
const q0 = query[i-1];
const t0 = types[i-1];
const q1 = query[i];
const t1 = types[i];
const q2 = query[i+1];
......@@ -99,7 +99,7 @@ class SearchBox{
const q3 = query[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 elements = [q1, q3]
i = i + 3
......@@ -126,16 +126,16 @@ class SearchBox{
return [newQuery, newTypes]
}
// For removing unnecessary quotes
function removeParenthesis(query, types) {
//console.log(query)
//console.log(types)
// For finding parenthesis pairs
function findPairs(query, types) {
const pairs = new Map();
// Find list of indices where parenthesis should be removed
let removed = []
for (let i=0; i < query.length; ++i) {
const q1 = query[i];
const t1 = types[i];
if (q1 === "(") {
//console.log("Start found!")
let index = 0;
for (let j=i+1; j < query.length; ++j) {
const q2 = query[j];
......@@ -144,17 +144,40 @@ class SearchBox{
index += 1;
}
if (q2 === ")") {
//console.log("End found!")
if (index != 0) {
index -= 1;
} else {
const contents = query.slice(i+1, j)
//console.log("PARENTHESIS VALUES")
//console.log(contents)
//console.log(i+1, j)
const tp = types.slice(i+1, j)
//console.log("PARENTHESIS TYPES")
//console.log(tp)
pairs.set(i, j)
pairs.set(j, i)
break
}
}
}
}
}
return pairs;
}
// For removing unnecessary parenthesis
function removeParenthesis(query, types) {
// Find list of indices where parenthesis should be removed
const pairs = findPairs(query, types)
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") {
......@@ -163,32 +186,47 @@ class SearchBox{
}
}
if (noop) {
removed.push(j)
removed.push(p)
removed.push(i)
}
break
}
}
}
// 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
removed = removed.sort((a, b) => b - a);
//console.log(query.join(" "));
//console.log(removed);
for (let j=0; j < removed.length; ++j) {
query.splice(removed[j], 1);
types.splice(removed[j], 1);
}
//console.log(query.join(" "));
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) {
let newQuery = query
let newTypes = types
const pairs = findPairs(query, types)
let combined = false
for (let i=0; i < query.length; ++i) {
......@@ -208,17 +246,37 @@ class SearchBox{
let lhsT
let rhsQ
let rhsT
lhsQ = query.slice(0, i+1)
lhsT = types.slice(0, i+1)
if (q1 !== ")") {
let rhsEnd
let lhsStart
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("(")
lhsT.unshift("P")
lhsQ.push(")")
lhsT.push("P")
}
rhsQ = query.slice(i+2, query.length)
rhsT = types.slice(i+2, query.length)
if (q3 !== "(") {
if (q3 === "(") {
rhsEnd = pairs.get(i+2)+1
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("(")
rhsT.unshift("P")
rhsQ.push(")")
......@@ -272,8 +330,12 @@ class SearchBox{
comboT.push("P")
}
}
newQuery = comboQ
newTypes = comboT
comboQ.unshift("(")
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
}
}
......@@ -283,11 +345,11 @@ class SearchBox{
// Merge
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);
// Combined all elements connected with AND
[query, types] = combineANDIn(query, types);
[query, types] = removeParenthesis(query, types);
// Combine parenthesis statements
let combined
......@@ -297,20 +359,70 @@ class SearchBox{
// done
if (combined) {
[query, types] = merge(query, types)
// After the last step perform on final cleanup
} else {
[query, types] = removeParenthesis(query, types);
[query, types] = combineANDIn(query, types);
[query, types] = removeParenthesis(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);
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){
this.reduceQuery(this.searchQuery, this.queryTypes)
getOptimadeQuery(allowOtherElements){
console.log('getOptimadeQuery this.searchQuery', this.searchQuery)
......
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