Giter VIP home page Giter VIP logo

math-symbolic-custom-transformation's Introduction

NAME
    Math::Symbolic::Custom::Transformation - Transform Math::Symbolic trees

SYNOPSIS
      use Math::Symbolic::Custom::Transformation;
      my $trafo = Math::Symbolic::Custom::Transformation->new(
        'TREE_x + TREE_x' => '2 * TREE_x'
      );
      
  my $modified = $trafo->apply($math_symbolic_tree);
      if (defined $modified) {
        print "Outermost operator is a sum of two identical trees.\n";
            print "Transformed it into a product. ($modified)\n";
      }
      else {
        print "Transformation could not be applied.\n";
      }
      
  # shortcut: new_trafo
      use Math::Symbolic::Custom::Transformation qw/new_trafo/;

      # use the value() function to have the transformation compute the value
      # of the expression after the replacements. simplify{} works similar.
      my $another_trafo = new_trafo(
        'TREE_foo / CONST_bar' => 'value{1/CONST_bar} * TREE_foo'
      );
      
  # If you'll need the same transformation but don't want to keep it around in
      # an object, just do this:
      use Memoize;
      memoize('new_trafo');
      # Then, passing the same transformation strings will result in a speedup of
      # about a factor 130 (on my machine) as compared to complete recreation
      # from strings. This is only 20% slower than using an existing
      # transformation.

