@c logic.mac--Logic algebra package for Maxima CAS.
@c Copyright (c) 2008--2009 Alexey Beshenov <al@beshenov.ru>.
@c
@c Version 2.1. Last modified 2009-01-07
@c
@c logic.mac is free software; you can redistribute it and/or modify it
@c under the terms of the GNU Lesser General Public License as published
@c by the Free Software Foundation; either version 2.1 of the License,
@c or (at your option) any later version.
@c
@c logic.mac is distributed in the hope that it will be useful, but
@c WITHOUT ANY WARRANTY; without even the implied warranty of
@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
@c General Public License for more details.
@c
@c You should have received a copy of the GNU General Public License
@c along with the logic.mac; see the file COPYING. If not, write to the
@c Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
@c Boston, MA 02110-1301, USA.

@top Logic algebra package for Maxima

@section Introduction

This is a draft version of logic algebra package for Maxima.
It is being developed by Alexey@tie{}Beshenov@tie{}(al@@beshenov.ru).
All source code is available uder the terms of GNU@tie{}GPL@tie{}2.1.

List of recognized operators:

@multitable @columnfractions .15 .10 .10 .45 .2
@headitem Operator @tab Type @tab Binding power @tab Description @tab Properties
@item @code{not}
@tab Prefix
@tab @code{70}
@tab Logical NOT (negation)
@tab
@item @code{and}
@tab N-ary
@tab @code{65}
@tab Logical AND (conjunction)
@tab Commutative
@item @code{nand}
@tab N-ary
@tab @code{62}
@tab Sheffer stroke (alternative denial, NAND)
@tab Commutative
@item @code{nor}
@tab N-ary
@tab @code{61}
@tab Webb-operation or Peirce arrow (Quine's dagger, NOR)
@tab Commutative
@item @code{or}
@tab N-ary
@tab @code{60}
@tab Logical OR (disjunction)
@tab Commutative
@item @code{implies}
@tab Infix
@tab @code{59}
@tab Implication
@tab
@item @code{eq}
@tab N-ary
@tab @code{58}
@tab Equivalence
@tab Commutative
@item @code{xor}
@tab N-ary
@tab @code{58}
@tab Sum modulo 2 (exclusive or)
@tab Commutative
@end multitable


@section @TeX{}@tie{}output

logic.mac assigns the following @TeX{}@tie{}output:

@table @code
@item not
@code{\neg}
@item and
@code{\wedge}
@item nand
@code{\mid}
@item nor
@code{\downarrow}
@item or
@code{\vee}
@item implies
@code{\rightarrow}
@item eq
@code{\sim}
@item xor
@code{\oplus}
@end table

Examples:

@example
(%i1) load ("logic.mac")$
@group
(%i2) tex (a implies b)$
$$a \rightarrow b$$
@end group
@group
(%i3) tex ((a nor b) nand c)$
$$\left(a \downarrow b\right) \mid c$$
@end group
@group
(%i4) tex (zhegalkin_form (a or b or c))$
$$a \wedge b \wedge c \oplus a \wedge b \oplus a \wedge c \oplus b
  \wedge c \oplus a \oplus b \oplus c$$
@end group
@group
(%i5) tex (boolean_form (a implies b implies c));
$$ \neg \left( \neg a \vee b\right) \vee c$$
@end group
@group
(%i6) tex (a eq b eq c);
$$a \sim b \sim c$$
@end group

@end example

@tex
$$a \rightarrow b$$
$$\left(a \downarrow b\right) \mid c$$
$$a \wedge b \wedge c \oplus a \wedge b \oplus a \wedge c \oplus b
  \wedge c \oplus a \oplus b \oplus c$$
$$ \neg \left( \neg a \vee b\right) \vee c$$
$$a \sim b \sim c$$
@end tex

@section Functions for logic algebra


@deffn {Function} logic_simp (@var{expr})

Returns a simplified version of logical expression @var{expr}.

Examples:

@example
(%i1) load ("logic.mac")$
@group
(%i2) logic_simp (a or (b or false or (a or b)));
(%o2)                               a or b
@end group
@group
(%i3) logic_simp (b eq a eq false eq true);
(%o3)                           eq a eq b false
@end group
@group
(%i4) logic_simp ((a xor true) xor b xor true);
(%o4)                               a xor b
@end group
@end example

The function applies only basic simplification rules without introducing new
functions.

N.B. It should be merged somehow with the basic Maxima simplifier.
@end deffn


@deffn {Function} characteristic_vector (@var{expr}, @var{var_1}, ..., @var{var_n})

Returns a list of size @math{2^n} with all possible values of @var{expr}.

For example, @code{characteristic_vector (f(x,y,z), x, y, z)} is equivalent to
list

@example
@group
[
  f (false, false, false),
  f (false, false,  true),
  f (false,  true, false),
  f (false,  true,  true),
  f ( true, false, false),
  f ( true, false,  true),
  f ( true,  true, false),
  f ( true,  true,  true)
]
@end group
@end example

If @code{@var{var_1}, ..., @var{var_n}} is omitted, it is assumed that

@example
[@var{var_1}, ..., @var{var_n}] = sort(listofvars(@var{expr}))
@end example

Examples:

@example
(%i1) load ("logic.mac")$
@group
(%i2) characteristic_vector (true);
(%o2)                               [true]
@end group
@group
(%i3) characteristic_vector (a xor b);
(%o3)                     [false, true, true, false]
@end group
@group
(%i4) characteristic_vector (a implies b);
(%o4)                      [true, true, false, true]
@end group
@group
(%i5) characteristic_vector (a implies b, a, b);
(%o5)                      [true, true, false, true]
@end group
@group
(%i6) characteristic_vector (a implies b, b, a);
(%o6)                      [true, false, true, true]
@end group
@end example
@end deffn


@deffn {Function} zhegalkin_form (@var{expr})

Returns the representation of @var{expr} in Zhegalkin basis
@code{@{xor, and, true@}}.

Examples:

@example
(%i1) load ("logic.mac")$
@group
(%i2) zhegalkin_form (a or b or c);
(%o2) (a and b and c) xor (a and b) xor (a and c)
                               xor (b and c) xor a xor b xor c
@end group
@group
(%i3) zhegalkin_form ((a implies b) or c);
(%o3) (a and b and c) xor (a and b) xor (a and c) xor a
                                                      xor true
@end group
@end example
@end deffn


@deffn {Function} logic_equiv (@var{expr_1}, @var{expr_2})

Returns @code{true} if @var{expr_1} is equivalent to @var{expr_2} and
@code{false} otherwise.

Examples:

@example
(%i1) load ("logic.mac")$
(%i2) e : ((a or b) xor c) and d$
@group
(%i3) zhegalkin_form (e);
(%o3) (a and b and d) xor (a and d) xor (b and d)
                                                 xor (c and d)
@end group
@group
(%i4) logic_equiv (%i2, %o3);
(%o4)                                true
@end group
@group
(%i5) is (characteristic_vector(%i2) = characteristic_vector(%o3));
(%o5)                                true
@end group
@group
(%i6) logic_equiv (x and y eq x, x implies y);
(%o6)                                true
@end group
@end example
@end deffn


@deffn {Function} dual_function (@var{expr})

@example
dual_function (f (x_1, ..., x_n)) := not f (not x_1, ..., not x_n).
@end example

Example:

@example
(%i1) load ("logic.mac")$
@group
(%i2) dual_function (x or y);
(%o2)                     not ((not x) or (not y))
@end group
@group
(%i3) demorgan (%);
(%o3)                               x and y
@end group
@end example
@end deffn


@deffn {Function} self_dual (@var{expr})
Returns @code{true} if @var{expr} is equivalent to
@code{dual_function (@var{expr})} and @code{false} otherwise.

Examples:

@example
(%i1) load ("logic.mac")$
@group
(%i2) self_dual (a);
(%o2)                               true
@end group
@group
(%i3) self_dual (not a);
(%o3)                               true
@end group
@group
(%i4) self_dual (a eq b);
(%o4)                               false
@end group
@end example
@end deffn


@deffn {Function} closed_under_f (@var{expr})
@code{closed_under_f (f (x_1, ..., x_n)} returns @code{true} if
@code{f (false, ..., false) = false} and @code{false} otherwise.

Examples:

@example
(%i1) load ("logic.mac")$
@group
(%i2) closed_under_f (x and y);
(%o2)                                true
@end group
@group
(%i3) closed_under_f (x or y);
(%o3)                                true
@end group
@end example
@end deffn


@deffn {Function} closed_under_t (@var{expr})
@code{closed_under_t (f (x_1, ..., x_n)} returns @code{true} if
@code{f (true, ..., true) = true} and @code{false} otherwise.

Examples:

@example
(%i1) load ("logic.mac")$
@group
(%i2) closed_under_t (x and y);
(%o2)                                true
@end group
@group
(%i3) closed_under_t (x or y);
(%o3)                                true
@end group
@end example
@end deffn


@deffn {Function} monotonic (@var{expr})
Returns @code{true} if characteristic vector of @var{expr} is monotonic, i.e.

@example
charvec : characteristic_vector(expr)
charvec[i] <= charvec[i+1],   i = 1, ..., n-1
@end example

where @code{a<=b := (a=b or (a=false and b=true))}.

Examples:

@example
(%i1) load ("logic.mac")$
@group
(%i2) monotonic (a or b);
(%o2)                                true
@end group
@group
(%i3) monotonic (a and b);
(%o3)                                true
@end group
@group
(%i4) monotonic (a implies b);
(%o4)                                false
@end group
@group
(%i5) monotonic (a xor b);
(%o5)                                false
@end group
@group
(%i6) characteristic_vector (a or b);
(%o6)                     [false, true, true, true]
@end group
@group
(%i7) characteristic_vector (a and b);
(%o7)                    [false, false, false, true]
@end group
@group
(%i8) characteristic_vector (a implies b);
(%o8)                     [true, true, false, true]
@end group
@group
(%i9) characteristic_vector (a xor b);
(%o9)                    [false, true, true, false]
@end group
@end example
@end deffn


@deffn {Function} linear (@var{expr})
Returns @code{true} if @code{zhegalkin_form(@var{expr})} is linear and
@code{false} otherwise.

Examples:

@example
(%i1) load ("logic.mac")$
@group
(%i2) linear (a or b);
(%o2)                                false
@end group
@group
(%i3) linear (a eq b);
(%o3)                                true
@end group
@group
(%i4) zhegalkin_form (a or b);
(%o4)              (a and b) xor a xor b
@end group
@group
(%i5) zhegalkin_form (a eq b);
(%o5)                 a xor b xor true
@end group
@end example

Linear functions are also known as counting or alternating functions.
@end deffn


@deffn {Function} functionally_complete (@var{expr_1}, ..., @var{expr_n})
Returns @code{true} if @var{expr_1}, ..., @var{expr_n} is a functionally
complete system and @code{false} otherwise.
The constants are essential (see the example below).

Examples:

@example
(%i1) load ("logic.mac")$
@group
(%i2) functionally_complete (x and y, x xor y);
(%o2)                                false
@end group
@group
(%i3) functionally_complete (x and y, x xor y, true);
(%o3)                                true
@end group
@group
(%i4) functionally_complete (x and y, x or y, not x);
(%o4)                                true
@end group
@end example
@end deffn


@deffn {Function} logic_basis (@var{expr_1}, ..., @var{expr_n})
Returns @code{true} if @var{expr_1}, ..., @var{expr_n} is a functionally
complete system without redundant elements and @code{false} otherwise.

Examples:

@example
(%i1) load ("logic.mac")$
@group
(%i2) logic_basis (x and y, x or y);
(%o2)                       false
@end group
@group
(%i3) logic_basis (x and y, x or y, not x);
(%o3)                       false
@end group
@group
(%i4) logic_basis (x and y, not x);
(%o4)                       true
@end group
@group
(%i5) logic_basis (x or y, not x);
(%o5)                       true
@end group
@group
(%i8) logic_basis (x and y, x xor y, true);
(%o8)                       true
@end group
@end example

All possible bases:

@example
(%i1) load ("logic.mac")$
(%i2) logic_functions : @{ not x, x nand y, x nor y,
                          x implies y, x and y, x or y,
                          x eq y, x xor y, true, false @}$
@group
(%i3) subset (powerset(logic_functions),
              lambda ([s], apply ('logic_basis, listify(s))));
(%o3) @{@{false, x eq y, x and y@}, @{false, x eq y, x or y@},
@{false, x implies y@}, @{true, x xor y, x and y@},
@{true, x xor y, x or y@}, @{not x, x implies y@},
@{not x, x and y@}, @{not x, x or y@},
@{x eq y, x xor y, x and y@}, @{x eq y, x xor y, x or y@},
@{x implies y, x xor y@}, @{x nand y@}, @{x nor y@}@}
@end group
@end example
@end deffn

@deffn {Function} logic_diff (@var{f}, @var{x})
Returns the logic derivative @math{df/dx} of @math{f} wrt @math{x}.

@example
@group
logic_diff (f (x_1, ..., x_k, ..., x_n),  x_k) :=
    f (x_1, ..., true, ..., x_n)  xor
        f (x_1, ..., false, ..., x_n)
@end group
@end example

Examples:

@example
(%i1) load ("logic.mac")$
@group
(%i2) logic_diff (a or b or c, a);
(%o2)          (b and c) xor b xor c xor true
@end group
@group
(%i3) logic_diff (a and b and c, a);
(%o3)                      b and c
@end group
@group
(%i4) logic_diff (a or (not a), a);
(%o4)                       false
@end group
@end example
@end deffn


@deffn {Function} boolean_form (@var{expr})

Returns the representation of @var{expr} in Boolean basis
@code{@{and, or, not@}}.

Examples:

@example
(%i1) load ("logic.mac")$
@group
(%i2) boolean_form (a implies b implies c);
(%o2)             (not ((not a) or b)) or c
@end group
@group
(%i3) demorgan (%);
(%o3)               ((not b) and a) or c
@end group
@group
(%i4) logic_equiv (boolean_form (a implies b implies c),
                   zhegalkin_form (a implies b implies c));
(%o4)                       true
@end group
@end example
@end deffn


@deffn {Function} demorgan (@var{expr})

Applies De Morgan's rules to @var{expr}:

@example
not (x_1 and ... and x_n) => (not x_1  or ...  or not x_n)
not (x_1  or ...  or x_n) => (not x_1 and ... and not x_n)
@end example

Example:

@example
(%i1) load ("logic.mac")$
@group
(%i2) demorgan (boolean_form (a nor b nor c));
(%o2)          (not a) and (not b) and (not c)
@end group
@end example
@end deffn


@deffn {Function} pdnf (@var{expr})

Returns the perfect disjunctive normal form of @var{expr}.

Example:

@example
(%i1) load ("logic.mac")$
@group
(%i2) pdnf (x implies y);
(%o2) (x and y) or ((not x) and y) or ((not x) and (not y))
@end group
@end example
@end deffn


@deffn {Function} pcnf (@var{expr})

Returns the perfect conjunctive normal form of @var{expr}.

Example:

@example
(%i1) load ("logic.mac")$
@group
(%i2) pcnf (x implies y);
(%o2)                   (not x) or y
@end group
@end example
@end deffn
