qbfMakeEqual :: Maybe [ID] -> FORMULA -> [Id.Token]
             -> FORMULA -> [Id.Token] -> Maybe [ID]
qbfMakeEqual (Just ids) f ts f1 ts1 = if length ts /= length ts1 then
                                          Nothing
                                      else case (f, f1) of
  (Predication t, Predication t1)
    | t == t1 -> Just ids
    | t `elem` ts && t1 `elem` ts1 -> let tt1 = ID t (Just t1) in
      if tt1 `elem` ids then
        Just ids
      else
        if ID t Nothing `notElem` ids && ID t1 Nothing `notElem` ids then
          Just (tt1 : ids)
        else
          Nothing
    | otherwise -> Nothing
  (Negation f_ _, Negation f1_ _) -> qbfMakeEqual (Just ids) f_ ts f1_ ts1
  (Conjunction (f_ : fs) _, Conjunction (f1_ : fs1) _) ->
    if length fs /= length fs1 then Nothing else
        case r of
            Nothing -> Nothing
            _ -> qbfMakeEqual r
                   (Conjunction fs nullRange) ts
                   (Conjunction fs1 nullRange) ts1
    where
      r = qbfMakeEqual (Just ids) f_ ts f1_ ts1
  (Disjunction fs r, Disjunction fs1 r1) -> qbfMakeEqual (Just ids)
    (Conjunction fs r) ts (Conjunction fs1 r1) ts1
  (Implication f_ f1_ _, Implication f2 f3 _) -> case r of
    Nothing -> Nothing
    _ -> qbfMakeEqual r f1_ ts f3 ts1
   where
     r = qbfMakeEqual (Just ids) f_ ts f2 ts1
  (Equivalence f_ f1_ r1, Equivalence f2 f3 _) -> qbfMakeEqual (Just ids)
    (Implication f_ f1_ r1) ts
    (Implication f2 f3 r1) ts1
  (ForAll ts_ f_ _, ForAll ts1_ f1_ _) -> case r of
    Nothing -> Nothing
    (Just ids_) -> Just (ids ++ filter (\ (ID x my) ->
      let Just y = my in
      (x `elem` ts_ && y `notElem` ts1_) ||
      (x `elem` ts1_ && y `notElem` ts_)) d)
     where
       d = ids_ List.\\ ids
   where
     r = qbfMakeEqual (Just ids) f_ (ts ++ ts_) f1_ (ts1 ++ ts1_)
  (Exists ts_ f_ r, Exists ts1_ f1_ r1) -> qbfMakeEqual (Just ids)
    (Exists ts_ f_ r) ts
    (Exists ts1_ f1_ r1) ts1
  (_1, _2) -> Nothing
qbfMakeEqual :: Maybe [ID] -> FORMULA -> [Id.Token]
             -> FORMULA -> [Id.Token] -> Maybe [ID]
