Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

compute normal forms w.r.t. given strategy #10

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

csternagel
Copy link
Contributor

A function for computing the normal forms of a given term w.r.t. a given strategy.

Question: should we avoid computing duplicate NFs? (In experiments this sometimes has a huge positive impact on the running time.) Or stay with the clearer (?) implementation?

@@ -19,6 +19,8 @@ import qualified Prelude as P
import Data.Rewriting.Rule (Rule (..))
import qualified Data.Rewriting.Rule as Rule

import Control.Applicative
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this line serve any purpose?

@int-e
Copy link
Contributor

int-e commented May 27, 2017

I believe this function is a bit too simple to be useful; for example, for terms without normal forms, it will not terminate. In general, an unrestricted search seems to be a bad idea, but it's hard to predict the tuning knobs that users will need.

A more modular approach could look like this:

import Control.Applicative
import Data.Functor.Identity
import Data.Rewriting.Rules.Rewrite

-- one step reducts
results :: Strategy f v v' -> Term f v -> [Term f v]
results s = fmap result . s

-- Generic breadth first enumeration of normal forms on the ARS level.
--
-- The function `f` can do things like elimination of duplicates,
-- prioritization or limiting the width (cf. beam search),
-- while the monad allows things like keeping track fo all
-- terms seen so far.
normalFormsBFM :: Monad m => (a -> m [a]) -> ([a] -> m [a]) -> a -> m [[a]]
normalFormsBFM s f t = go [t] where
     go ts = do
         ts' <- mapM s ts
         (:) [t | (t, []) <- zip ts ts'] <$> (f (concat ts') >>= go)

-- pure version
normalFormsBF :: (a -> [a]) -> ([a] -> [a]) -> a -> [[a]]
normalFormsBF s f = runIdentity . bfsM (Identity . s) (Identity . f)

-- the proposed `normalForms` could be implemented as
normalForms :: Strategy f v v' -> Term f v -> [Term f v]
normalForms s = concat . normalFormsBF (results s) id

-- but we can also easily do stuff like
--   let nub' = Set.toList . Set.fromList in
--   let size = Term.fold (\v -> 1) (\f xs -> 1 + sum xs) in
--   concat . take 10 . nfs (results s) (filter (\t -> size t <= 10) . nub'))
-- to limit the depth and size of intermediate terms to 10, and avoids
-- many duplicates.

Perhaps normalFormsBFM should really be a more general breadth first search (which would look almost the same but take a predicate for which nodes to include in the result, instead of checking for zero successors)

Of course that would raise the question of where to put the normalFormsBF* functions.

@int-e
Copy link
Contributor

int-e commented May 27, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants