Algorithm-CP-IZ
view release on metacpan or search on metacpan
lib/Algorithm/CP/IZ.pm view on Meta::CPAN
}
}
if ($params->{Criteria}) {
$criteria_func = $params->{Criteria};
}
if ($params->{MaxFail}) {
$max_fail = int($params->{MaxFail});
}
if ($params->{ValueSelectors}) {
$value_selectors = $params->{ValueSelectors};
}
if ($params->{MaxFailFunc}) {
$max_fail_func = $params->{MaxFailFunc};
}
if ($params->{NoGoodSet}) {
$ngs = $params->{NoGoodSet};
}
if ($params->{Notify}) {
$notify = $params->{Notify};
unless (ref $notify eq 'Algorithm::CP::IZ::SearchNotify') {
$notify = Algorithm::CP::IZ::SearchNotify->new($notify);
}
$notify->set_var_array($var_array);
}
my $is_search35 = $value_selectors || $max_fail_func || $ngs || $notify;
if ($is_search35) {
unless ($value_selectors) {
if ($criteria_func) {
$Algorithm::CP::IZ::CriteriaValueSelector::CriteriaFunction = $criteria_func;
$value_selectors = [
map {
$self->create_value_selector_simple("Algorithm::CP::IZ::CriteriaValueSelector")
} (0..scalar(@$var_array)-1)];
}
else {
$value_selectors = [
map {
$self->get_value_selector(&CS_VALUE_SELECTOR_MIN_TO_MAX)
} (0..scalar(@$var_array)-1)];
}
}
my $i = 0;
for my $v (@$array) {
my $vs = $value_selectors->[$i];
$vs->prepare($i);
$i++;
}
if ($max_fail_func) {
return Algorithm::CP::IZ::cs_searchValueSelectorRestartNG(
$array,
$value_selectors,
$find_free_var_id,
$find_free_var_func,
$max_fail_func,
$max_fail,
defined($ngs) ? $ngs->{_ngs} : 0,
defined($notify) ? $notify->{_ptr} : 0);
}
else {
return Algorithm::CP::IZ::cs_searchValueSelectorFail(
$array,
$value_selectors,
$find_free_var_id,
$find_free_var_func,
$max_fail,
defined($notify) ? $notify->{_ptr} : 0);
}
}
else {
if ($criteria_func) {
return Algorithm::CP::IZ::cs_searchCriteria($array,
$find_free_var_id,
$find_free_var_func,
$criteria_func,
$max_fail);
}
else {
return Algorithm::CP::IZ::cs_search($array,
$find_free_var_id,
$find_free_var_func,
$max_fail);
}
}
if ($criteria_func) {
return Algorithm::CP::IZ::cs_searchCriteria($array,
$find_free_var_id,
$find_free_var_func,
$criteria_func,
$max_fail);
}
else {
return Algorithm::CP::IZ::cs_search($array,
$find_free_var_id,
$find_free_var_func,
$max_fail);
}
}
sub _validate_find_all_params {
my $params = shift;
return 1 unless (defined($params));
return 0 unless (ref $params eq 'HASH');
my %checker = (
FindFreeVar => sub {
my $x = shift;
if (ref $x) {
validate([$x], ["C"], "find_all: FindFreeVar must be a number or coderef");
lib/Algorithm/CP/IZ.pm view on Meta::CPAN
@$val_array = map { int($_) } @$val_array;
$index = ref $index ? $index : $self->_const_var(int($index));
my $parray = $self->_create_registered_int_array($val_array);
my $ptr = Algorithm::CP::IZ::cs_Element($$index,
$$parray, scalar(@$val_array));
my $ret = Algorithm::CP::IZ::Int->new($ptr);
$self->_register_variable($ret);
return $ret;
}
sub VarElement {
my $self = shift;
my ($index, $var_array) = @_;
validate([scalar @_, $index, $var_array],
[sub { shift == 2 }, "V", "vA1"],
"Usage: VarElement(index_var, [value_vars])");
@$var_array = map { ref $_ ? $_ : $self->_const_var(int($_)) } @$var_array;
$index = ref $index ? $index : $self->_const_var(int($index));
my $parray = $self->_create_registered_var_array($var_array);
my $ptr = Algorithm::CP::IZ::cs_VarElement($$index,
$$parray, scalar(@$var_array));
my $ret = Algorithm::CP::IZ::Int->new($ptr);
$self->_register_variable($ret);
return $ret;
}
sub VarElementRange {
my $self = shift;
my ($index, $var_array) = @_;
validate([scalar @_, $index, $var_array],
[sub { shift == 2 }, "V", "vA1"],
"Usage: VarElementRange(index_var, [value_vars])");
@$var_array = map { ref $_ ? $_ : $self->_const_var(int($_)) } @$var_array;
$index = ref $index ? $index : $self->_const_var(int($index));
my $parray = $self->_create_registered_var_array($var_array);
my $ptr = Algorithm::CP::IZ::cs_VarElementRange($$index,
$$parray, scalar(@$var_array));
my $ret = Algorithm::CP::IZ::Int->new($ptr);
$self->_register_variable($ret);
return $ret;
}
sub Cumulative {
my $self = shift;
my ($starts, $durations, $resources, $limit) = @_;
validate([$starts, $durations, $resources, $limit, 1],
["vA0", "vA0", "vA0", "V", sub {
@$starts == @$durations && @$durations == @$resources
}],
"Usage: Cumulative([starts], [durations], [resources], limit)");
@$starts = map { ref $_ ? $_ : $self->_const_var(int($_)) } @$starts;
@$durations = map { ref $_ ? $_ : $self->_const_var(int($_)) } @$durations;
@$resources = map { ref $_ ? $_ : $self->_const_var(int($_)) } @$resources;
$limit = ref $limit ? $limit : $self->_const_var(int($limit));
my $pstarts = $self->_create_registered_var_array($starts);
my $pdurs = $self->_create_registered_var_array($durations);
my $pres = $self->_create_registered_var_array($resources);
my $ret = Algorithm::CP::IZ::cs_Cumulative($$pstarts, $$pdurs, $$pres,
scalar(@$starts), $$limit);
return $ret;
}
sub Disjunctive {
my $self = shift;
my ($starts, $durations) = @_;
validate([$starts, $durations, 1],
["vA0", "vA0", sub {
@$starts == @$durations
}],
"Usage: Disjunctive([starts], [durations])");
@$starts = map { ref $_ ? $_ : $self->_const_var(int($_)) } @$starts;
@$durations = map { ref $_ ? $_ : $self->_const_var(int($_)) } @$durations;
my $pstarts = $self->_create_registered_var_array($starts);
my $pdurs = $self->_create_registered_var_array($durations);
my $ret = Algorithm::CP::IZ::cs_Disjunctive($$pstarts, $$pdurs,
scalar(@$starts));
return $ret;
}
sub Regular {
my $self = shift;
my ($x, $d, $q0, $F) = @_;
validate([scalar(@_), $x,
$d,
$q0, $F
],
[sub { shift == 4 }, "vA0",
sub {
# array of array of integer
return 0 unless (ref $d eq "ARRAY");
for my $row (@$d) {
return 0 unless (ref $row eq "ARRAY");
for my $i (@$row) {
return 0 unless (looks_like_number($i));
}
}
return 1;
},
"I","iA0"
],
"Usage: Regular([vars], [table(QxS)], q0, [F])");
# $q0 must be in valid states
return unless (0 <= $q0 && $q0 < scalar(@$d));
# need acceptable states
return unless (grep { 0 <= $_ && $_ < scalar(@$d) } @$F);
my @xv = map { ref $_ ? $_ : $self->_const_var(int($_)) } @$x;
my $px = $self->_create_registered_var_array(\@xv);
my $pfarray = $self->_create_registered_int_array($F);
# get S for Regular (input alphabet size)
# Q is size saclar(@$d)
my $max_s = 0;
for my $row (@$d) {
my $s = scalar(@$row);
$max_s = $s if ($max_s < $s)
}
# no acceptable alphabet
if ($max_s == 0) {
# accept empty set only
return scalar(@$x) == 0;
}
# create d as 1d array
my @darray = (-1) x (scalar(@$d) * $max_s);
for (my $qi = 0; $qi < scalar(@$d); $qi++) {
my $row = $d->[$qi];
my $idx0 = $max_s * $qi;
my $idx1 = $idx0 + scalar(@$row)-1;
@darray[$idx0..$idx1] = @$row;
}
lib/Algorithm/CP/IZ.pm view on Meta::CPAN
=item create_int(MIN, MAX, [, NAME])
Create an instance of Algorithm::CP::IZ::Int. Its domain is {MIN..MAX}.
=item search(VARIABLES [, PARAMS])
Try to instantiate all VARIABLES(arrayref).
PARAMS will be hashref containning following keys.
=over 2
=item FindFreeVar
FindFreeVar specifies variable selection strategy.
Choose constants from Algorithm::CP::IZ::FindFreeVar or specify your own
function as coderef here.
Most simple function will be following. (select from first)
sub simple_find_free_var{
my $array = shift; # VARIABLES is in parameter
my $n = scalar @$array;
for my $i (0..$n-1) {
return $i if ($array->[$i]->is_free);
}
return -1; # no free variable
};
=item Criteria
Criteria specifies value selection strategy.
Specify your own function as coderef here.
sub sample_criteria {
# position in VARIABLES, and candidate value
my ($index, $val) = @_;
# first value used in search is
# minimum value returned by criteria.
return $val;
};
(If ValueSelector is specified, this parameter is ignored.)
=item MaxFail
Upper limit of fail count while searching solutions.
=item ValueSelectors
Arrayref of Algorithm::CP::IZ::ValueSelector instances created via
get_value_selector or create_value_selector_simple method.
(If ValueSelector is specified, this parameter is ignored.)
=item MaxFailFunc
CodeRef of subroutine which returns maxfail for restart.
=item NoGoodSet
A Algorithm::CP::IZ::NoGoodSet instance which collects NoGoods.
=item Notify
Specify a notify object receives following notification by search function.
search_start
search_end
before_value_selection
after_value_selection
enter
leave
found
if OBJECT is a object, method having notification name will be called.
if OBJECT is a hashref, notification name must be a key of hash and
value must be a coderef.
=back
Returns 1 (success) or 0 (fail).
=item find_all(VARIABLES, CALLBACK [, PARAMS])
Find all solutions. CALLBACK(coderef) is called for each solution.
(First parameter of CALLBACK is VARIABLE)
# this callback collects all solutions in @r
my @r;
sub callback {
my $var_array = shift;
push(@r, [map { $_->value } @$var_array]);
};
PARAMS will be hashref containning following keys.
=over 2
=item FindFreeVar
Same as search method.
=back
Returns 1 (success) or 0 (fail).
=item get_nb_fails
Returns fail count while searching solution.
=item get_nb_choice_points
Returns choice count while searching solution.
=item save_context
Save current status of variables and constraints.
my $v1 = $iz->create_int(1, 9);
$iz->save_context; # current status is saved.
$v1->Le(5); # $v1 is {1..5}
$iz->restore_context; # $v1 is restored to {1..9}
Returns integer which will be used for restore_context_until.
=item restore_context
( run in 0.856 second using v1.01-cache-2.11-cpan-39bf76dae61 )