-
Notifications
You must be signed in to change notification settings - Fork 68
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
NonEmpty AdjacencyIntMaps #250
base: main
Are you sure you want to change the base?
Conversation
unsafeNonEmpty :: [Int] -> NonEmpty Int | ||
unsafeNonEmpty = fromMaybe (error msg) . nonEmpty | ||
where | ||
msg = "Algebra.Graph.AdjacencyIntMap.unsafeNonEmpty: Graph is empty" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be Algebra.Graph.NonEmpty.AdjacencyIntMap
. Alternatively, we could move this utility function to Algebra.Graph.Internal
to avoid code duplication.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think Internal sounds good
-- Complexity: /O(1)/ time and memory. | ||
-- | ||
-- @ | ||
-- 'AdjacencyIntMap.hasVertex' x (vertex x) == True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit confused: do we really need qualifications AdjacencyIntMap.
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so. I was following very closely the NonEmpty.AdjacencyMap
module
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ha, indeed. If it's redundant, let's drop it there too.
-- induceJust1 . 'gmap' 'Just' == 'Just' | ||
-- induceJust1 . 'gmap' (\\x -> if p x then 'Just' x else 'Nothing') == 'induce1' p | ||
-- @ | ||
-- TODO: double check there's no analogue for AIMs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I don't think there is one.
import qualified Data.IntSet as IntSet | ||
|
||
sizeLimit :: Testable prop => prop -> Property | ||
sizeLimit = mapSize (min 10) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is size10
in Algebra.Graph.Test
, so this can be dropped.
-- vertexSet . 'clique1' == Set.'Set.fromList' . 'Data.List.NonEmpty.toList' | ||
-- @ | ||
vertexSet :: AdjacencyIntMap -> IntSet | ||
vertexSet = coerce AIM.vertexIntSet |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, should be vertexIntSet
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(And accompanying documentation functions IntSet.
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed 👍
test "Axioms of non-empty graphs" axioms | ||
test "Theorems of non-empty graphs" theorems | ||
|
||
putStrLn $ "\n============ Ord NonEmpty.AdjacencyIntMap ============" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to reduce code duplication for non-empty tests. We could move some tests into Algebra.Graph.Test.Generic
, adding suffix NonEmpty
to properties for disambiguation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
testAdjacencyMap
would be a model to go off? It seems like most of the functions from the NAM
modules are candidates
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think we can reuse tests for most functions from NonEmpty
modules. Just thought that perhaps creating Generic.NonEmpty
would be best since then we don't need to do any renaming.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I'm not clear about the some of the issues and steps. What would need to be renamed? Does the plan look something like this?
Algebra.Graph.Test.API
module should getNonEmpty
functions added and the nonempty types should get anonemptyAPI :: API (G/Mono) (Ord/(~) Int)
- also add the
ToGraph
instance for NAIM - new
TestsuiteInt g -> IO ()
functions go inAlgebra.Graph.Test.Generic.NonEmpty
- each nonempty module would import the
API
,Generic
, andGeneric.NonEmpty
modules similar to whatAlgebra.Graph.Test.AdjacencyMap
does
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After refreshing my memory on how things are implemented, here is a more concrete plan:
-
Extend
data API g c
with new fields that correspond to missing methods (most of them end with the suffix1
). In fact there is a TODO for this:alga/test/Algebra/Graph/Test/API.hs
Line 58 in 026ba0e
-- TODO: Add missing API entries for Acyclic, NonEmpty and Symmetric graphs. -
Add tests for missing methods to
Test.Generic
orTest.Generic.NonEmpty
-- whichever turns out to be clearer/more convenient. -
I don't think we need any
ToGraph
instances for non-empty graphs but perhaps I'm mistaken? Instead, I expectAPI
definitions similar toalga/test/Algebra/Graph/Test/API.hs
Lines 146 to 148 in 026ba0e
-- | The API of 'AM.AdjacencyMap'. adjacencyMapAPI :: API AM.AdjacencyMap Ord adjacencyMapAPI = API -
Tests for non-empty modules would need to import
API
,Generic
and perhaps alsoGeneric.NonEmpty
(if it turns out to be convenient).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the plan! Refactoring the nonempty modules to use generic is a bit daunting, but I'll try to find time and energy soon
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jitwit If you don't want to deal with this daunting task feel free to simply leave a TODO describing the plan. I do understand that it's no fun at all and happy to do it myself :)
@jitwit Thanks for doing this! I'm a bit terrified about the combinatorial explosion in modules but no idea what to do about it :) |
Yeah, the explosion is a bit horrifying. Is that part of why no |
@jitwit Yep. At some point, I also had a representation based on arrays but then deleted it too. |
Hi and sorry for the MASSIVE delay, I finally returned to this! Hope all is well. |
@jitwit Hey, welcome back! All is good and I hope you're good too. Nice new avatar 👍 The plan looks fine to me, looking forward to future commits :) |
Things are still good here, too. Thanks! |
Hi, I was wondering what the current status of this PR is. I realized that AdjacencyIntMaps don't have an scc algorithm, which led me to realizing NonEmpty AdjacencyIntMaps were missing too. Should I try to submit a PR for IntMap scc? It would basically be similar in nature to this PR, copying the code from the regular AdjacencyMap. Thanks! |
@zyklotomic Hi there! I think @jitwit run out of steam a bit, so it would be great if you could help. Let's give @jitwit a week to comment. If we don't hear back from him, I think it would be fine to create a new PR, keeping all the commits from this PR and their authorship, and then fixing the remaining issues. I'm happy to review. |
I was trying to continue the work mentioned in the thread above #250 (comment) . If I understand correctly about extending the test API, we would want to add the field overlays1 :: forall a. c a => NonEmpty (g a) -> g a which should be analogous to the existing overlays :: forall a. c a => [g a] -> g a Furthermore, I interpreted your plan as that we should be adding API's for other types of graphs. I started with I think we do in fact need I am not sure if I understood your plan correctly, let me know if I have misunderstood it. Thanks! |
@zyklotomic I think you understood the plan correctly. However, implementing a non-generic version of the testsuite for the new module should be OK too: as long as every property we promise in comments is tested, I will be happy :) So, feel free to test some (or all?) of the properties directly, without trying to be too generic. (I admit I might have overengineered the testsuite quite a bit...) However, since this is all still going to be quite a lot of work, I'd like us to take a step back and think: is adding If I recall correctly, your specific motivation for doing this was the
I am a bit unhappy with how the library looks at the moment (it's way too complex) and I think adding more APIs may be a step in the wrong direction. So, it'd be really interesting to learn more about your motivation/use-case. |
I have already been using an auxiliary mapping due to space complexity reasons. Performance boost isn't super important. If you are interested, I used scc here. I was trying to write a heap analysis of the GHC runtime. I used scc to compress cycles in the heap reference graph into one representative node. The only reason why I thought to add it was because it was missing. I do agree that the library is a bit complex. In my experience, it is because of the inconsistencies (such as |
Wow, that's very cool! Best wishes with finishing this project.
Yes, I agree with you. I'd love to have consistency, but it seems almost unreachable in practice because of so many different combinations of graph flavours. It's very hard to implement, document, test and maintain all of these combinations. I'll try to find a way around that, hopefully soon. |
Adding modules for NAIMs
I was having problems in the test suite with
reachable
about couldn't match typeToVertex AIM
with typeInt
so I commented it out for now.I changed the complexity comments for
vertexCount
/edgeCount
in AIM, which claimedO(1)
.Hopefully not too many names in the documentation are out of sync!