qbfMakeEqual (Just ids) f ts f1 ts1 = if length ts /= length ts1 then
                                          Nothing
                                      else case (f, f1) of
  (Predication t, Predication t1)
    | t == t1 -> Just ids
    | t `elem` ts && t1 `elem` ts1 -> let tt1 = ID t (Just t1) in
      if tt1 `elem` ids then
        Just ids
      else
        if ID t Nothing `notElem` ids && ID t1 Nothing `notElem` ids then
          Just (tt1 : ids)
        else
          Nothing
    | otherwise -> Nothing
  (Negation f_ _, Negation f1_ _) -> qbfMakeEqual (Just ids) f_ ts f1_ ts1
  (Conjunction (f_ : fs) _, Conjunction (f1_ : fs1) _) ->
    if length fs /= length fs1 then Nothing else
        case r of
            Nothing -> Nothing
            _ -> qbfMakeEqual r
                   (Conjunction fs nullRange) ts
                   (Conjunction fs1 nullRange) ts1
    where
      r = qbfMakeEqual (Just ids) f_ ts f1_ ts1
  (Disjunction fs r, Disjunction fs1 r1) -> qbfMakeEqual (Just ids)
    (Conjunction fs r) ts (Conjunction fs1 r1) ts1
  (Implication f_ f1_ _, Implication f2 f3 _) -> case r of
    Nothing -> Nothing
    _ -> qbfMakeEqual r f1_ ts f3 ts1
   where
     r = qbfMakeEqual (Just ids) f_ ts f2 ts1
  (Equivalence f_ f1_ r1, Equivalence f2 f3 _) -> qbfMakeEqual (Just ids)
    (Implication f_ f1_ r1) ts
    (Implication f2 f3 r1) ts1
  (ForAll ts_ f_ _, ForAll ts1_ f1_ _) -> case r of
    Nothing -> Nothing
    (Just ids_) -> Just (ids ++ filter (\ (ID x my) ->
      let Just y = my in
      (x `elem` ts_ && y `notElem` ts1_) ||
      (x `elem` ts1_ && y `notElem` ts_)) d)
     where
       d = ids_ List.\\ ids
   where
     r = qbfMakeEqual (Just ids) f_ (ts ++ ts_) f1_ (ts1 ++ ts1_)
  (Exists ts_ f_ r, Exists ts1_ f1_ r1) -> qbfMakeEqual (Just ids)
    (Exists ts_ f_ r) ts
    (Exists ts1_ f1_ r1) ts1
  (_1, _2) -> Nothing
qbfMakeEqual (Just ids) f ts f1 ts1 = if length ts /= length ts1 then
                                          Nothing
                                      else case (f, f1) of
  (Predication t, Predication t1)
    | t == t1 -> Just ids
    | t `elem` ts && t1 `elem` ts1 -> let tt1 = ID t (Just t1) in
      if tt1 `elem` ids then
        Just ids
      else
        if ID t Nothing `notElem` ids && ID t1 Nothing `notElem` ids then
          Just (tt1 : ids)
        else
          Nothing
    | otherwise -> Nothing
  (Negation f_ _, Negation f1_ _) -> qbfMakeEqual (Just ids) f_ ts f1_ ts1
  (Conjunction (f_ : fs) _, Conjunction (f1_ : fs1) _) ->
    if length fs /= length fs1 then Nothing else
        case r of
            Nothing -> Nothing
            _ -> qbfMakeEqual r
                   (Conjunction fs nullRange) ts
                   (Conjunction fs1 nullRange) ts1
    where
      r = qbfMakeEqual (Just ids) f_ ts f1_ ts1
  (Disjunction fs r, Disjunction fs1 r1) -> qbfMakeEqual (Just ids)
    (Conjunction fs r) ts (Conjunction fs1 r1) ts1
  (Implication f_ f1_ _, Implication f2 f3 _) -> case r of
    Nothing -> Nothing
    _ -> qbfMakeEqual r f1_ ts f3 ts1
   where
     r = qbfMakeEqual (Just ids) f_ ts f2 ts1
  (Equivalence f_ f1_ r1, Equivalence f2 f3 _) -> qbfMakeEqual (Just ids)
    (Implication f_ f1_ r1) ts
    (Implication f2 f3 r1) ts1
  (ForAll ts_ f_ _, ForAll ts1_ f1_ _) -> case r of
    Nothing -> Nothing
    (Just ids_) -> Just (ids ++ filter (\ (ID x my) ->
      let Just y = my in
      (x `elem` ts_ && y `notElem` ts1_) ||
      (x `elem` ts1_ && y `notElem` ts_)) d)
     where
       d = ids_ List.\\ ids
   where
     r = qbfMakeEqual (Just ids) f_ (ts ++ ts_) f1_ (ts1 ++ ts1_)
  (Exists ts_ f_ r, Exists ts1_ f1_ r1) -> qbfMakeEqual (Just ids)
    (Exists ts_ f_ r) ts
    (Exists ts1_ f1_ r1) ts1
  (_1, _2) -> Nothing