All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgrapht.nio.dimacs.DIMACSImporter Maven / Gradle / Ivy

The newest version!
/*
 * (C) Copyright 2010-2023, by Michael Behrisch and Contributors. 
 *
 * JGraphT : a free Java graph-theory library
 *
 * See the CONTRIBUTORS.md file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0, or the
 * GNU Lesser General Public License v2.1 or later
 * which is available at
 * http://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR LGPL-2.1-or-later
 */
package org.jgrapht.nio.dimacs;

import org.jgrapht.*;
import org.jgrapht.alg.util.*;
import org.jgrapht.nio.*;

import java.io.*;
import java.util.*;
import java.util.function.*;

/**
 * Imports a graph specified in DIMACS format.
 *
 * 

* See {@link DIMACSFormat} for a description of all the supported DIMACS formats. * *

* In summary, one of the most common DIMACS formats was used in the * 2nd DIMACS challenge and follows * the following structure: * *

 * {@code
 * DIMACS G {
 *    c  ignored during parsing of the graph
 *    p edge  
 *    e  
 *    e  
 *    e  
 *    e  
 *    ...
 * }
 * }
 * 
* * Although not specified directly in the DIMACS format documentation, this implementation also * allows for the a weighted variant: * *
 * {@code 
 * e    
 * }
 * 
* * Note: the current implementation does not fully implement the DIMACS specifications! Special * (rarely used) fields specified as 'Optional Descriptors' are currently not supported (ignored). * * @author Michael Behrisch (adaptation of GraphReader class) * @author Joris Kinable * @author Dimitrios Michail * * @param the graph vertex type * @param the graph edge type */ public class DIMACSImporter extends BaseEventDrivenImporter implements GraphImporter { /** * Default key used for vertex ID. */ public static final String DEFAULT_VERTEX_ID_KEY = "ID"; private Function vertexFactory; private final double defaultWeight; /** * Construct a new DIMACSImporter * * @param defaultWeight default edge weight */ public DIMACSImporter(double defaultWeight) { super(); this.defaultWeight = defaultWeight; } /** * Construct a new DIMACSImporter */ public DIMACSImporter() { this(Graph.DEFAULT_EDGE_WEIGHT); } /** * Get the user custom vertex factory. This is null by default and the graph supplier is used * instead. * * @return the user custom vertex factory */ public Function getVertexFactory() { return vertexFactory; } /** * Set the user custom vertex factory. The default behavior is being null in which case the * graph vertex supplier is used. * * If supplied the vertex factory is called every time a new vertex is encountered in the file. * The method is called with parameter the vertex identifier from the file and should return the * actual graph vertex to add to the graph. * * @param vertexFactory a vertex factory */ public void setVertexFactory(Function vertexFactory) { this.vertexFactory = vertexFactory; } /** * Import a graph. * *

* The provided graph must be able to support the features of the graph that is read. For * example if the file contains self-loops then the graph provided must also support self-loops. * The same for multiple edges. * *

* If the provided graph is a weighted graph, the importer also reads edge weights. Otherwise * edge weights are ignored. * * @param graph the output graph * @param input the input reader * @throws ImportException in case an error occurs, such as I/O or parse error */ @Override public void importGraph(Graph graph, Reader input) throws ImportException { DIMACSEventDrivenImporter genericImporter = new DIMACSEventDrivenImporter().renumberVertices(false).zeroBasedNumbering(false); Consumers consumers = new Consumers(graph); genericImporter.addVertexCountConsumer(consumers.nodeCountConsumer); genericImporter.addEdgeConsumer(consumers.edgeConsumer); genericImporter.importInput(input); } private class Consumers { private Graph graph; private List list; public Consumers(Graph graph) { this.graph = graph; this.list = new ArrayList<>(); } public final Consumer nodeCountConsumer = n -> { for (int i = 1; i <= n; i++) { V v; if (vertexFactory != null) { v = vertexFactory.apply(i); graph.addVertex(v); } else { v = graph.addVertex(); } list.add(v); /* * Notify the first time we create the node. */ notifyVertex(v); notifyVertexAttribute( v, DEFAULT_VERTEX_ID_KEY, DefaultAttribute.createAttribute(i)); } }; public final Consumer> edgeConsumer = t -> { int source = t.getFirst(); V from = getElement(list, source - 1); if (from == null) { throw new ImportException("Node " + source + " does not exist"); } int target = t.getSecond(); V to = getElement(list, target - 1); if (to == null) { throw new ImportException("Node " + target + " does not exist"); } E e = graph.addEdge(from, to); if (graph.getType().isWeighted()) { double weight = t.getThird() == null ? defaultWeight : t.getThird(); graph.setEdgeWeight(e, weight); } notifyEdge(e); }; } private static E getElement(List list, int index) { return index < list.size() ? list.get(index) : null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy