• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

t/H25-May-2000-2,4861,907

Logic.pmH A D25-May-200034.9 KiB1,089376

MANIFESTH A D25-May-200047 65

Makefile.PLH A D25-May-2000748 2116

READMEH A D25-May-200018.4 KiB534369

README

1=head1 NAME
2
3Math::Logic - Provides pure 2, 3 or multi-value logic.
4
5=head1 SYNOPSIS
6
7    use Math::Logic qw( $TRUE $FALSE $UNDEF $STR_TRUE $STR_FALSE $STR_UNDEF ) ;
8                    #       1      0     -1     'TRUE'    'FALSE'    'UNDEF'
9
10    use Math::Logic ':NUM' ; # $TRUE $FALSE $UNDEF -- what you normally want
11
12    use Math::Logic ':ALL' ; # All the constants
13
14    use Math::Logic ':STR' ; # $STR_TRUE $STR_FALSE $STR_UNDEF
15
16    # 2-degree logic
17    my $true  = Math::Logic->new( -value => $TRUE,  -degree => 2 ) ;
18    my $false = Math::Logic->new( -value => $FALSE, -degree => 2 ) ;
19    my $x     = Math::Logic->new_from_string( 'TRUE,2' ) ;
20
21    print "true" if $true ;
22
23    # 3-degree logic (non-propagating)
24    my $true  = Math::Logic->new( -value => $TRUE,  -degree => 3 ) ;
25    my $false = Math::Logic->new( -value => $FALSE, -degree => 3 ) ;
26    my $undef = Math::Logic->new( -value => $UNDEF, -degree => 3 ) ;
27    my $x     = Math::Logic->new_from_string( 'FALSE,3' ) ;
28
29    print "true" if ( $true | $undef ) == $TRUE ;
30
31    # 3-degree logic (propagating)
32    my $true  = Math::Logic->new( -value => $TRUE,  -degree => 3, -propagate => 1 ) ;
33    my $false = Math::Logic->new( -value => $FALSE, -degree => 3, -propagate => 1 ) ;
34    my $undef = Math::Logic->new( -value => $UNDEF, -degree => 3, -propagate => 1 ) ;
35    my $x     = Math::Logic->new_from_string( '( UNDEF, 3, -propagate )' ) ;
36
37    print "undef" if ( $true | $undef ) == $UNDEF ;
38
39    # multi-degree logic
40    my $True   = 100 ; # Define our own true
41    my $False  = $FALSE ;
42    my $true   = Math::Logic->new( -value => $True,  -degree => $True ) ;
43    my $very   = Math::Logic->new( -value => 67,     -degree => $True ) ;
44    my $fairly = Math::Logic->new( -value => 33,     -degree => $True ) ;
45    my $false  = Math::Logic->new( -value => $False, -degree => $True ) ;
46    my $x      = Math::Logic->new_from_string( "25,$True" ) ;
47
48    print "maybe" if ( $very | $fairly ) > 50 ;
49
50    # We can have arbitrarily complex expressions; the result is a Math::Logic
51    # object; all arguments must be Math::Logic objects or things which can be
52    # promoted into such and must all be compatible. The outcome depends on
53    # which kind of logic is being used.
54    my $xor = ( $x | $y ) & ( ! ( $x & $y ) ) ;
55    # This is identical to:
56    my $xor = $x ^ $y ;
57
58
59=head1 DESCRIPTION
60
61Perl's built-in logical operators, C<and>, C<or>, C<xor> and C<not> support
622-value logic. This means that they always produce a result which is either
63true or false. In fact perl sometimes returns 0 and sometimes returns undef
64for false depending on the operator and the order of the arguments. For "true"
65Perl generally returns the first value that evaluated to true which turns out
66to be extremely useful in practice. Given the choice Perl's built-in logical
67operators are to be preferred -- but when you really want pure 2-degree logic
68or 3-degree logic or multi-degree logic they are available through this module.
69
70The only 2-degree logic values are 1 (TRUE) and 0 (FALSE).
71
72The only 3-degree logic values are 1 (TRUE), 0 (FALSE) and -1 (UNDEF). Note
73that UNDEF is -1 I<not> C<undef>!
74
75The only multi-degree logic values are 0 (FALSE)..C<-degree> -- the value of
76TRUE is equal to the degree, usually 100.
77
78The C<-degree> is the maximum value (except for 2 and 3-degree logic); i.e.
79logic of I<n>-degree is I<n+1>-value logic, e.g. 100-degree logic has 101
80values, 0..100.
81
82Although some useful constants may be exported, this is an object module and
83the results of logical comparisons are Math::Logic objects.
84
85=head2 2-degree logic
86
872-degree logic has one simple truth table for each logical operator.
88
89        Perl Logic      Perl Logic     Perl Logic
90    A B and  and    A B or   or    A B xor  xor
91    - - ---  ---    - - --   --    - - ---  ---
92    F F  F    F     F F  F    F    F F  F    F
93    T T  T    T     T T  T    T    T T  F    F
94    T F  F    F     T F  T    T    T F  T    T
95    F T  F    F     F T  T    T    F T  T    T
96
97      Perl Logic
98    A not  not
99    - ---  ---
100    F  T    T
101    T  F    F
102
103In the above tables when dealing with Perl's built-in logic T and F are any
104true and any false value respectively; with Math::Logic they are objects whose
105values are 1 and 0 respectively. Note that whilst Perl may return 0 or undef
106for false and any other value for true, Math::Logic returns an object whose
107value is either 0 (FALSE) or 1 (TRUE) only.
108
109    my $true   = Math::Logic->new( -value => $TRUE,  -degree => 2 ) ;
110    my $false  = Math::Logic->new( -value => $FALSE, -degree => 2 ) ;
111
112    my $result = $true & $false ; # my $result = $true->and( $false ) ;
113
114    print $result if $result == $FALSE ;
115
116=head2 3-degree logic
117
1183-degree logic has two different truth tables for "and" and "or"; this module
119supports both. In the Perl column F means false or undefined; and T, F and U
120under Math::Logic are objects with values 1 (TRUE), 0 (FALSE) and -1 (UNDEF)
121respectively. The + signifies propagating nulls (UNDEFs).
122
123        Perl  Logic        Perl  Logic         Perl  Logic
124    A B and  and+ and    A B or or+  or    A B xor  xor+ xor(same)
125    - - ---  ---  ---    - - -- --   --    - - ---  ---  ---
126    U U  F    U    U     U U  F  U    U    U U  F    U    U
127    U F  F    U    F     U F  F  U    U    U F  F    U    U
128    F U  F    U    F     F U  F  U    U    F U  F    U    U
129    F F  F    F    F     F F  F  F    F    F F  F    F    F
130    U T  F    U    U     U T  T  U    T    U T  T    U    U
131    T U  F    U    U     T U  T  U    T    T U  T    U    U
132    T T  T    T    T     T T  T  T    T    T T  F    F    F
133    T F  F    F    F     T F  T  T    T    T F  T    T    T
134    F T  F    F    F     F T  T  T    T    F T  T    T    T
135
136      Perl  Logic
137    A not  not+ not(same)
138    - ---  ---  ---
139    U  T    U    U
140    U  T    U    U
141    F  T    T    T
142    T  F    F    F
143
144    # 3-degree logic (non-propagating)
145    my $true   = Math::Logic->new( -value => $TRUE,  -degree => 3 ) ;
146    my $false  = Math::Logic->new( -value => $FALSE, -degree => 3 ) ;
147    my $undef  = Math::Logic->new( -value => $UNDEF, -degree => 3 ) ;
148
149    my $result = $undef & $false ; # my $result = $undef->and( $false ) ;
150
151    print $result if $result == $FALSE ;
152
153    # 3-degree logic (propagating)
154    my $true   = Math::Logic->new( -value => $TRUE,  -degree => 3, -propagate => 1 ) ;
155    my $false  = Math::Logic->new( -value => $FALSE, -degree => 3, -propagate => 1 ) ;
156    my $undef  = Math::Logic->new( -value => $UNDEF, -degree => 3, -propagate => 1 ) ;
157
158    my $result = $undef & $false ; # my $result = $undef->and( $false ) ;
159
160    print $result if $result == $UNDEF ;
161
162=head2 multi-degree logic
163
164This is used in `fuzzy' logic. Typically we set the C<-degree> to 100
165representing 100% likely, i.e. true; 0 represents 0% likely, i.e. false, and
166any integer in-between is a probability.
167
168The truth tables for multi-degree logic work like this:
169
170    and     lowest  value is the result;
171    or      highest value is the result;
172    xor     by truth table xor(a,b) == and(or(a,b),not(and(a,b)))
173    not     degree minus the value is the result.
174
175               Logic
176     A   B  and  or xor
177    --- --- --- --- ---
178      0   0   0   0   0
179      0 100   0 100 100
180    100   0   0 100 100
181    100 100 100 100   0
182      0  33   0  33  33
183     33   0   0  33  33
184     33 100  33 100  67
185     33  33  33  33  33
186    100  33  33 100  67
187      0  67   0  67  67
188     67   0   0  67  67
189     67 100  67 100  33
190     67  67  67  67  33
191    100  67  67 100  33
192     33  67  33  67  67
193     67  33  33  67  67
194
195     A  not
196    --- ---
197      0 100
198     33  67
199     67  33
200    100   0
201
202    # multi-degree logic
203    my $True   = 100 ; # Define our own TRUE and FALSE
204    my $False  = $FALSE ;
205    $true      = Math::Logic->new( -value => $True,  -degree => $True ) ;
206    $very      = Math::Logic->new( -value => 67,     -degree => $True ) ;
207    $fairly    = Math::Logic->new( -value => 33,     -degree => $True ) ;
208    $false     = Math::Logic->new( -value => $False, -degree => $True ) ;
209
210    my $result = $fairly & $very ; # my $result = $fairly->and( $very ) ;
211
212    print $result if $result == $fairly ;
213
214=head2 Public methods
215
216    new             class   object (also used for assignment)
217    new_from_string class   object
218    value                   object
219    degree                  object
220    propagate               object
221    incompatible            object
222    compatible              object (deprecated)
223    as_string               object
224    and                     object (same as &)
225    or                      object (same as |)
226    xor                     object (same as ^)
227    not                     object (same as !)
228    ""                      object (see as_string)
229    0+                      object (automatically handled)
230    <=>                     object (comparisons)
231    &                       object (logical and)
232    |                       object (logical or)
233    ^                       object (logical xor)
234    !                       object (logical not)
235
236=head2 new (class and object method)
237
238    my $x = Math::Logic->new ;
239
240    my $y = Math::Logic->new( -value => $FALSE, -degree => 3, -propagate => 0 );
241
242    my $a = $x->new ;
243
244    my $b = $y->new( -value => $TRUE ) ;
245
246This creates new Math::Logic objects. C<new> should never fail because it will
247munge any arguments into something `sensible'; in particular if the value is
248set to -1 (UNDEF) for 2 or multi-degree logic it is silently converted to 0
249(FALSE). In all other cases anything that is true in Perl is converted to 1
250(TRUE) and everything else to 0 (FALSE).
251
252
253If used as an object method, e.g. for assignment then the settings are those
254of the original object unless overridden. If used as a class method with no
255arguments then default values are used.
256
257C<-degree> an integer indicating the number of possible truth values;
258typically set to 2, 3 or 100 (to represent percentages). Minimum value is 2.
259
260C<-propagate> a true/false integer indicating whether NULLs (UNDEF) should
261propagate; only applicable for 3-degree logic where it influences which truth
262table is used.
263
264C<-value> an integer representing the truth value. For 2-degree logic only 1
265and 0 are valid (TRUE and FALSE); for 3-degree logic 1, 0, and -1 are valid
266(TRUE, FALSE and UNDEF); for multi-degree logic any positive integer less than
267or equal to the C<-degree> is valid.
268
269=head2 new_from_string (class and object method)
270
271    my $x = Math::Logic->new_from_string( '1,2' ) ;
272    my $y = Math::Logic->new_from_string( 'TRUE,3,-propagate' ) ;
273    my $z = Math::Logic->new_from_string( '( FALSE, 3, -propagate )' ) ;
274    my $m = Math::Logic->new_from_string( '33,100' ) ;
275    my $n = Math::Logic->new_from_string( '67%,100' ) ;
276
277This creates new Math::Logic objects. The string B<must> include the first two
278values, which are C<-value> and C<-degree> respectively.
279
280True  values can be expressed as  1, T or any word beginning with T, e.g.
281TRUE or -true; the pattern is /^-?[tT]/.
282False values can be expressed as  0, F or any word beginning with F, e.g.
283FALSE or -false; the pattern is /^-?[fF]/.
284Undef values can be expressed as -1, U or any word beginning with U, e.g.
285UNDEF or -undef; the pattern is /^-?[uU]/.
286Propagate is set to true by adding a third parameter matching /^-?[tTpP1]/,
287e.g. -propagate. To set propagate to false either don't include a third
288parameter or include it as 0 (zero).
289
290=head2 value (object method)
291
292    print $x->value ;
293    print $x ;
294
295This returns the numeric value of the object. For 2-degree logic this will
296always be 1 or 0; for 3-degree logic the value will be 1, 0 or -1; for
297multi-degree logic the value will be a positive integer <= C<-degree>.
298
299=head2 degree (object method)
300
301    print $x->degree ;
302
303This returns the degree of the object, i.e. the number of possible truth
304values the object may hold; it is always 2 or more.
305
306=head2 propagate (object method)
307
308    print $x->propagate ;
309
310This returns whether or not the object propagates NULLs (UNDEF). Objects using
3112 or multi-degree logic always return FALSE; 3-degree logic objects may return
312TRUE or FALSE.
313
314=head2 incompatible (object method)
315
316    print $x & $y unless $x->incompatible( $y ) ;
317
318Returns FALSE if the objects are compatible; returns an error string if
319incompatible (which Perl treats as TRUE), e.g.:
320
321    $x = Math::Logic->new_from_string('1,2') ;
322    $y = Math::Logic->new_from_string('0,3') ;
323    # The above are incompatible because the first uses 2-degree logic and the
324    # second uses 3-degree logic.
325    print $x->incompatible( $y ) if $x->incompatible( $y ) ;
326    # This will print something like:
327    Math::Logic(2,0) and Math::Logic(3,0) are incompatible at ./logic.t line 2102
328    # The first number given is the degree and the second the propagate setting
329
330Objects are compatible if they have the same C<-degree> and in the case of
3313-degree logic the same C<-propagate>. Logical operators will only work on
332compatible objects, there is no type-coersion (but see typecasting later).
333
334=head2 compatible DEPRECATED (object method)
335
336    print $x->compatible( $y ) ;
337
338Returns TRUE or FALSE depending on whether the two objects are compatible.
339Objects are compatible if they have the same C<-degree> and in the case of
3403-degree logic the same C<-propagate>. Logical operators will only work on
341compatible objects, there is no type-coersion (but see typecasting later).
342
343=head2 as_string and "" (object method)
344                                    # output:
345    print $x->as_string ;           # TRUE
346    print $x->as_string( 1 ) ;      # (TRUE,2)
347    print $x->as_string( -full ) ;  # (TRUE,2)
348
349    print $x ;                      # TRUE
350    print $x->value ;               # 1
351
352    print $m ;                      # 33
353    print $m->value ;               # 33
354    print $m->as_string( 1 ) ;      # (33%,100)
355
356Usually you won't have to bother using C<as_string> since Perl will invoke it
357for you as necessary; however if you want a string that can be saved, (perhaps
358to be read in using C<new_from_string> later), you can pass an argument to
359C<as_string>.
360
361=head2 and and & (object method)
362
363    print "true" if ( $y & $z ) == $TRUE ;
364    print "yes"  if $y & 1 ;
365    print "yes"  if $TRUE & $y ;
366
367    $r = $y & $z ; # Creates a new Math::Logic object with the resultant truth value
368
369    print "true" if $y->and( $z ) == $TRUE ;
370
371Applies logical and to two objects. The truth table used depends on the
372object's C<-degree> (and in the case of 3-degree logic on the C<-propagate>).
373(See the truth tables above.)
374
375=head2 or and | (object method)
376
377    print "true" if ( $y | $z ) == $TRUE ;
378    print "yes"  if $y | 1 ;
379    print "yes"  if $TRUE | $y ;
380
381    $r = $y | $z ; # Creates a new Math::Logic object with the resultant truth value
382
383    print "true" if $y->or( $z ) == $TRUE ;
384
385Applies logical or to two objects. The truth table used depends on the
386object's C<-degree> (and in the case of 3-degree logic on the C<-propagate>).
387(See the truth tables above.)
388
389=head2 xor and ^ (object method)
390
391    print "true" if ( $y ^ $z ) == $TRUE ;
392    print "yes"  if $y ^ 0 ;
393    print "yes"  if $TRUE ^ $y ;
394
395    $r = $y ^ $z ; # Creates a new Math::Logic object with the resultant truth value
396
397    print "true" if $y->xor( $z ) == $TRUE ;
398
399Applies logical xor to two objects. The truth table used depends on the
400object's C<-degree>. (See the truth tables above.)
401
402=head2 not and ! (object method)
403
404    print "true" if ! $y == $TRUE ;
405
406    $r = ! $y ; # Creates a new Math::Logic object with the resultant truth value
407
408    print "true" if $y->not == $TRUE ;
409
410Applies logical not to the object. The truth table used depends on the
411object's C<-degree>. (See the truth tables above.)
412
413=head2 comparisons and <=> (object method)
414
415All the standard (numeric) comparison operators may be applied to Math::Logic
416objects, i.e. <, <=, >, =>, ==, != and <=>.
417
418=head2 typecasting
419
420The only typecasting that appears to make sense is between 2 and 3-degree
421logic. There is no direct support for it but it can be achieved thus:
422
423    my $x = Math::Logic->new_from_string( '1,2' ) ;  # TRUE  2-degree
424    my $y = Math::Logic->new_from_string( '0,3' ) ;  # FALSE 3-degree
425    my $z = Math::Logic->new_from_string( '-1,3' ) ; # UNDEF 3-degree
426
427    $x3 = $x->new( -degree => 3 ) ;
428    $y2 = $y->new( -degree => 2 ) ;
429    $z2 = $y->new( -degree => 2 ) ; # UNDEF converted silently to FALSE
430
431=head1 BUGS
432
433Multi-degree logic has a minimum degree of 4, i.e. 5-value, 0..4.
434
435If you use & on two incompatible Math::Logic objects perl dies; I believe that
436this is due to a problem with overload: it does not occur with perl 5.6.0.
437
438=head1 CHANGES
439
4402000/05/25
441
442No changes; just corrected an error in the tarball that meant the test would
443fail in some cases due to permissions problem.
444
4452000/05/22
446
447Dropped use of readonly pragma.
448
449
4502000/04/26
451
452Deleted quite a lot of internal error checks to improve speed.
453
454Class is now inheritable.
455
456
4572000/04/15
458
459Have switched constants to readonly scalars, i.e. $TRUE instead of TRUE etc.
460This makes them easier to use for certain things, e.g. string interpolation
461and as array indexes or hash keys. The (now deprecated) constants still work
462but you are recommended to use the constant scalars instead. You will need
463to install C<readonly.pm> which should be available from wherever you got
464Math::Logic.
465
466The bugs with overload do not occur with perl 5.6.0. Added two tests which are
467run if perl's version is > 5.005.
468
469
4702000/02/27
471
472Numerous minor documentation changes to clarify terminology.
473
474Two bugs noted.
475
476More tests added.
477
478
4792000/02/23
480
481Corrected multi-degree xor to match the truth table equivalence, i.e.
482
483    xor(a,b) == and(or(a,b),not(and(a,b)))
484
485which can be expressed in Math::Logic as
486
487    $a->xor( $b ) == $a->or( $b )->and( $a->and( $b )->not )
488
489or as
490
491    $a ^ $b == ( $a | $b ) & ( ! ( $a & $b ) )
492
493
4942000/02/22
495
496Minor correction to _croak so that error messages don't list filename and line
497twice; plus other minor cleanups to improve error output.
498
499Changed the way new_from_string handles string truth values; numeric truth
500values operate as before.
501
502
503
5042000/02/21
505
506Added incompatible method and now deprecate compatible method; this provides
507better error messages; updated test script.
508
509
5102000/02/20
511
512Minor documentation fixes. Also eliminated a warning that occurred under
5135.005.
514
515
5162000/02/19
517
518First version. Ideas taken from my Math::Logic3 and (unpublished) Math::Fuzzy;
519this module is intended to supercede both.
520
521=head1 AUTHOR
522
523Mark Summerfield. I can be contacted as <summer@perlpress.com> -
524please include the word 'logic' in the subject line.
525
526=head1 COPYRIGHT
527
528Copyright (c) Mark Summerfield 2000. All Rights Reserved.
529
530This module may be used/distributed/modified under the LGPL.
531
532=cut
533
534