Acme-Test-LogicalEquivalence

 view release on metacpan or  search on metacpan

MANIFEST  view on Meta::CPAN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.008.
Changes
LICENSE
MANIFEST
META.json
META.yml
Makefile.PL
README
bin/test-logical-equivalence
lib/Acme/Test/LogicalEquivalence.pm
t/00-compile.t
t/00-report-prereqs.dd
t/00-report-prereqs.t
t/01-universal-laws.t
xt/author/clean-namespaces.t
xt/author/critic.t
xt/author/eol.t
xt/author/no-tabs.t
xt/author/pod-coverage.t

META.json  view on Meta::CPAN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
   "abstract" : "Test if expressions are logically equivalent",
   "author" : [
      "Charles McGarvey <chazmcgarvey@brokenzipper.com>"
   ],
   "dynamic_config" : 0,
   "generated_by" : "Dist::Zilla version 6.008, CPAN::Meta::Converter version 2.150005",
   "keywords" : [
      "test",
      "logic"
   ],
   "license" : [
      "perl_5"
   ],
   "meta-spec" : {
      "version" : 2
   },
   "name" : "Acme-Test-LogicalEquivalence",
   "no_index" : {

META.yml  view on Meta::CPAN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
---
abstract: 'Test if expressions are logically equivalent'
author:
  - 'Charles McGarvey <chazmcgarvey@brokenzipper.com>'
build_requires:
  ExtUtils::MakeMaker: '0'
  File::Spec: '0'
  IO::Handle: '0'
  IPC::Open3: '0'
  Test::More: '0'
  blib: '1.01'
configure_requires:
  ExtUtils::MakeMaker: '0'
dynamic_config: 0
generated_by: 'Dist::Zilla version 6.008, CPAN::Meta::Converter version 2.150005'
keywords:
  - test
  - logic
license: perl
meta-spec:
  version: '1.4'
name: Acme-Test-LogicalEquivalence
no_index:
  directory:
    - eg
    - share
    - shares

Makefile.PL  view on Meta::CPAN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.008.
use strict;
 
use 5.008;
 
 
my %WriteMakefileArgs = (
  "ABSTRACT" => "Test if expressions are logically equivalent",
  "AUTHOR" => "Charles McGarvey <chazmcgarvey\@brokenzipper.com>",
  "CONFIGURE_REQUIRES" => {
    "ExtUtils::MakeMaker" => 0
  },
  "DISTNAME" => "Acme-Test-LogicalEquivalence",
  "EXE_FILES" => [
    "bin/test-logical-equivalence"
  ],
  "LICENSE" => "perl",
  "MIN_PERL_VERSION" => "5.008",
  "NAME" => "Acme::Test::LogicalEquivalence",
  "PREREQ_PM" => {
    "Exporter" => 0,
    "Test::More" => 0,
    "namespace::clean" => 0,
    "strict" => 0,
    "warnings" => 0

README  view on Meta::CPAN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
NAME
 
    Acme::Test::LogicalEquivalence - Test if expressions are logically
    equivalent
 
VERSION
 
    version 0.001
 
SYNOPSIS
 
        use Test::More;
        use Acme::Test::LogicalEquivalence qw(is_logically_equivalent);
     
        # test two expressions with 2 variables using the special vars $a and $b
        is_logically_equivalent(2, sub { $a && $b }, sub { $b && $a });
     
        # same as above
        is_logically_equivalent(2, sub { $_[0] && $_[1] }, sub { $_[1] && $_[0] });
     
        # you can do as many vars as you like
        is_logically_equivalent(3, sub { $_[0] || ($_[1] && $_[2]) },
                                   sub { ($_[0] || $_[1]) && ($_[0] || $_[2]) });
     
        done_testing;
 
DESCRIPTION
 
    Some expressions are "logically equivalent" to other expressions, but
    it may not be easy to tell if one or both of the expressions are
    reasonably complicated. Or maybe you're like many other people and are
    too lazy to go through the effort... Either way, why not let your
    computer prove logical equivalence for you?
 
FUNCTIONS
 
 is_logically_equivalent
 
    Test logical equivalence of two subroutines.
 
        my $is_equivalent = is_logically_equivalent($numvars, &sub1, &sub2);
 
    This will execute both of the subroutines one or more times (depending
    on how many variables you specify) with different inputs. The
    subroutines shall be considered logically equivalent if, for all
    combinations of inputs, they both return the same thing.
 
    Returns true if the subroutines are logically equivalent, false
    otherwise.
 
SEE ALSO
 
      * What is logical equivalence? Start here:
 
AUTHOR
 
    Charles McGarvey <chazmcgarvey@brokenzipper.com>
 
COPYRIGHT AND LICENSE
 
    This software is copyright (c) 2016 by Charles McGarvey.

bin/test-logical-equivalence  view on Meta::CPAN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!perl
# ABSTRACT: Test if expressions are logically equivalent
# PODNAME: test-logical-equivalence
 
 
use 5.008;
use warnings FATAL => 'all';
use strict;
 
use Acme::Test::LogicalEquivalence qw(is_logically_equivalent);
 
sub usage {
    print <<END;
$0 EXPR1 EXPR2
Test if two simple expressions are logically equivalent.
 
Exactly two expressions must be given.
 
Example: $0 '\$a || \$b' '\$b || \$a'
Remember that you may need to escape special characters like "\$" from your shell.
END
    exit 1;
}
 
sub find_num_vars {

bin/test-logical-equivalence  view on Meta::CPAN

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
}
 
# convert $a-style vars to $_[0]-style to support more than just $a and $b
$expr1 =~ s/\$([a-z])/'$_['.(ord($1) - 97).']'/ge;
$expr2 =~ s/\$([a-z])/'$_['.(ord($1) - 97).']'/ge;
 
my $sub1 = eval "sub { $expr1 }" or die "Expression 1: $@\n";   ## no critic (ProhibitStringyEval)
my $sub2 = eval "sub { $expr2 }" or die "Expression 2: $@\n";   ## no critic (ProhibitStringyEval)
 
plan tests => (2 ** $num);
note "Testing for logical equivalence of two expressions with $num variable(s)...";
 
my $equivalence = is_logically_equivalent($num, $sub1, $sub2);
note $equivalence ? 'Logical equivalence proved!' : 'Bummer...';
 
__END__
 
=pod
 
=encoding UTF-8
 
=head1 NAME
 
test-logical-equivalence - Test if expressions are logically equivalent
 
=head1 VERSION
 
version 0.001
 
=head1 SYNOPSIS
 
    # be sure to escape $ and other special characters from your shell
    test-logical-equivalence '$a && $b' '$b && $a'
 
=head1 SEE ALSO
 
=over 4
 
=item *
 
L<Acme::Test::LogicalEquivalence>
 
=back

lib/Acme/Test/LogicalEquivalence.pm  view on Meta::CPAN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# ABSTRACT: Test if expressions are logically equivalent
# KEYWORDS: test logic
 
use 5.008;
use strict;
 
our $VERSION = '0.001'; # VERSION
 
use Exporter qw(import);
use namespace::clean -except => [qw(import)];
 
our @EXPORT_OK = qw(is_logically_equivalent);
 
 
sub is_logically_equivalent {
    my $numvars = shift;
    my $sub1 = shift;
    my $sub2 = shift;
 
    my $equivalence = 1;
 
    for (my $i = 0; $i < 2 ** $numvars; ++$i) {
        my @vars = split(//, substr(unpack("B32", pack('N', $i)), -$numvars));
 
        (local $a, local $b) = @vars;

lib/Acme/Test/LogicalEquivalence.pm  view on Meta::CPAN

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
1;
 
__END__
 
=pod
 
=encoding UTF-8
 
=head1 NAME
 
Acme::Test::LogicalEquivalence - Test if expressions are logically equivalent
 
=head1 VERSION
 
version 0.001
 
=head1 SYNOPSIS
 
    use Test::More;
    use Acme::Test::LogicalEquivalence qw(is_logically_equivalent);
 
    # test two expressions with 2 variables using the special vars $a and $b
    is_logically_equivalent(2, sub { $a && $b }, sub { $b && $a });
 
    # same as above
    is_logically_equivalent(2, sub { $_[0] && $_[1] }, sub { $_[1] && $_[0] });
 
    # you can do as many vars as you like
    is_logically_equivalent(3, sub { $_[0] || ($_[1] && $_[2]) },
                               sub { ($_[0] || $_[1]) && ($_[0] || $_[2]) });
 
    done_testing;
 
=head1 DESCRIPTION
 
Some expressions are "logically equivalent" to other expressions, but it may not be easy to tell if
one or both of the expressions are reasonably complicated. Or maybe you're like many other people
and are too lazy to go through the effort... Either way, why not let your computer prove logical
equivalence for you?
 
=head1 FUNCTIONS
 
=head2 is_logically_equivalent
 
Test logical equivalence of two subroutines.
 
    my $is_equivalent = is_logically_equivalent($numvars, &sub1, &sub2);
 
This will execute both of the subroutines one or more times (depending on how many variables you
specify) with different inputs. The subroutines shall be considered logically equivalent if, for all
combinations of inputs, they both return the same thing.
 
Returns true if the subroutines are logically equivalent, false otherwise.
 
=head1 SEE ALSO
 
=over 4
 
=item *
 
What is logical equivalence? Start here: L<https://en.wikipedia.org/wiki/Logical_equivalence>
 
=back
 
=head1 AUTHOR
 
Charles McGarvey <chazmcgarvey@brokenzipper.com>
 
=head1 COPYRIGHT AND LICENSE
 
This software is copyright (c) 2016 by Charles McGarvey.

t/00-compile.t  view on Meta::CPAN

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 
plan tests => 2 + ($ENV{AUTHOR_TESTING} ? 1 : 0);
 
my @module_files = (
    'Acme/Test/LogicalEquivalence.pm'
);
 
my @scripts = (
    'bin/test-logical-equivalence'
);
 
# no fake home requested
 
my @switches = (
    -d 'blib' ? '-Mblib' : '-Ilib',
);
 

t/01-universal-laws.t  view on Meta::CPAN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#!perl
 
use strict;
 
 
use Acme::Test::LogicalEquivalence qw(is_logically_equivalent);
 
note "Let's see if the universe still makes sense...";
 
note 'Identity laws';
is_logically_equivalent 1,
    sub { $a && 1 },
    sub { $a };
is_logically_equivalent 1,
    sub { $a || 0 },
    sub { $a };
 
note 'Domination laws';
is_logically_equivalent 1,
    sub { $a || 1 },
    sub { 1 };
is_logically_equivalent 1,
    sub { $a && 0 },
    sub { 0 };
 
note 'Idempotent laws';
is_logically_equivalent 1,
    sub { $a && $a },
    sub { $a };
is_logically_equivalent 1,
    sub { $a || $a },
    sub { $a };
 
note 'Double negation law';
is_logically_equivalent 1,
    sub { !!$a },
    sub { $a };
 
note 'Commutative laws';
is_logically_equivalent 2,
    sub { $a || $b },
    sub { $b || $a };
is_logically_equivalent 2,
    sub { $a && $b },
    sub { $b && $a };
 
note 'Associative laws';
is_logically_equivalent 3,
    sub { ($_[0] || $_[1]) || $_[2] },
    sub { $_[0] || ($_[1] || $_[2]) };
is_logically_equivalent 3,
    sub { ($_[0] && $_[1]) && $_[2] },
    sub { $_[0] && ($_[1] && $_[2]) };
 
note 'Distributive laws';
is_logically_equivalent 3,
    sub { $_[0] || ($_[1] && $_[2]) },
    sub { ($_[0] || $_[1]) && ($_[0] || $_[2]) };
is_logically_equivalent 3,
    sub { $_[0] && ($_[1] || $_[2]) },
    sub { ($_[0] && $_[1]) || ($_[0] && $_[2]) };
 
note 'De Morgan\'s laws';
is_logically_equivalent 2,
    sub { !($a && $b) },
    sub { !$a || !$b };
is_logically_equivalent 2,
    sub { !($a || $b) },
    sub { !$a && !$b };
 
note 'Absorption laws';
is_logically_equivalent 2,
    sub { $a || ($a && $b) },
    sub { $a };
is_logically_equivalent 2,
    sub { $a && ($a || $b) },
    sub { $a };
 
note 'Negation laws';
is_logically_equivalent 1,
    sub { $a || !$a },
    sub { 1 };
is_logically_equivalent 1,
    sub { $a && !$a },
    sub { 0 };
 
done_testing;

xt/author/eol.t  view on Meta::CPAN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
use strict;
 
# this test was generated with Dist::Zilla::Plugin::Test::EOL 0.19
 
use Test::More 0.88;
 
my @files = (
    'bin/test-logical-equivalence',
    'lib/Acme/Test/LogicalEquivalence.pm',
    't/00-compile.t',
    't/00-report-prereqs.dd',
    't/00-report-prereqs.t',
    't/01-universal-laws.t',
    'xt/author/clean-namespaces.t',
    'xt/author/critic.t',
    'xt/author/eol.t',
    'xt/author/no-tabs.t',
    'xt/author/pod-coverage.t',

xt/author/no-tabs.t  view on Meta::CPAN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
use strict;
 
# this test was generated with Dist::Zilla::Plugin::Test::NoTabs 0.15
 
use Test::More 0.88;
 
my @files = (
    'bin/test-logical-equivalence',
    'lib/Acme/Test/LogicalEquivalence.pm',
    't/00-compile.t',
    't/00-report-prereqs.dd',
    't/00-report-prereqs.t',
    't/01-universal-laws.t',
    'xt/author/clean-namespaces.t',
    'xt/author/critic.t',
    'xt/author/eol.t',
    'xt/author/no-tabs.t',
    'xt/author/pod-coverage.t',



( run in 0.404 second using v1.01-cache-2.11-cpan-3cd7ad12f66 )