Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial version.

  • Loading branch information...
commit 12157cb3eaf74a8b9d0fb7091f1c8e2b46c0739a 0 parents
@tvondra authored
43 META.json
@@ -0,0 +1,43 @@
+{
+ "name": "fuzzy_logic",
+ "abstract": "Operators for three basic fuzzy logics - Łukasiewicz, Gödel and product.",
+ "description": "Implements basic logical operators (conjunction, disjunction, implication and negation) for three basic fuzzy logics - Łukasiewicz, Gödel and product. In case of the Łukasiewicz logic, there are also operators for weak conjunction and disjunction.",
+ "version": "1.0.0",
+ "maintainer": "Tomas Vondra <tv@fuzzy.cz>",
+ "license": "bsd",
+ "prereqs": {
+ "runtime": {
+ "requires": {
+ "PostgreSQL": "8.3.0"
+ }
+ }
+ },
+ "provides": {
+ "godel_logic": {
+ "file": "godel_logic--1.0.0.sql",
+ "version": "1.0.0"
+ },
+ "lukasiewicz_logic": {
+ "file": "lukasiewicz_logic--1.0.0.sql",
+ "version": "1.0.0"
+ },
+ "product_logic": {
+ "file": "product_logic--1.0.0.sql",
+ "version": "1.0.0"
+ }
+ },
+ "resources": {
+ "repository": {
+ "url": "https://github.com:tvondra/fuzzy_logic.git",
+ "web": "http://github.com/tvondra/fuzzy_logic",
+ "type": "git"
+ },
+ "x_wiki": "http://en.wikipedia.org/wiki/Fuzzy_logic"
+ },
+ "tags" : ["fuzzy", "logic", "operators", "Gödel", "product", "Łukasiewicz"],
+ "meta-spec": {
+ "version": "1.0.0",
+ "url": "http://pgxn.org/meta/spec.txt"
+ },
+ "release_status" : "testing"
+}
9 Makefile
@@ -0,0 +1,9 @@
+EXTENSION = godel_logic lukasiewicz_logic product_logic
+DATA = sql/godel_logic--1.0.0.sql sql/lukasiewicz_logic--1.0.0.sql sql/product_logic--1.0.0.sql
+
+CFLAGS=`pg_config --includedir-server`
+
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+
85 README.md
@@ -0,0 +1,85 @@
+Fuzzy logic
+===========
+This extension provides basic logical operators (conjunction, disjunction,
+implication and negation) for three basic fuzzy logics - Łukasiewicz, Gödel
+and product. For the Łukasiewicz logic, there are also operators for weak
+conjunction and disjunction.
+
+
+Installation
+------------
+Technically, there are three extensions - one for each logic. You have to
+choose just one of them, as all of them define the same operators.
+
+* `godel_logic` - Gödel logic
+* `lukasiewicz_logic` - Łukasiewicz logic
+* `product_logic` - product logic
+
+So let's say you've chosen Łukasiewicz logic, therefore you want to install
+the `lukasiewicz_logic` extension. If you're on 9.1 (or newer), all you need
+to do to install it is
+
+ $ make install
+
+and then
+
+ db=# CREATE EXTENSION lukasiewicz_logic;
+
+This should create a `fuzzy_boolean` data type (technically a FLOAT domain)
+and four basic logical operators (shared by all three extensions):
+
+* `&` - conjunction (AND)
+* `|` - disjunction (OR)
+* `!` - negation (NOT)
+* `->` - implication
+
+and two logical operators (just for Łukasiewicz logic)
+
+* `&&` - weak conjunction
+* `||` - weak disjunction
+
+So now when the logic is installed, let's use it.
+
+
+Usage
+-----
+Using the extension is quite straightforward - get somewhere a fuzzy boolean
+value and apply the operators to it. E.g. you can do this
+
+ db=# SELECT (0.5 & 0.5) -> (!0.3 | 0.3);
+
+ result
+ --------
+ 1
+
+or you may create a table with `fuzzy_boolean` column. Or maybe you can
+define predicates - functions returning `fuzzy_boolean` values and then use
+them like this
+
+ db=# SELECT is_fast(speed) & (! is_expensive(price)) FROM cars;
+
+and so on.
+
+
+Drawbacks
+---------
+The first thing to realize is that with fuzzy logic the world is not just
+black and white anymore. There's not just perfect truth and falsehood - there're
+many degrees of truth. The unpleasant consequence is that the indexing does not
+work as efficiently as with plain boolean values.
+
+You can make it work with simple conditions like these
+
+ db=# SELECT * FROM cars WHERE is_fast > 0.8
+
+or with a predicate and an expression index
+
+ db=# SELECT * FROM cars WHERE is_fast(speed) > 0.8
+
+But once you start combining the conditions, the indexing does not work. Consider
+for example this query
+
+ db=# SELECT * FROM cars WHERE is_fast & (! is_expensive) > 0.75
+
+With plain boolean conditions, it could be evaluated using a bitmap index scan,
+but with fuzzy logic that's not possible.
4 godel_logic.control
@@ -0,0 +1,4 @@
+# Gödel fuzzy logic
+comment = 'Provides operators to evaluate fuzzy logic expressions according to Gödel logic.'
+default_version = '1.0.0'
+relocatable = true
4 lukasiewicz_logic.control
@@ -0,0 +1,4 @@
+# Łukasiewicz fuzzy logic
+comment = 'Provides operators to evaluate fuzzy logic expressions according to Łukasiewicz logic.'
+default_version = '1.0.0'
+relocatable = true
4 product_logic.control
@@ -0,0 +1,4 @@
+# Product fuzzy logic
+comment = 'Provides operators to evaluate fuzzy logic expressions according to product logic.'
+default_version = '1.0.0'
+relocatable = true
38 sql/godel_logic--1.0.0.sql
@@ -0,0 +1,38 @@
+CREATE DOMAIN fuzzy_boolean AS FLOAT CHECK (VALUE BETWEEN 0 AND 1);
+
+CREATE FUNCTION godel_conjunction(a fuzzy_boolean, b fuzzy_boolean) RETURNS fuzzy_boolean AS $$
+ SELECT least($1, $2)::fuzzy_boolean;
+$$ LANGUAGE SQL;
+
+CREATE FUNCTION godel_disjunction(a fuzzy_boolean, b fuzzy_boolean) RETURNS fuzzy_boolean AS $$
+ SELECT (1 - least(1-$1, 1-$2))::fuzzy_boolean;
+$$ LANGUAGE SQL;
+
+CREATE FUNCTION godel_residuum(a fuzzy_boolean, b fuzzy_boolean) RETURNS fuzzy_boolean AS $$
+ SELECT (CASE WHEN $2 >= $1 THEN 1 ELSE $2 END)::fuzzy_boolean;
+$$ LANGUAGE SQL;
+
+CREATE FUNCTION godel_negation(a fuzzy_boolean) RETURNS fuzzy_boolean AS $$
+ SELECT (CASE WHEN $1 = 0 THEN 1 ELSE 0 END)::fuzzy_boolean;
+$$ LANGUAGE SQL;
+
+CREATE OPERATOR & (
+ PROCEDURE = godel_conjunction,
+ LEFTARG = fuzzy_boolean,
+ RIGHTARG = fuzzy_boolean,
+ COMMUTATOR = &);
+
+CREATE OPERATOR | (
+ PROCEDURE = godel_disjunction,
+ LEFTARG = fuzzy_boolean,
+ RIGHTARG = fuzzy_boolean,
+ COMMUTATOR = |);
+
+CREATE OPERATOR -> (
+ PROCEDURE = godel_residuum,
+ LEFTARG = fuzzy_boolean,
+ RIGHTARG = fuzzy_boolean);
+
+CREATE OPERATOR ! (
+ PROCEDURE = godel_negation,
+ RIGHTARG = fuzzy_boolean);
58 sql/lukasiewicz_logic--1.0.0.sql
@@ -0,0 +1,58 @@
+CREATE DOMAIN fuzzy_boolean AS FLOAT CHECK (VALUE BETWEEN 0 AND 1);
+
+CREATE FUNCTION lukasiewicz_conjunction(a fuzzy_boolean, b fuzzy_boolean) RETURNS fuzzy_boolean AS $$
+ SELECT greatest(0, $1 + $2 - 1)::fuzzy_boolean;
+$$ LANGUAGE SQL;
+
+CREATE FUNCTION lukasiewicz_weak_conjunction(a fuzzy_boolean, b fuzzy_boolean) RETURNS fuzzy_boolean AS $$
+ SELECT least($1, $2)::fuzzy_boolean;
+$$ LANGUAGE SQL;
+
+CREATE FUNCTION lukasiewicz_disjunction(a fuzzy_boolean, b fuzzy_boolean) RETURNS fuzzy_boolean AS $$
+ SELECT least(1, $1 + $2)::fuzzy_boolean;
+$$ LANGUAGE SQL;
+
+CREATE FUNCTION lukasiewicz_weak_disjunction(a fuzzy_boolean, b fuzzy_boolean) RETURNS fuzzy_boolean AS $$
+ SELECT greatest($1, $2)::fuzzy_boolean;
+$$ LANGUAGE SQL;
+
+CREATE FUNCTION lukasiewicz_residuum(a fuzzy_boolean, b fuzzy_boolean) RETURNS fuzzy_boolean AS $$
+ SELECT least(1, 1 - $1 + $2)::fuzzy_boolean;
+$$ LANGUAGE SQL;
+
+CREATE FUNCTION lukasiewicz_negation(a fuzzy_boolean) RETURNS fuzzy_boolean AS $$
+ SELECT (1 - $1)::fuzzy_boolean;
+$$ LANGUAGE SQL;
+
+CREATE OPERATOR & (
+ PROCEDURE = lukasiewicz_conjunction,
+ LEFTARG = fuzzy_boolean,
+ RIGHTARG = fuzzy_boolean,
+ COMMUTATOR = &);
+
+CREATE OPERATOR && (
+ PROCEDURE = lukasiewicz_weak_conjunction,
+ LEFTARG = fuzzy_boolean,
+ RIGHTARG = fuzzy_boolean,
+ COMMUTATOR = &&);
+
+CREATE OPERATOR | (
+ PROCEDURE = lukasiewicz_disjunction,
+ LEFTARG = fuzzy_boolean,
+ RIGHTARG = fuzzy_boolean,
+ COMMUTATOR = |);
+
+CREATE OPERATOR || (
+ PROCEDURE = lukasiewicz_weak_disjunction,
+ LEFTARG = fuzzy_boolean,
+ RIGHTARG = fuzzy_boolean,
+ COMMUTATOR = ||);
+
+CREATE OPERATOR -> (
+ PROCEDURE = lukasiewicz_residuum,
+ LEFTARG = fuzzy_boolean,
+ RIGHTARG = fuzzy_boolean);
+
+CREATE OPERATOR ! (
+ PROCEDURE = lukasiewicz_negation,
+ RIGHTARG = fuzzy_boolean);
38 sql/product_logic--1.0.0.sql
@@ -0,0 +1,38 @@
+CREATE DOMAIN fuzzy_boolean AS FLOAT CHECK (VALUE BETWEEN 0 AND 1);
+
+CREATE FUNCTION product_conjunction(a fuzzy_boolean, b fuzzy_boolean) RETURNS fuzzy_boolean AS $$
+ SELECT ($1*$2)::fuzzy_boolean;
+$$ LANGUAGE SQL;
+
+CREATE FUNCTION product_disjunction(a fuzzy_boolean, b fuzzy_boolean) RETURNS fuzzy_boolean AS $$
+ SELECT ($1 + $2 - $1*$2)::fuzzy_boolean;
+$$ LANGUAGE SQL;
+
+CREATE FUNCTION product_residuum(a fuzzy_boolean, b fuzzy_boolean) RETURNS fuzzy_boolean AS $$
+ SELECT least(1, $2/$1)::fuzzy_boolean;
+$$ LANGUAGE SQL;
+
+CREATE FUNCTION product_negation(a fuzzy_boolean) RETURNS fuzzy_boolean AS $$
+ SELECT (CASE WHEN $1 = 0 THEN 1 ELSE 0 END)::fuzzy_boolean;
+$$ LANGUAGE SQL;
+
+CREATE OPERATOR & (
+ PROCEDURE = product_conjunction,
+ LEFTARG = fuzzy_boolean,
+ RIGHTARG = fuzzy_boolean,
+ COMMUTATOR = &);
+
+CREATE OPERATOR | (
+ PROCEDURE = product_disjunction,
+ LEFTARG = fuzzy_boolean,
+ RIGHTARG = fuzzy_boolean,
+ COMMUTATOR = |);
+
+CREATE OPERATOR -> (
+ PROCEDURE = product_residuum,
+ LEFTARG = fuzzy_boolean,
+ RIGHTARG = fuzzy_boolean);
+
+CREATE OPERATOR ! (
+ PROCEDURE = product_negation,
+ RIGHTARG = fuzzy_boolean);
Please sign in to comment.
Something went wrong with that request. Please try again.