acacia icon indicating copy to clipboard operation
acacia copied to clipboard

Geometric bounds of tree partition are not checked

Open milibopp opened this issue 9 years ago • 6 comments

The current tree constructors fail, when they are supplied with a set of points not contained within their partition.

  • [ ] First of all, the construction of a (minimal) partition that contains a set of given points must be implemented. This could be wrapped in a subtrait of Partition.
  • [ ] The tree needs to be equipped with constructors making use of the above. Examine, in how far the type system can be used to guarantee such a property.

milibopp avatar Jan 10 '15 14:01 milibopp

If I understand you correctly, you would like to resolve this by constructing the minimal domain, instead of being able to specify the domain yourself?

I can imagine that this might be an issue for some use cases, where you want to use a specific domain, although I don't have a good example atm, besides maybe directly comparing your implementation to other codes.

Or do you think this would be a nonissue?

In the meantime an explicit check when inserting a point would be a workable alternative imo, but would be associated with a certain runtime cost. Do you think a safe and unsafe version of the constructor would be a good idea?

Btw, the same is true for checking for duplicates, but I'm not sure if this would not be better handled by supporting multiple leafs.

Moredread avatar Sep 15 '16 12:09 Moredread

OK, I've benched the creation of a PureTree with explicit testing wheter the object is inside the tree domain, i.e.

    pub fn new<I: Iterator<Item=O>>(iter: I, partition: P) -> PureTree<P, O> {
        let mut tree = PureTree::empty(partition);
        for object in iter {
            if tree.partition.contains(&object.position()) {
                tree.insert(object)
            } else {
                panic!("WAHHH")
            }
        }
        tree
    }

Without testing:

test pure_tree::test::pure_tree_quad_new_1000                ... bench:     217,655 ns/iter (+/- 14,512)

With testing:

test pure_tree::test::pure_tree_quad_new_1000                ... bench:     220,087 ns/iter (+/- 56,874)

The difference doesn't seem to be significant, but it might be worthwhile to test other cases.

Moredread avatar Sep 15 '16 13:09 Moredread

Looks like the performance penalty is negligible. No need to introduce an unsafe API for one percent performance gain imho. The check you are proposing is more about improving error reporting. And yes, that's worthwhile doing, I didn't even consider that at the beginning.

If you want to merge that, I would suggest changing new to return something like a Result<PureTree<P, O>, ConstructionError>, because that can be caught & handled if necessary.

Regarding your question about the minimal domain: the current API takes the list of objects and the partition. This may be inconvenient, as it can cause a runtime error, when you don't care about the partition being a particular fixed value or simply don't know what it is.

To avoid that, constructing a partition that forms an outer hull around the list of objects (for a given type of partition supporting this → subtrait) allows a safe tree construction for arbitrary data known only at runtime. And that function could return a PureTree directly, no Result required.

milibopp avatar Sep 15 '16 19:09 milibopp

See PR #89

Moredread avatar Sep 16 '16 06:09 Moredread

The error type is still a bit barebones, i.e. it isn't a real Error yet... But besides that you could already review the rest.

On that note, would you reexport error types?

Moredread avatar Sep 16 '16 06:09 Moredread

Why would it have to be anything more than a barebones enum? And what precisely do you mean by re-export?

milibopp avatar Sep 16 '16 20:09 milibopp