Slash Boxes
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

agent (5836)


Agent Zhang (章亦春) is a happy Yahoo! China guy who loves Perl more than anything else.

Journal of agent (5836)

Saturday April 16, 2005
03:01 AM

Actual Implementation of Math::Model

[ #24220 ]

=from 2005.4.14.8:00.AM
=to ...4.14.9:45.AM

Now I decide to sit down to consider seriously the matter of hacking on Math::Model. The basic code can be borrowed from the existing module. I think a procedural design will be appropriate here.

Math::Model should offer the following subroutines:

  • reg_eq
  • unreg_eq
  • reg_var
  • unreg_var
  • reg_eqs
  • get_eqs
  • get_vars
  • use_solve
  • new_layer
  • bye_layer

The last two functions are completely new. They provide the magic of assuming and backtracking. Once the user invokes new_layer, Math::Model will create a new layer (or a new "copy") for the math model, so any subsequent updates to the model won't spoil the original one. When the user calls bye_layer some time later, Math::Model will recover the model immediately back to the initial state just before the last new_layer calling. In other words, a call of bye_layer will effectively remove all the modifications to the math model (through reg_eq, unreg_var, etc.) since the last invocation of new_layer. This behavior is very similar to assuming and backtracking.

I finally prefer stack structures to do such trick. The implementation of bye_layer and new_layer is straightforward:

        our (@ModelStack, %Vars, @Equas);

        # new_layer: Create and enter a new layer.
        sub new_layer {
                push @ModelStack, {%Vars}, [@Equas];
                @Equas = ();

        # bye_layer: quit the current layer.
        sub bye_layer {
                my $ref = pop @ModelStack;
                return unless $ref;
                @Equas = @$ref;
                $ref = pop @ModelStack;
                %Vars = %$ref;

I hasten to ask the following question: What do we mean by a math model? A math model is composed of nothing but several equations, some optional inequalities, and a list of unknown variables. This basic concept should be clarified first at this point.

For each layer, there are two "localized" structures, %Vars and @Equas. %Vars is inherited directly from the outer layer (or parent layer), while @Equas holds only the equations built on the current layer due to efficiency considerations. The realization of the get_eqs function therefore needs a thorough rewrite accordingly:

        # get_eqs: get all the equations
        sub get_eqs {
                my @equas = get_eq_and_des();
                my @eqs = ();
                for (my $i=0; $i @equas; $i += 2) {
                        push @eqs, $equas[$i];
                return @eqs;

        # get_eq_and_des: get all the equations and corresponding descriptions:
        sub get_eq_and_des {
                my @equas;
                for (my $i = 1; $i @ModelStack; $i += 2) {
                        my $ref = $ModelStack[$i];
                        push @equas, @$ref;
                return (@equas, @Equas);

There is no need to modify the get_vars function originated from since the semantics of the %Vars structure does not change.

Now that we've got an implementation, it's time for us to write some tests...

I'm afraid I'm not a real XP programmer as I seldom write tests before any actual coding. Sigh.

With an excellent repertoire of math model management utilities, we can then happily implement the @assume language mechanism for our CIR scripts, which cannot be difficult. Aha!

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
More | Login | Reply
Loading... please wait.