<commit_before><?php

class Graph implements Countable{
    /**
     * array of all edges in this graph
     * 
     * @var array[Edge]
     */
	private $edges = array();
    
	/**
	 * array of all vertices in this graph
	 * 
	 * @var array[Vertex]
	 */
	private $vertices = array();
	
	/**
	 * create a new Vertex in the Graph
	 * 
	 * @param int|NULL $vertex          instance of Vertex or new vertex ID to use
	 * @param boolean  $returnDuplicate normal operation is to throw an exception if given id already exists. pass true to return original vertex instead
	 * @return Vertex (chainable)
	 * @throws Exception if given vertex $id is invalid or already exists
	 * @uses Vertex::getId()
	 */
	public function createVertex($id=NULL,$returnDuplicate=false){
	    if($id === NULL){    // no ID given
	        $id = $this->getNextId();
	    }else if(!is_int($id) && !is_string($id)){
	        throw new Exception('Vertex ID has to be of type integer or string');
	    }
	    if(isset($this->vertices[$id])){
	        if($returnDuplicate){
	            return $this->vertices[$id];
	        }
	        throw new Exception('ID must be unique');
	    }
	    $vertex = new Vertex($id,$this);
		$this->vertices[$id] = $vertex;
		return $vertex;
	}
	
	/**
	 * create a new Vertex in this Graph from the given input Vertex of another graph
	 * 
	 * @param Vertex $vertex
	 * @return Vertex new vertex in this graph
	 * @throws Exception
	 */
	public function createVertexClone($originalVertex){
	    $id = $originalVertex->getId();
	    if(isset($this->vertices[$id])){
	        throw new Exception('Id of cloned vertex already exists');
	    }
	    $newVertex = new Vertex($id,$this);
	    // TODO: properly set attributes of vertex
	    $this->vertices[$id] = $newVertex;
	    return $newVertex;
	}
	
	/**
	 * create new clone/copy of this graph - copy all attributes and vertices, but do NOT copy edges
	 * 
	 * using this method is faster than creating a new graph and calling createEdgeClone() yourself
	 *
	 * @return Graph
	 */
	public function createGraphCloneEdgeless(){
	    $graph = new Graph();
	    // TODO: set additional graph attributes
	    foreach($this->getVertices() as $vid=>$originalVertex){
	        $vertex = new Vertex($vid,$graph);
	        // TODO: set additional vertex attributes
	        $graph->vertices[$vid] = $vertex;
	    }
	    return $graph;
	}
	
	/**
	 * create new clone/copy of this graph - copy all attributes, vertices and edges
	 *
	 * @return Graph
	 * @uses Graph::createGraphCloneEdgeless()
	 * @uses Graph::createEdgeClone()
	 */
	public function createGraphClone(){
	    $graph = $this->createGraphCloneEdgeless();
	    foreach($this->edges as $edge){
	        $graph->createEdgeClone($edge);
	    }
	    return $graph;
	}
	
