+ Logica is an open source declarative logic programming language for data manipulation.
+
+
+
+ Logica extends syntax of logic programming for intuitive and efficient data
+ manipulation. It compiles to SQL thus providing you access to the power
+ of SQL engines with the convenience of logic programming syntax.
+
+
+
+
+
Examples
+
+
+
+ One may say that for programming languages like Python and Java functions are the
+ basic building blocks. For Logica and other logic programming languages
+ those building blocks are predicates.
+
+ Logic program is defined as a set of rules that define output predicates
+ from pre-defied predicates. Those pre-defined predecates represent input data.
+
+ For example here is a rule to identify names of expensive books, from an existing
+ table of book prices.
+
+
+
+
+# Logica rule to get expensive books.
+ExpensiveBook(book_name) :- # book_name is expensive if and only if
+ Book(book_name, price), # book_name costs price
+ price > 100; # and price is greater than 100.
+
+
+
+If you are familiar with SQL, you may see that the rule above
+is equivalent to the flowing SQL statement. Not that familiarity with SQL is
+required to learn Logica, not at all.
+
+
+
+# SQL statement to get expensive books.
+SELECT book_name
+FROM book
+WHERE price > 100;
+
+
+Predicate is a statement with variables. Any table can be treated as predicate,
+where column names are the variables, and each row is a set of values of the variables
+that satisfies the statement.
+
+While SQL is quite convenient for small queries like the one above it
+gets hard to read when complexity grows. Logica leverages power of
+mathematical syntax to scale nicely as complexity grows.
+
+Let's assume we have a table BabyNames
+that for each name, year, city and
+gender specifies
+number of babies of that name born.
+The following program finds a list of popular names, where a name
+is defined as popular if it was the most popular name on some year.
+
+
+# Count babies per year.
+NameCountByYear(name:, year:) += number :-
+ BabyNames(name:, year:, number:);
+
+# For each year pick the most popular.
+TopNameByYear(year) ArgMax= name -> NameCountByYear(name:, year:);
+
+# Accumulate most popular name into a table, droppig the year.
+PopularName(name: TopNameByYear());
+
+
+Sometimes data analysis requires solving algorithmic problems. Logica's
+syntax is suited for it naturally. Here is a program finding prime numbers
+that are less than 100.
+
+
+# Define natural numbers from 0 to 99.
+N(x) :- x in Range(100);
+# Define primes.
+Prime(prime: x) :-
+ N(x),
+ x > 1,
+ ~(
+ N(y),
+ y > 1,
+ y != x,
+ x % y == 0
+ );
+
+
+
+Finally here is an example of program that runs over
+GDELT Project dataset,
+finding people mentioned in the context of "artificial general intelligence".
+
+
+
+
Observe that program is divided into a rule defining predicate
+ NewsData and rule for AgiMentions.
+The first rule is essentially doing data cleaning, formatting the dataset in a shape
+that is convenient to use. Then second rule peforms the task at hand.
+
+
+
+In Logica problems are naturally split into smaller components that end up
+reusable. So in the future if we have more analysis to do with GDELT dataset
+we may take advantage of the NewsData predicate that we just wrote.
+
+
+
+# Structuring the data conveniently.
+NewsData(year:, month:, day:, persons:, quotations:) :-
+ gdelt-bq.gdeltv2.gkg(persons: persons_str, quotations:, date: date_num),
+ # Column `data` in GDELT dataset is given as an integer.
+ year == ToInt64(Substr(ToString(date_num), 1, 4)),
+ month == ToInt64(Substr(ToString(date_num), 5, 2)),
+ day == ToInt64(Substr(ToString(date_num), 7, 2)),
+ persons List= (person :- person in Split(persons_str, ";"));
+
+# Performing the task at hand.
+@OrderBy(AgiMentions, "mentions desc");
+@Limit(AgiMentions, 10);
+AgiMentions(person:, mentions? += 1) distinct :-
+ person in persons,
+ Like(quotations, "%artificial general intelligence%"),
+ NewsData(persons:, quotations:);
+
+
+
+This program completes in interactive time
+when ran over the 4TB dataset
+via BigQuery.
+
+
+
Why Logica?
+
+Logica is for engineers, data scientists and other specialists who
+need to perform complex data processing and analysis.
+Queries and pipelines written in Logica can run on
+BigQuery and SQLite engines.
+Information stored in these systems is thus available in Logica.
+
+
+
+Logica compiles to SQL and gives you access to the power of SQL engines,
+including the massively distrbuted Google BigQuery engine,
+with the convenience of logic programming syntax. This is useful because
+BigQuery is magnitudes more powerful than state of the art native
+logic programming engines.
+
+
+
+We encourage you to try Logica, especially if
+
+
+
+
you already use logic programming and need more computational power, or
+
you use SQL, but feel unsatisfied about its readability, or
+
you want to learn logic programming and apply it to processing of Big Data.
+
+
+Among other engines, there is partial support for Trino and Postgres.
+Contributions to improve this support are
+very welcome!
+
+
+
+
I have not heard of logic programming. What is it?
+
+
+Logic programming is a declarative programming paradigm where the program is
+written as a set of logical statements.
+
+
+
+Logic programming was developed in academia from the late 60s. Prolog and
+Datalog are the most prominent examples of logic programming languages.
+Logica is a successor to
+Yedalog,
+a language created at Google earlier. Logica as well as Yedalog belong to
+Datalog family.
+
+
+
+Datalog and relational databases start from the same idea: think of data
+as relations and think of data manipulation as a sequence of operations over
+these relations. But Datalog and SQL differ in how these operations are
+described. Datalog is inspired by the mathematical syntax of the first order
+propositional logic and SQL follows the syntax of natural language.
+
+
+
+SQL was based on the natural language to give access to databases to the people
+without formal training in computer programming or mathematics. This convenience
+may become costly when the logic that you want to express is non trivial.
+There are many examples of hard-to-read SQL queries that correspond to simple
+logic programs.
+
+
+
+Logica follows Yedalog in the attempt to merge these branches back together:
+extending the elegant syntax of Logic Programming to solve practical problems
+and leverage the tremendous advances of SQL infrastructure for the execution.
+
+
+
+
How does Logica work?
+
+Logica compiles the logic program into a SQL expression,
+so it can be executed on BigQuery, the state of the art SQL engine.
+
+Among database theoreticians Datalog and SQL are known to be equivalent.
+And indeed the conversion from Datalog to SQL and back is often straightforward.
+However there are a few nuances, for example how to treat disjunction and negation. In Logica we tried to make choices that make understanding of the resulting SQL structure as easy as possible, thus empowering user to write programs that are executed efficiently.
+
+
+Learn basics of Logica with the
+CoLab tutorial
+located at tutorial folder.
+See examples of using Logica in examples folder.
+
+You try Logica immediately in the browser in Playground.
+
+
+
+It is easy to install Logica on your machine as well.
+
+# Welcome to Logica Playground!
+# Go ahead and edit this program. Start with editing book names and prices.
+# You can write new predicates, specify which predicate you want to
+# run in the input box below.
+Book("From Caves to Stars", 120);
+Book("Morning of Juliet", 40);
+Book("Dawn of the Apes", 45);
+Book("Tragedy and Discord", 124);
+Book("How to Get Rich Writing Books for $5", 5);
+Book("I Wrote a Book for $5, Guess What Happened Next!", 4);
+Book("Breakfast at Paris", 30);
+Book("My Friend: Dragon", 102);
+
+ExpensiveBook(book_name) :-
+ Book(book_name, price),
+ price > 100;
+
+
+
\ No newline at end of file
diff --git a/docs/syntax_highlighting.js b/docs/syntax_highlighting.js
new file mode 100644
index 0000000..20ab0b1
--- /dev/null
+++ b/docs/syntax_highlighting.js
@@ -0,0 +1,69 @@
+/*
+Copyright 2023 Google LLC
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License. */
+
+
+function HighlightCodeElements(doc) {
+ console.log('HELLO!');
+ synt_obj = {
+ multiline_comment: /\/\*.*\*\//gs,
+ end_of_line_comment: /#.*/g,
+ operator: />|</g,
+ string: /["].*["]/g,
+ predicate: /[A-Z]\w*/g,
+ field: /\w+:/g,
+ agg_field: /\w+[?]/g,
+ keyword: / if | then | else | distinct | in /g,
+ variable: /[a-z]\w*/g
+ };
+
+ function Decorate(s, r, prefix, suffix, subdecor) {
+ let result = ''
+ let from_index = 0;
+ s.replace(r, (match, at, unused_s) => {
+ result += subdecor(s.slice(from_index, at));
+ result += prefix + match + suffix;
+ from_index = at + match.length;
+ return '';
+ });
+
+ result += subdecor(s.slice(from_index, s.length));
+ return result;
+ }
+
+ var syntax_elements = Object.entries(synt_obj);
+
+ function MakeDecorator(syntax_elements) {
+ let n, r, rest;
+ [[n, r], ...rest] = syntax_elements;
+
+ let subdecorator;
+ if (rest.length > 0) {
+ subdecorator = MakeDecorator(rest);
+ } else {
+ subdecorator = x => x;
+ }
+ return s => Decorate(s, r, `
`, `
`, subdecorator);
+ }
+
+ function HighlightLogicaCode(code) {
+ highlighter = MakeDecorator(syntax_elements);
+ return highlighter(code);
+ }
+
+ divs = doc.getElementsByClassName('code');
+ for (let d of divs) {
+ d.innerHTML = HighlightLogicaCode(d.innerText);
+ }
+}
\ No newline at end of file