module Frenetic.NetCore.Reduce ( reduce ) where import Frenetic.Common import Data.Maybe import qualified Data.MultiSet as MS import qualified Data.Set as Set import Frenetic.NetCore.Types import Frenetic.NetCore.Short -- |Reduce the policy to produce a smaller, more readable policy reduce = reducePo reducePo :: Policy -> Policy reducePo PoBottom = PoBottom reducePo (PoBasic pr act) = if pr' == matchNone || act == mempty then PoBottom else PoBasic pr' act' where pr' = reducePr pr act' = act -- Note that because we use multiset forwarding semantics, we CANNOT do common -- subexpression reduction on unions. reducePo (PoUnion p1 p2) = if p1' == PoBottom then p2' else if p2' == PoBottom then p1' else PoUnion p1' p2' where p1' = reducePo p1 p2' = reducePo p2 -- TODO(astory): do reductions beyond common subexpression reduction. Ideas: -- top reduction, bottom reduction, empty intersection reduction. reducePr :: Predicate -> Predicate reducePr p@(PrUnion _ _) = prOr leaves where leaves = Set.toList . Set.fromList . map reducePr . prUnUnion $ p reducePr p@(PrIntersect _ _) = result where leaves = Set.toList . Set.fromList . map reducePr . prUnIntersect $ p nSwitches = Set.size .Set.fromList . mapMaybe switchOfPred $ leaves result = if nSwitches > 1 then matchNone else prAnd leaves reducePr (PrNegate (PrNegate p)) = reducePr p reducePr (PrNegate p) = PrNegate (reducePr p) reducePr p = p switchOfPred (PrTo s) = Just s switchOfPred _ = Nothing