diff --git a/arbor/morph/em_morphology.cpp b/arbor/morph/em_morphology.cpp
index 6e482c7e062e68eefc4545e0129b7441e1aa7042..ba6d275131217ae32a7b175c25e893ee0fb23e31 100644
--- a/arbor/morph/em_morphology.cpp
+++ b/arbor/morph/em_morphology.cpp
@@ -1,4 +1,5 @@
 #include <mutex>
+#include <stack>
 #include <vector>
 
 #include <arbor/morph/error.hpp>
@@ -141,4 +142,40 @@ mlocation em_morphology::canonicalize(mlocation loc) const {
     return loc;
 }
 
+mlocation_list em_morphology::minset(const mlocation_list& in) const {
+    mlocation_list L;
+
+    std::stack<msize_t> stack;
+
+    // All root branches must be searched.
+    for (auto c: morph_.branch_children(mnpos)) {
+        stack.push(c);
+    }
+
+    // Depth-first traversal of the branch tree.
+    while (!stack.empty()) {
+        auto branch = stack.top();
+        stack.pop();
+
+        // Search for a location on branch.
+        auto it = std::lower_bound(in.begin(), in.end(), mlocation{branch, 0});
+
+        // If found, insert to the minset and skip the rest of this sub-tree.
+        if (it!=in.end() && it->branch==branch) {
+            L.push_back(*it);
+            continue;
+        }
+
+        // No location on this branch, so continue searching in this sub-tree.
+        for (auto c: morph_.branch_children(branch)) {
+            stack.push(c);
+        }
+    }
+
+    util::sort(L);
+
+    return L;
+}
+
 } // namespace arb
+
diff --git a/arbor/morph/em_morphology.hpp b/arbor/morph/em_morphology.hpp
index 5b2f3dc4a5fab0ed403bb998f7d07352372907a7..94aa5b0fe783551928d3506d5cdc5910d2ea0d5b 100644
--- a/arbor/morph/em_morphology.hpp
+++ b/arbor/morph/em_morphology.hpp
@@ -34,6 +34,8 @@ public:
     // representation of loc.
     // If include_loc is false, the input location is excluded from the result.
     mlocation_list cover(mlocation, bool include_loc=true) const;
+
+    mlocation_list minset(const mlocation_list&) const;
 };
 
 } // namespace arb
diff --git a/test/unit/test_em_morphology.cpp b/test/unit/test_em_morphology.cpp
index c724f5d1f9b772df2893d1c1a7e71a13ceccf094..39528837f92c891ecc1f141e6ff71de20dcac907 100644
--- a/test/unit/test_em_morphology.cpp
+++ b/test/unit/test_em_morphology.cpp
@@ -187,6 +187,57 @@ TEST(em_morphology, cover) {
     }
 }
 
+TEST(em_morphology, minset) {
+    using pvec = std::vector<arb::msize_t>;
+    using svec = std::vector<arb::msample>;
+    using ll = arb::mlocation_list;
+    constexpr auto npos = arb::mnpos;
+
+    // Eight samples
+    //                  no-sphere  sphere
+    //          sample   branch    branch
+    //            0         0         0
+    //           1 3       0 1       1 2
+    //          2   4     0   1     1   2
+    //             5 6       2 3       3 4
+    //                7         3         4
+    pvec parents = {npos, 0, 1, 0, 3, 4, 4, 6};
+    svec samples = {
+        {{  0,  0,  0,  2}, 3},
+        {{ 10,  0,  0,  2}, 3},
+        {{100,  0,  0,  2}, 3},
+        {{  0, 10,  0,  2}, 3},
+        {{  0,100,  0,  2}, 3},
+        {{100,100,  0,  2}, 3},
+        {{  0,200,  0,  2}, 3},
+        {{  0,300,  0,  2}, 3},
+    };
+    arb::sample_tree sm(samples, parents);
+    {
+        arb::em_morphology em(arb::morphology(sm, false));
+
+        EXPECT_EQ((ll{}), em.minset(ll{}));
+        EXPECT_EQ((ll{{2,0.1}}), em.minset(ll{{2,0.1}}));
+        EXPECT_EQ((ll{{0,0.5}, {1,0.5}}), em.minset(ll{{0,0.5}, {1,0.5}}));
+        EXPECT_EQ((ll{{0,0.5}}), em.minset(ll{{0,0.5}}));
+        EXPECT_EQ((ll{{0,0}, {1,0}}), em.minset(ll{{0,0}, {0,0.5}, {1,0}, {1,0.5}}));
+        EXPECT_EQ((ll{{0,0}, {1,0.5}}), em.minset(ll{{0,0}, {0,0.5}, {1,0.5}, {2,0.5}}));
+        EXPECT_EQ((ll{{0,0}, {2,0.5}}), em.minset(ll{{0,0}, {0,0.5}, {2,0.5}}));
+        EXPECT_EQ((ll{{0,0}, {2,0.5}, {3,0}}), em.minset(ll{{0,0}, {0,0.5}, {2,0.5}, {3,0}, {3,1}}));
+        EXPECT_EQ((ll{{0,0}, {1,0}}), em.minset(ll{{0,0}, {0,0.5}, {1,0}, {2,0.5}, {3,0}, {3,1}}));
+    }
+    {
+        arb::em_morphology em(arb::morphology(sm, true));
+
+        EXPECT_EQ((ll{}), em.minset(ll{}));
+        EXPECT_EQ((ll{{2,0.1}}), em.minset(ll{{2,0.1}}));
+        EXPECT_EQ((ll{{0,0.5}}), em.minset(ll{{0,0.5}, {1,0.5}}));
+        EXPECT_EQ((ll{{0,0.5}}), em.minset(ll{{0,0.5}}));
+        EXPECT_EQ((ll{{0,0}}), em.minset(ll{{0,0}, {0,0.5}, {1,0}, {1,0.5}}));
+        EXPECT_EQ((ll{{1,0.5}, {3,0.1}, {4,0.5}}), em.minset(ll{{1,0.5}, {1,1}, {3,0.1}, {4,0.5}, {4,0.7}}));
+    }
+}
+
 // Test expressions that describe location sets (locset).
 TEST(locset, expressions) {
     auto root = arb::ls::root();
@@ -625,3 +676,4 @@ TEST(region, thingify) {
         EXPECT_EQ(thingify(join(lhs, rhs), em), ror);
     }
 }
+