Skip to content

Conversation

@RaoulLuque
Copy link
Member

I think the auxiliary space and time complexity as recently updated in #815, are not quite right for Bron-Kerbosch.

For one, the auxiliary space complexity cannot be right. Since, we return a Vec with HashSet, the auxiliary space has to be at least equal to the number of maximal cliques in the graph. Moon and Moser showed that this can be up to 3 ^ (|V| / 3) many. Thus, I suggest introducing k as a variable to denote the number of maximal cliques in the graph.

The time complexity might also be able to be written in terms of k, however this would probably also depend on this implementation of Bron-Kerbosch with pivoting. Instead one could write something like:

/// * Time complexity: **O(p(|V|)k)**

For some polynomial p, which makes clear that the runtime is not always exponential in the number of vertices, but is merely dominated by the number of maximal cliques in the graph.

@RaoulLuque RaoulLuque force-pushed the 825_maximal_clique_doc_fix branch from d7f3ef5 to 8b31f64 Compare June 9, 2025 15:36
@RaoulLuque RaoulLuque changed the title docs: Fix time and auxiliary space complexity of bron-kerbosch docs: Fix auxiliary space (and time) complexity of bron-kerbosch Jun 9, 2025
@starovoid
Copy link
Collaborator

The "Auxiliary" space means exactly the auxiliary space, not the size of output data. For greater clarity, it is really useful to specify k, but as a separate comment, not as a replacement for the current doc-line.

@RaoulLuque
Copy link
Member Author

RaoulLuque commented Jun 9, 2025

I think might be using different definitions of auxiliary space and I am not sure which one is correct. I looked at the one from wikipedia which states:

The term auxiliary space refers to space other than that consumed by the input. 

Thus, the space used by the output would also be part of the auxiliary space. This is confirmed by the more precise definition using Turing Machines, which follows the above one and can be found using the same link:

Auxiliary space complexity could be formally defined in terms of a 
[Turing machine](https://en.wikipedia.org/wiki/Turing_machine) 
with a separate input tape which cannot be written to, only read, 
and a conventional working tape which can be written to. The 
auxiliary space complexity is then defined (and analyzed) via the 
working tape.

@starovoid
Copy link
Collaborator

starovoid commented Jun 9, 2025

Thus, the space used by the output would also be part of the auxiliary space. This is confirmed by the more precise definition using Turing Machines, which follows the above one and can be found using the same link:

Then I suggest this: in situations where the output size exceeds the size of the auxiliary space, describe both components.

This difference makes sense due to the existence of algorithms that return iterators, in which it is impossible to unambiguously specify the space complexity, since the output can simply be discarded.

@RaoulLuque
Copy link
Member Author

Then I suggest this: in situations where the output size exceeds the size of the auxiliary space, describe both components.

This difference makes sense due to the existence of algorithms that return iterators, in which it is impossible to unambiguously specify the space complexity, since the output can simply be discarded.

Okay, I see the possible ambiguity with returned Iterators. However, in that case we should still be able to clearly compute the auxiliary space complexity. Take for example a function which would return an iterator of the numbers from 1 to n. If it is implemented storing only the previously outputted number then I agree that the auxiliary space used is O(1). If it instead all previously outputted number (would be inefficient of course), then it is O(n).

However, in this case we actually store the entire output (all maximal cliques) at at least one point in time in the function. Thus it is auxiliary space used by the function. Therefore, I would definitely lean towards including this in the auxiliary space complexity of the function itself for this case.

@starovoid
Copy link
Collaborator

Moon and Moser showed that this can be up to 3 ^ (|V| / 3) many. Thus, I suggest introducing k as a variable to denote the number of maximal cliques in the graph.

Shouldn't we write O(|V|^2 +|V|k), since each clique can contain up to |V| nodes?

@RaoulLuque
Copy link
Member Author

Moon and Moser showed that this can be up to 3 ^ (|V| / 3) many. Thus, I suggest introducing k as a variable to denote the number of maximal cliques in the graph.

Shouldn't we write O(|V|^2 +|V|k), since each clique can contain up to |V| nodes?

Yes and No ^^ I think this is not clear and depends on the author, but since k can be exponential, in that case the V term would vanish in the Landau Notation and thus some leave it out in general.

However, when looking at the complete graph with increasing n for example, the k would be constant which would not make a lot of sense of course. Thus, I think you have a point :) So yeah, that would be even more precise, good point 😁

@RaoulLuque
Copy link
Member Author

Just adapted it accordingly 🌞