	/**
	 * create new clone of the given edge between adjacent vertices
	 * 
	 * @param Edge $originalEdge original edge from old graph
	 * @return Edge new edge in this graph
	 * @uses Edge::getVerticesId()
	 * @uses Graph::getVertex()
	 * @uses Vertex::createEdge() to create a new undirected edge if given edge was undrected
	 * @uses Vertex::createEdgeTo() to create a new directed edge if given edge was directed
	 * @uses Edge::getWeight()
	 * @uses Edge::setWeight()
	 */
	public function createEdgeClone($originalEdge){
	    $ends = $originalEdge->getVerticesId();
	    
	    $a = $this->getVertex($ends[0]); // get start vertex from old start vertex id
	    $b = $this->getVertex($ends[1]); // get target vertex from old target vertex id
	    
	    if($originalEdge instanceof EdgeDirected){
	        $newEdge = $a->createEdgeTo($b);
	    }else{
	        $newEdge = $a->createEdge($b); // create new edge between new a and b
	    }
	    // TODO: copy edge attributes<commit_msg>Additional helper to clone graph with given edges<commit_after><?php

class Graph implements Countable{
    /**
     * array of all edges in this graph
     * 
     * @var array[Edge]
     */
	private $edges = array();
    
	/**
	 * array of all vertices in this graph
	 * 
	 * @var array[Vertex]
	 */
	private $vertices = array();
	
	/**
	 * create a new Vertex in the Graph
	 * 
	 * @param int|NULL $vertex          instance of Vertex or new vertex ID to use
	 * @param boolean  $returnDuplicate normal operation is to throw an exception if given id already exists. pass true to return original vertex instead
	 * @return Vertex (chainable)
	 * @throws Exception if given vertex $id is invalid or already exists
	 * @uses Vertex::getId()
	 */
	public function createVertex($id=NULL,$returnDuplicate=false){
	    if($id === NULL){    // no ID given
	        $id = $this->getNextId();
	    }else if(!is_int($id) && !is_string($id)){
	        throw new Exception('Vertex ID has to be of type integer or string');
	    }
	    if(isset($this->vertices[$id])){
	        if($returnDuplicate){
	            return $this->vertices[$id];
	        }
	        throw new Exception('ID must be unique');
	    }
	    $vertex = new Vertex($id,$this);
		$this->vertices[$id] = $vertex;
		return $vertex;
	}
	
	/**
	 * create a new Vertex in this Graph from the given input Vertex of another graph
	 * 
	 * @param Vertex $vertex
	 * @return Vertex new vertex in this graph
	 * @throws Exception
	 */
	public function createVertexClone($originalVertex){
	    $id = $originalVertex->getId();
	    if(isset($this->vertices[$id])){
	        throw new Exception('Id of cloned vertex already exists');
	    }
	    $newVertex = new Vertex($id,$this);
	    // TODO: properly set attributes of vertex
	    $this->vertices[$id] = $newVertex;
	    return $newVertex;
	}
	
	/**
	 * create new clone/copy of this graph - copy all attributes and vertices, but do NOT copy edges
	 * 
	 * using this method is faster than creating a new graph and calling createEdgeClone() yourself
	 *
	 * @return Graph
	 */
	public function createGraphCloneEdgeless(){
	    $graph = new Graph();
	    // TODO: set additional graph attributes
	    foreach($this->getVertices() as $vid=>$originalVertex){
	        $vertex = new Vertex($vid,$graph);
	        // TODO: set additional vertex attributes
	        $graph->vertices[$vid] = $vertex;
	    }
	    return $graph;
	}
	
	/**
	 * create new clone/copy of this graph - copy all attributes and vertices. but only copy all given edges
	 *
	 * @param array[Edge] $edge array of edges to be cloned
	 * @return Graph
	 * @uses Graph::createGraphCloneEdgeless()
	 * @uses Graph::createEdgeClone() for each edge to be cloned
	 */
	public function createGraphCloneEdges($edges){
	    $graph = $this->createGraphCloneEdgeless();
	    foreach($edges as $edge){
	        $graph->createEdgeClone($edge);
	    }
	    return $graph;
	}
	
	/**
	 * create new clone/copy of this graph - copy all attributes, vertices and edges
	 *
	 * @return Graph
	 * @uses Graph::createGraphCloneEdges() to clone graph with current edges
	 */
	public function createGraphClone(){
	    return $this->createGraphCloneEdges($this->edges);
	}
	
	/**
	 * create new clone of the given edge between adjacent vertices
	 * 
	 * @param Edge $originalEdge original edge from old graph
	 * @return Edge new edge in this graph
	 * @uses Edge::getVerticesId()
	 * @uses Graph::getVertex()
	 * @uses Vertex::createEdge() to create a new undirected edge if given edge was undrected
	 * @uses Vertex::createEdgeTo() to create a new directed edge if given edge was directed
	 * @uses Edge::getWeight()
	 * @uses Edge::setWeight()
	 */
	public function createEdgeClone($originalEdge){
	    $ends = $originalEdge->getVerticesId();
	    
	    $a = $this->getVertex($ends[0]); // get start vertex from old start vertex id
	    $b = $this->getVertex($ends[1]); // get target vertex from old target vertex id
	    
	    if($originalEdge instanceof EdgeDirected){
	        $newEdge = $a->createEdgeTo($b);
	    }else{
	        $newEdge = $a->createEdge($b); // create new edge between new a and b
	    }
	    // TODO: copy edge attributes
{'fraction_non_alphanumeric': 0.11977329974811084, 'fraction_numerical': 0.0005037783375314861, 'mean_word_length': 2.962574850299401, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 40, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1012031', 'n_tokens_mistral': 2404, 'n_tokens_neox': 2206, 'n_words': 799}