Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
CoPaR
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
This is an archived project. Repository and other project resources are read-only.
Show more breadcrumbs
Informatik 8
CoPaR
Commits
9b761979
Commit
9b761979
authored
6 years ago
by
Hans-Peter Deifel
Browse files
Options
Downloads
Patches
Plain Diff
Implement sum bag data type
parent
2ccb7ef8
No related branches found
No related tags found
No related merge requests found
Changes
2
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
copar.cabal
+1
-0
1 addition, 0 deletions
copar.cabal
src/Data/SumBag.hs
+131
-0
131 additions, 0 deletions
src/Data/SumBag.hs
with
132 additions
and
0 deletions
copar.cabal
+
1
−
0
View file @
9b761979
...
...
@@ -33,6 +33,7 @@ library
, Data.Float.Utils
, Data.List.Utils
, Data.Text.Prettyprint
, Data.SumBag
, Copar.RefinementInterface
, Copar.Functors
, Copar.FunctorDescription
...
...
This diff is collapsed.
Click to expand it.
src/Data/SumBag.hs
0 → 100644
+
131
−
0
View file @
9b761979
{-# LANGUAGE RoleAnnotations #-}
module
Data.SumBag
(
SumBag
,
empty
,
singleton
,
size
,
sum
,
insert
,
delete
)
where
import
Prelude
hiding
(
sum
,
min
)
import
qualified
Data.List.NonEmpty
as
NE
type
SumBag
a
=
Tree
a
data
Tree
a
=
Leaf
|
Node
(
MetaData
a
)
(
Element
a
)
(
Tree
a
)
(
Tree
a
)
type
role
Tree
nominal
data
MetaData
a
=
MetaData
{
nodeSize
::
Int
,
nodeSum
::
a
}
data
Element
a
=
Element
{
value
::
a
,
multiplicity
::
NE
.
NonEmpty
a
}
empty
::
SumBag
a
empty
=
Leaf
singleton
::
Monoid
a
=>
a
->
SumBag
a
singleton
a
=
node
(
Element
a
(
NE
.
fromList
[
a
]))
Leaf
Leaf
size
::
SumBag
a
->
Int
size
Leaf
=
0
size
(
Node
node
_
_
_
)
=
nodeSize
node
sum
::
Monoid
a
=>
SumBag
a
->
a
sum
Leaf
=
mempty
sum
(
Node
node
_
_
_
)
=
nodeSum
node
insert
::
(
Ord
a
,
Monoid
a
)
=>
a
->
SumBag
a
->
SumBag
a
insert
a
Leaf
=
node
(
Element
a
(
NE
.
fromList
[
a
]))
Leaf
Leaf
insert
a
(
Node
_
e
left
right
)
|
a
<
value
e
=
balance1
e
(
insert
a
left
)
right
|
a
>
value
e
=
balance1
e
left
(
insert
a
right
)
|
otherwise
=
node
(
addOnce
e
)
left
right
delete
::
(
Ord
a
,
Monoid
a
)
=>
a
->
SumBag
a
->
SumBag
a
delete
_
Leaf
=
Leaf
delete
a
(
Node
_
e
left
right
)
|
a
<
value
e
=
balance1
e
(
delete
a
left
)
right
|
a
>
value
e
=
balance1
e
left
(
delete
a
right
)
|
Just
e'
<-
delOnce
e
=
node
e'
left
right
|
otherwise
=
helper
left
right
where
helper
Leaf
right
=
right
helper
left
Leaf
=
left
helper
left
right
=
let
(
min
,
rest
)
=
delmin
right
in
balance1
min
left
rest
-- Internal functions
-- | "Smart" constructor for Node. Will compute the meta data from its subtrees
node
::
Monoid
a
=>
Element
a
->
Tree
a
->
Tree
a
->
Tree
a
node
a
left
right
=
let
nodeData
=
MetaData
{
nodeSize
=
size
left
+
1
+
size
right
,
nodeSum
=
NE
.
head
(
multiplicity
a
)
<>
sum
left
<>
sum
right
}
in
Node
nodeData
a
left
right
rotateSingleLeft
::
Monoid
a
=>
Element
a
->
Tree
a
->
Tree
a
->
Tree
a
rotateSingleLeft
a
x
(
Node
_
b
y
z
)
=
node
b
(
node
a
x
y
)
z
rotateSingleLeft
_
_
_
=
error
"rotateSingleLeft called with empty right tree"
rotateSingleRight
::
Monoid
a
=>
Element
a
->
Tree
a
->
Tree
a
->
Tree
a
rotateSingleRight
b
(
Node
_
a
x
y
)
z
=
node
a
x
(
node
b
y
z
)
rotateSingleRight
_
_
_
=
error
"rotateSingleRight called with empty left tree"
rotateDoubleLeft
::
Monoid
a
=>
Element
a
->
Tree
a
->
Tree
a
->
Tree
a
rotateDoubleLeft
a
x
(
Node
_
c
(
Node
_
b
y1
y2
)
z
)
=
node
b
(
node
a
x
y1
)
(
node
c
y2
z
)
rotateDoubleLeft
_
_
_
=
error
"rotateDoubleLeft called with too small left tree"
rotateDoubleRight
::
Monoid
a
=>
Element
a
->
Tree
a
->
Tree
a
->
Tree
a
rotateDoubleRight
c
(
Node
_
a
x
(
Node
_
b
y1
y2
))
z
=
node
b
(
node
a
x
y1
)
(
node
c
y2
z
)
rotateDoubleRight
_
_
_
=
error
"rotateDoubleRight called with too small left tree"
balance1
::
Monoid
a
=>
Element
a
->
Tree
a
->
Tree
a
->
Tree
a
balance1
a
left
right
-- Subtrees have only one element
|
size
left
+
size
right
<
2
=
node
a
left
right
-- Right subtree is too heavy
|
size
right
>
balanceBound
*
size
left
=
let
Node
_
_
rleft
rright
=
right
sizeRL
=
size
rleft
sizeRR
=
size
rright
in
if
sizeRL
<
sizeRR
then
rotateSingleLeft
a
left
right
else
rotateDoubleLeft
a
left
right
-- Left subtree is too heavy
|
size
left
>
balanceBound
*
size
right
=
let
Node
_
_
lleft
lright
=
left
sizeLL
=
size
lleft
sizeLR
=
size
lright
in
if
sizeLL
<
sizeLR
then
rotateSingleRight
a
left
right
else
rotateDoubleRight
a
left
right
-- No subtree is too heave, we can just form a new tree straight away
|
otherwise
=
node
a
left
right
addOnce
::
Semigroup
a
=>
Element
a
->
Element
a
addOnce
e
=
let
total
=
NE
.
head
(
multiplicity
e
)
in
e
{
multiplicity
=
NE
.
cons
(
total
<>
value
e
)
(
multiplicity
e
)
}
delOnce
::
Element
a
->
Maybe
(
Element
a
)
delOnce
e
=
case
snd
(
NE
.
uncons
(
multiplicity
e
))
of
Nothing
->
Nothing
Just
rest
->
Just
(
e
{
multiplicity
=
rest
})
delmin
::
Monoid
a
=>
Tree
a
->
(
Element
a
,
Tree
a
)
delmin
Leaf
=
error
"delmin: Empty tree"
delmin
(
Node
_
e
Leaf
_
)
=
(
e
,
Leaf
)
delmin
(
Node
_
e
left
right
)
=
(
\
left'
->
balance1
e
left'
right
)
<$>
delmin
left
balanceBound
::
Int
balanceBound
=
4
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment