class SimpleCycleBasis {

    public Collection essentialCycles() {
        Collection result = new HashSet();

        boolean[][] a = getCycleEdgeIncidenceMatrix();

        boolean[][] ai = inverseBinaryMatrix(a, cycles.size());

        for (int i = 0; i < cycles.size(); i++) {

            // Construct kernel vector u
            boolean[] u = new boolean[edgeList.size()];
            for (int j = 0; j < cycles.size(); j++) {
                u[j] = ai[j][i];
            }

            // Construct kernel vector u from a column of the inverse of a
            AuxiliaryGraph gu = new AuxiliaryGraph(graph, u);

            boolean isEssential = true;

            Iterator vertexIterator = graph.vertexSet().iterator();
            while (isEssential && vertexIterator.hasNext()) {
                Object vertex = vertexIterator.next();

                Collection incidentEdges = graph.edgesOf(vertex);

                // check if the vertex is incident to an edge with u[edge] == 1
                boolean shouldSearchCycle = false;

                for (Iterator it = incidentEdges.iterator(); it.hasNext();) {
                    Edge edge = (Edge) it.next();
                    int index = getEdgeIndex(edge);
                    if (u[index]) {
                        shouldSearchCycle = true;
                        break;
                    }
                }

                if (shouldSearchCycle) {

                    Object auxVertex0 = gu.auxVertex0(vertex);
                    Object auxVertex1 = gu.auxVertex1(vertex);

                    // Search for shortest paths
                    for (Iterator minPaths = new MinimalPathIterator(gu, auxVertex0, auxVertex1); minPaths.hasNext();) {
                        List auxPath = (List) minPaths.next();
                        List edgesOfNewCycle = new ArrayList(auxPath.size());

                        for (Iterator it = auxPath.iterator(); it.hasNext();) {
                            Edge auxEdge = (Edge) it.next();

                            // Get the edge corresponding to the aux. edge
                            Edge e = (Edge) gu.edge(auxEdge);

                            if (edgesOfNewCycle.contains(e)) {
                                edgesOfNewCycle.remove(e);
                            } else {
                                edgesOfNewCycle.add(e);
                            }

                        }

                        SimpleCycle cycle = new SimpleCycle(graph, edgesOfNewCycle);

                        if (cycle.weight() > ((SimpleCycle) cycles.get(i)).weight()) {
                            break;
                        }

                        if (!cycle.equals((SimpleCycle) cycles.get(i))) {
                            isEssential = false;
                            break;
                        }

                    }

                }

            }

            if (isEssential) {
                result.add(cycles.get(i));
            }

        }

        return result;
    }

    public  SimpleCycleBasis(List<SimpleCycle> cycles, List edgeList, UndirectedGraph graph);
    public  SimpleCycleBasis(UndirectedGraph graph);

}