Acme-Test-LogicalEquivalence

 view release on metacpan or  search on metacpan

MANIFEST  view on Meta::CPAN

# 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

{
   "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" : {
      "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
      "version" : 2
   },
   "name" : "Acme-Test-LogicalEquivalence",
   "no_index" : {

META.yml  view on Meta::CPAN

---
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:
  url: http://module-build.sourceforge.net/META-spec-v1.4.html
  version: '1.4'
name: Acme-Test-LogicalEquivalence
no_index:
  directory:
    - eg
    - share
    - shares

Makefile.PL  view on Meta::CPAN

# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.008.
use strict;
use warnings;

use 5.008;

use ExtUtils::MakeMaker;

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

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:
      https://en.wikipedia.org/wiki/Logical_equivalence

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

#!perl
# ABSTRACT: Test if expressions are logically equivalent
# PODNAME: test-logical-equivalence


use 5.008;
use warnings FATAL => 'all';
use strict;

use Test::More;
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

}

# 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

package Acme::Test::LogicalEquivalence;
# ABSTRACT: Test if expressions are logically equivalent
# KEYWORDS: test logic

use 5.008;
use warnings;
use strict;

our $VERSION = '0.001'; # VERSION

use Exporter qw(import);
use Test::More;
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

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


use Test::More;

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',
);

use File::Spec;
use IPC::Open3;

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

#!perl

use warnings;
use strict;

use Test::More;

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

use strict;
use warnings;

# this test was generated with Dist::Zilla::Plugin::Test::EOL 0.19

use Test::More 0.88;
use Test::EOL;

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

use strict;
use warnings;

# this test was generated with Dist::Zilla::Plugin::Test::NoTabs 0.15

use Test::More 0.88;
use Test::NoTabs;

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.317 second using v1.01-cache-2.11-cpan-26ccb49234f )