@starovoid starovoid force-pushed the 825_maximal_clique_doc_fix branch from 07cf1ef to c8399a8 Compare June 16, 2025 10:21
@starovoid starovoid added this pull request to the merge queue Jun 16, 2025
@starovoid starovoid added this to the 0.8.3 milestone Jun 16, 2025
@starovoid starovoid added the A-documentation Area: Docs label Jun 16, 2025
Merged via the queue into petgraph:master with commit a801119 Jun 16, 2025
10 checks passed
@github-actions github-actions bot mentioned this pull request Jun 16, 2025
RaoulLuque added a commit to RaoulLuque/petgraph that referenced this pull request Jun 18, 2025
…graph#825)

I think the auxiliary space and time complexity as recently updated in
petgraph#815, are not quite right for Bron-Kerbosch.

For one, the auxiliary space complexity cannot be right. Since, we
return a `Vec` with `HashSet`, the auxiliary space has to be at least
equal to the number of maximal cliques in the graph. [Moon and Moser
showed](https://link.springer.com/article/10.1007/BF02760024) that this
can be up to `3 ^ (|V| / 3)` many. Thus, I suggest introducing `k` as a
variable to denote the number of maximal cliques in the graph.

The time complexity might also be able to be written in terms of `k`,
however this would probably also depend on this implementation of
Bron-Kerbosch with pivoting. Instead one could write something like:

```
/// * Time complexity: **O(p(|V|)k)**
```
For some polynomial `p`, which makes clear that the runtime is not
always exponential in the number of vertices, but is merely dominated by
the number of maximal cliques in the graph.
@RaoulLuque RaoulLuque deleted the 825_maximal_clique_doc_fix branch September 22, 2025 07:14
github-merge-queue bot pushed a commit that referenced this pull request Sep 30, 2025
## 🤖 New release

* `petgraph`: 0.8.2 -> 0.8.3 (✓ API compatible changes)

<details><summary><i><b>Changelog</b></i></summary><p>

<blockquote>

##
[0.8.3](https://github.com/petgraph/petgraph/compare/petgraph@v0.8.2...petgraph@v0.8.3)
- 2025-09-28

### Bug Fixes

- Infinite `subgraph_isomorphisms_iter` for empty isomorphisms
([#780](#780))
- Algos don't work on `UndirectedAdaptor`
([#870](#870))
([#871](#871))
- use a queue for SPFA
([#893](#893))
- `StableGraph::reverse` breaks free lists
([#890](#890))

### Documentation

- Fix examples link in README and unify typesetting of one word
([#823](#823))
- Add link to multigraph definition to isomorphism algos
([#824](#824))
- Fix auxiliary space (and time) complexity of bron-kerbosch
([#825](#825))
- Fix Typo in Operator Module Documentation
([#831](#831))
- Sync the crate feature flags in the README and docs
([#832](#832))
- Remove all \[Generic\] tags from algo docstrings
([#835](#835))
- Fix typos in comments
([#836](#836))
- Revamp CONTRIBUTING.md
([#833](#833))
- Update `GraphMap` link in README
([#857](#857))
- Add doc comment for `Dot::with_attr_getters`
([#850](#850))
- Specify iteration order for neighbors and edges and their variants
([#790](#790))
- Collection of Doc fixes
([#856](#856))

### New Features

- Add `into_nodes_edges_iters` to `StableGraph`
([#841](#841))
- Add methods to reserve & shrink `StableGraph` capacity
([#846](#846))
- Add Dinic's Maximum Flow Algorithm
([#739](#739))
- make Csr::from_sorted_edges generic over edge type and properly
increase edge_count in Csr::from_sorted_edges
([#861](#861))
- Add `map_owned` and `filter_map_owned` for `Graph` and `StableGraph`
([#863](#863))
- Add dijkstra::with_dynamic_goal
([#855](#855))
- Fix self-loop bug in all_simple_paths and enable multiple targets
([#865](#865))
- mark petgraph::dot::Dot::graph_fmt as public
([#866](#866))
- Add bidirectional Dijkstra algorithm
([#782](#782))

### Performance

- Make A* tie break on lower h-values
([#882](#882))

### Refactor

- add examples for scc algorithms and reorganize into dedicated module
([#830](#830))
- Remove unnecessary trait bounds from impls/methods
([#828](#828))
- replace uses of 'crate::util::zip' with 'core::iter::zip'
([#849](#849))
- Fix clippy (and other) lints
([#851](#851))
- Cleanup repo ([#854](#854))
- replace crate::util::enumerate with Iterator::enumerate
([#881](#881))

### Testing

- Add dependency list for 'quickcheck' feature
([#822](#822))
- Fix feature cfg capitalization in doctest
([#852](#852))
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Egor Starovoitov <52821033+starovoid@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants