Skip Menu |

This queue is for tickets about the Math-LinearCombination CPAN distribution.

Report information
The Basics
Id: 2829
Status: new
Priority: 0/
Queue: Math-LinearCombination

People
Owner: Nobody in particular
Requestors: cpan [...] martin.lorensen.dk
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: (no value)
Fixed in: (no value)



Subject: Removing (unused) variables
When using Math::LP to solve problems which changes over time, time and space are wasted on variables no longer used. More over, the Math::LP::Solve object complains about variables not used (from the XS code which makes the messages hard to trap). Attached is a patch to version 0.03 of Math::LP which adds support for removing of unused variables of a LP system. Regards, Martin Lorensen
--- LP.pm-orig Wed Jun 18 19:36:21 2003 +++ LP.pm Fri Jun 20 20:34:01 2003 @@ -112,6 +112,72 @@ } return $var->{col_index}; } +sub remove_variable { # remove the variable and reassign numbers to the rest! + my Math::LP $this = shift; + my Math::LP::Variable $var = shift; + + # check variable + $this->croak("A variable named `" . $var->{name} . "' is not registered to the LP.\n") + unless (exists $this->{variables}->{$var->{name}}); + $this->croak("The variable has no col_index!") + unless defined $var->{col_index}; + my $tv = $this->{variables}->{$var->id}; + $this->croak("The variable with that name has a different col_index!") + if $var->{col_index} != $tv->{col_index}; + + # check use of variable + my $constr = $this->variable_in_use($var); + return $constr if defined $constr; + + # everything is OK - remove ... + delete $this->{variables}->{$var->id}; + + # ... and renumber + foreach my $v (values %{$this->{variables}}) { + $v->{col_index} -= 1 unless $v->{col_index} < $var->{col_index}; + } + + # Ready for new use! (both if they are not the same object) + $var->{col_index} = undef; + $tv->{col_index} = undef; + + return 0; +} +sub remove_unused_variables { + my Math::LP $this = shift; + + my $renumber = 0; + + # Remove unused + foreach my $v (values %{$this->{variables}}) { + unless (defined $this->variable_in_use($v)) { + $v->{col_index} = undef; + delete $this->{variables}->{$v->id}; + $renumber = 1; + } + } + + return unless $renumber; + + # Renumber remaining (keep order) + my $i = 1; + foreach my $v (sort { $a->{col_index} <=> $b->{col_index} } values %{$this->{variables}}) { + $v->{col_index} = $i++; + } +} +sub variable_in_use { # check use of var + my Math::LP $this = shift; + my Math::LP::Variable $var = shift; + + foreach my $constr (@{$this->{constraints}}) { + if (exists $constr->{lhs}->get_entries->{$var->id}) { + delete $constr->{lhs}->get_entries->{$var->id} + if $constr->{lhs}->get_entries->{$var->id}->{coeff} == 0; + return $constr if (exists $constr->{lhs}->get_entries->{$var->id}); + }; + } + return undef; +} sub add_constraint { # does what it says, implicitly adds all the variables my Math::LP $this = shift; my Math::LP::Constraint $constr = shift; @@ -388,7 +454,7 @@ type => $LE, ); $lp->add_constraint($constr); - + # solve the LP and print the results $lp->solve() or die "Could not solve the LP"; print "Optimum = ", $obj_fn->{value}, "\n"; @@ -481,13 +547,26 @@ =item add_variable($var) -registers the variable as belonging to the LP. The C<index> field of +registers the variable as belonging to the LP. The C<col_index> field of the variable is set as a side effect. For this reason it is not allowed to use 1 variable in 2 LP objects. +=item remove_variable($var) + +unregisters a variable that is no longer used in the LP. The C<col_index> +field of the variable are set to C<undef> and the remaining variables of +the LP is renumbered to remove the "gap" (order are preserved). Returns 0 +on success or if a constraint uses the variable, the constraint is returned. + +=item remove_unused_variables() + +unregisters all variables that is no longer used in the LP. C<col_index> +fields of the variables are set to C<undef> and the remaining variables of +the LP is renumbered to remove the "gaps" (order are preserved). + =item add_constraint($constr) -adds a Math::LP::Constraint to the LP. The C<index> field of the constraint +adds a Math::LP::Constraint to the LP. The C<row_index> field of the constraint is likewise set. It is thus also not allowed to use a single constraint in more than 1 LP. All variables present in the constraint are automatically registered.