DESCRIPTION
    Math::Symbolic::Custom::Transformation is an extension to the
    Math::Symbolic module. You're assumed to be remotely familiar with that
    module throughout the documentation.

    This package implements transformations of Math::Symbolic trees using
    Math::Symbolic trees. I'll try to explain what this means in the
    following paragraphs.

    Until now, in order to be able to inspect a Math::Symbolic tree, one had
    to use the low-level Math::Symbolic interface like comparing the top
    node's term type with a constant (such as "T_OPERATOR") and then its
    operator type with more constants. This has changed with the release of
    Math::Symbolic::Custom::Pattern.

    To modify the tree, you had to use equally low-level or even
    encapsulation-breaking methods. This is meant to be changed by this
    distribution.

  EXAMPLE
    Say you want to change any tree that is a sum of two identical trees
    into two times one such tree. Let's assume the original object is in the
    variable $tree. The old way was: (strictures and warnings assumed)

      use Math::Symbolic qw/:all/;
      
  sub sum_to_product {
        if ( $tree->term_type() == T_OPERATOR
             and $tree->type() == B_SUM
             and $tree->op1()->is_identical($tree->op2()) )
        {
          $tree = Math::Symbolic::Operator->new(
            '*', Math::Symbolic::Constant->new(2), $tree->op1()->new()
          );
        }
        return $tree;
      }

    What you'd do with this package is significantly more readable:

      use Math::Symbolic::Custom::Transformation qw/new_trafo/;
      
  my $Sum_To_Product_Rule = new_trafo('TREE_a + TREE_a' => '2 * TREE_a');
      
  sub sum_to_product {
        my $tree = shift;
        return( $Sum_To_Product_Rule->apply($tree) || $tree );
      }

    Either version could be shortened, of course. The significant
    improvement, however, isn't shown by this example. If you're doing
    introspection beyond the outermost operator, you will end up with giant,
    hardly readable if-else blocks when using the old style transformations.
    With this package, however, such introspection scales well:

      use Math::Symbolic::Custom::Transformation qw/new_trafo/;
      
  my $Sum_Of_Const_Products_Rule = new_trafo(
        'CONST_a * TREE_b + CONST_c * TREE_b'
        => 'value{CONST_a + CONST_c} * TREE_b'
      );
      
  sub sum_to_product {
        my $tree = shift;
        return( $Sum_Of_Const_Products_Rule->apply($tree) || $tree );
      }

    For details on the "value{}" construct in the transformation string, see
    the "SYNTAX EXTENSIONS" section.

  EXPORT
    None by default, but you may choose to import the "new_trafo" subroutine
    as an alternative constructor for Math::Symbolic::Custom::Transformation
    objects.

  PERFORMANCE
    The performance of transformations isn't astonishing by itself, but if
    you take into account that they leave the original tree intact, we end
    up with a speed hit of only 16% as compared to the literal code. (That's
    the huge if-else block I was talking about.)

    You may be tempted to recreate the transformation objects from strings
    whenever you need them. There's one thing to say about that: Don't! The
    construction of transformations is really slow because they have been
    optimised for performance on application, not creation. (Application
    should be around 40 times faster than creation from strings!)

    *Note:* Starting with version 2.00, this module also supports the
    new-ish Math::Symbolic::Parser::Yapp parser implementation which is
    significantly faster than the old Parse::RecDescent based
    implementation. Replacement strings are parsed using Yapp by default
    now, which means a performance increase of about 20%. The search
    patterns are still parsed using the default Math::Symbolic parser which
    will be switched to Yapp at some point in the future. If you force the
    use of the Yapp parser globally, the parser performance will improve by
    about an order of magnitude! You can do so by adding the following
    before using Math::Symbolic::Custom::Transformation:

      use Math::Symbolic;
      BEGIN {
        $Math::Symbolic::Parser = Math::Symbolic::Parser->new(
          implementation => 'Yapp'
        );
      }
      use Math::Symbolic::Custom::Transformation;
      #...

    If you absolutely must include the source strings where the
    transformation is used, consider using the Memoize module which is part
    of the standard Perl distribution these days.

      use Memoize;
      use Math::Symbolic::Custom::Transformation qw/new_trafo/;
      memoize('new_trafo');

      sub apply_some_trafo {
        my $source = shift;
            my $trafo = new_trafo(...some pattern... => ...some transformation...);
            return $trafo->apply($source);
      }

    This usage has the advantage of putting the transformation source
    strings right where they make the most sense in terms of readability.
    The memoized subroutine "new_trafo" only constructs the transformation
    the first time it is called and returns the cached object every time
    thereafter.

  SYNTAX EXTENSIONS
    The strings from which you can create transformations are basically
    those that can be parsed as Math::Symbolic trees. The first argument to
    the transformation constructor will, in fact, be parsed as a
    Math::Symbolic::Custom::Pattern object. The second, however, may include
    some extensions to the default Math::Symbolic syntax. These extensions
    are the two functions "value{...}" and "simplify{...}". The curly braces
    serve the purpose to show the distinction from algebraic parenthesis.
    When finding a "value{EXPR}" directive, the module will calculate the
    value of "EXPR" when the transformation is applied. (That is, after the
    "TREE_foo", "CONST_bar" and "VAR_baz" placeholders have been inserted!)
    The result is then inserted into the transformed tree.

    Similarily, the "simplify{EXPR}" directive will use the Math::Symbolic
    simplification routines on "EXPR" when the transformation is being
    applied (and again, after replacing the placeholders with the matched
    sub-trees.

  METHODS
    This is a list of public methods.

    new
      This is the constructor for Math::Symbolic::Custom::Transformation
      objects. It takes two arguments: A pattern to look for and a
      replacement.

      The pattern may either be a Math::Symbolic::Custom::Pattern object
      (fastest), or a Math::Symbolic tree which will internally be
      transformed into a pattern or even just a string which will be parsed
      as a pattern.

      The replacement for the pattern may either be a Math::Symbolic tree or
      a string to be parsed as such.

    apply
      Applies the transformation to a Math::Symbolic tree. First argument
      must be a Math::Symbolic tree to transform. The tree is not
      transformed in-place, but its matched subtrees are contained in the
      transformed tree, so if you plan to use the original tree as well as
      the transformed tree, take care to clone one of the trees.

      "apply()" returns the transformed tree if the transformation pattern
      matched and a false value otherwise.

      On errors, it throws a fatal error.

    apply_recursive
      "Recursively" applies the transformation. The Math::Symbolic tree
      passed in as argument will be modified in-place.

      Hold on: This does not mean that the transformation is applied again
      and again, but that the Math::Symbolic tree you are applying to is
      descended into and while walking back up the tree, the transformation
      is tried for every node.

      Basically, it's applied bottom-up. Top-down would not usually make
      much sense. If the application to any sub-tree throws a fatal error,
      this error is silently caught and the application to other sub-trees
      is continued.

      Usage is the same as with the "shallow" "apply()" method.

    to_string
      Returns a string representation of the transformation. In presence of
      the "simplify" or "value" hooks, this may fail to return the correct
      represenation. It does not round-trip!

      (Generally, it should work if only one hook is present, but fails if
      more than one hook is found.)

  SUBROUTINES
    This is a list of public subroutines.

    new_trafo
      This subroutine is an alternative to the "new()" constructor for
      Math::Symbolic::Custom::Transformation objects that uses a hard coded
      package name. (So if you want to subclass this module, you should be
      aware of that!)

    new_trafo_group
      This subroutine is the equivalent of "new_trafo", but for creation of
      new transformation groups. See
      Math::Symbolic::Custom::Transformation::Group.

SEE ALSO
    New versions of this module can be found on http://steffen-mueller.net
    or CPAN.

    This module uses the Math::Symbolic framework for symbolic computations.

    Math::Symbolic::Custom::Pattern implements the pattern matching
    routines.

AUTHOR
    Steffen Müller, <symbolic-module at steffen-mueller dot net>

COPYRIGHT AND LICENSE
    Copyright (C) 2006-2008 by Steffen Mueller

    This library is free software; you can redistribute it and/or modify it
    under the same terms as Perl itself, either Perl version 5.6.1 or, at
    your option, any later version of Perl 5 you may have available.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.