Algorithm-SAT-Backtracking

 view release on metacpan or  search on metacpan

lib/Algorithm/SAT/Expression.pm  view on Meta::CPAN

    # This first clause is the 'or' portion. "One of them must be true."
    my $self     = shift;
    my @literals = @_;
    push( @{ $self->{_expr} }, \@_ );
    $self->_ensure(@literals);

    # Then, we generate clauses such that "only one of them is true".
    for ( my $i = 0; $i <= $#literals; $i++ ) {
        for ( my $j = $i + 1; $j <= $#literals; $j++ ) {
            push(
                @{ $self->{_expr} },
                [   $self->negate_literal( $literals[$i] ),
                    $self->negate_literal( $literals[$j] )
                ]
            );
        }
    }
    return $self;
}

# ### and
# Add each of the provided literals into their own clause in the expression.
sub and {
    my $self = shift;
    $self->_ensure(@_);
    push( @{ $self->{_expr} }, [$_] ) for @_;
    return $self;
}

# ### solve
# Solve this expression with the backtrack solver. Lazy-loads the solver.
sub solve {
    return $_[0]->{_implementation}
        ->new->solve( $_[0]->{_variables}, $_[0]->{_expr} );
}

# ### _ensure
# Private method that ensures that a particular literal is marked as being in
# the expression.
sub _ensure {
    my $self = shift;
    do {
        $self->{_literals}->{$_} = 1;
        push( @{ $self->{_variables} }, $_ );
        }
        for grep { !$self->{_literals}->{$_} }
        map { substr( $_, 0, 1 ) eq "-" ? substr( $_, 1 ) : $_ } @_;
}

sub negate_literal {
    my ( undef, $var ) = @_;

    return ( substr( $var, 0, 1 ) eq "-" )
        ? substr( $var, 1 )
        : '-' . $var;
}

1;
__END__

=encoding utf-8

=head1 NAME

Algorithm::SAT::Expression - A class that represent an expression for L<Algorithm::SAT::Backtracking>

=head1 SYNOPSIS


    # with the default implementation (Algorithm::SAT::Backtracking)

    use Algorithm::SAT::Expression;
    my $exp = Algorithm::SAT::Expression->new;
    $exp->or( 'blue',  'green',  '-yellow' );
    $exp->or( '-blue', '-green', 'yellow' );
    $exp->or( 'pink',  'purple', 'green', 'blue', '-yellow' );
    my $model = $exp->solve();
    # $model  now is { 'yellow' => 1, 'green' => 1 }

    # using a specific implementation

    use Algorithm::SAT::Expression;
    my $exp = Algorithm::SAT::Expression->new->with("Algorithm::SAT::Backtracking::DPLL");
    $exp->or( 'blue',  'green',  '-yellow' );
    $exp->or( '-blue', '-green', 'yellow' );
    $exp->or( 'pink',  'purple', 'green', 'blue', '-yellow' );
    my $model = $exp->solve();
    # $model  now is { 'yellow' => 1, 'green' => 1 }


=head1 DESCRIPTION

Algorithm::SAT::Expression is a class that helps to build an expression to solve with L<Algorithm::SAT::Backtracking>.

Have a look also at the tests file for an example of usage.

=head1 METHODS

=head2 and()

Takes the inputs and build an B<AND> expression for it

=head2 or()

Takes the inputs and build an B<OR> expression for it

=head2 xor()

Takes the inputs and build an B<XOR> expression for it

=head2 solve()

Uses L<Algorithm::SAT::Backtracking> to return a model that satisfies the expression.
The model it's a hash containing in the keys the literal and as the value if their presence represented by a 1 and the absence by a 0.

Note: if you use the Ordered implementation, the result is a L<Hash::Ordered>.

=head2 with()

Allow to change the SAT Algorithm used to solve the given expression



( run in 0.794 second using v1.01-cache-2.11-cpan-ceb78f64989 )