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 )