School Commit Init

This commit is contained in:
2024-08-31 12:07:21 +03:00
commit 0b130ee18c
2801 changed files with 4720552 additions and 0 deletions
@@ -0,0 +1,224 @@
#include "directed_graph.h"
#include <unordered_set>
#include <unordered_map>
#include <string>
#include <fstream>
DirectedGraph::DirectedGraph(){
// nothing to do
}
DirectedGraph::~DirectedGraph(){
// nothing to do
}
DirectedGraph::DirectedGraph(const DirectedGraph& g){
this->_vertices = g._vertices;
this->_inbounds.clear();
this->_outbounds.clear();
this->_weights.clear();
for(std::pair<const int, std::unordered_set<int>> p : g._inbounds){
this->_inbounds[p.first] = p.second;
}
for(std::pair<const int, std::unordered_set<int>> p : g._outbounds){
this->_outbounds[p.first] = p.second;
}
for(std::pair<const std::pair<int, int>, int> p : g._weights){
this->_weights[p.first] = p.second;
}
}
DirectedGraph DirectedGraph::operator=(const DirectedGraph& g){
this->_vertices = g._vertices;
this->_inbounds.clear();
this->_outbounds.clear();
this->_weights.clear();
for(std::pair<const int, std::unordered_set<int>> p : g._inbounds){
this->_inbounds[p.first] = p.second;
}
for(std::pair<const int, std::unordered_set<int>> p : g._outbounds){
this->_outbounds[p.first] = p.second;
}
for(std::pair<const std::pair<int, int>, int> p : g._weights){
this->_weights[p.first] = p.second;
}
return *this;
}
DirectedGraph DirectedGraph::reindex() const{
std::unordered_map<int, int> old_to_new;
int i = this->numVertices()-1;
for(int v : this->_vertices){
old_to_new[v] = i;
i--;
}
DirectedGraph new_g;
for(int v : this->_vertices){
new_g.addVertex(old_to_new[v]);
}
for(std::pair<const std::pair<int, int>, int> p : this->_weights){
new_g.addEdge(old_to_new[p.first.first], old_to_new[p.first.second], p.second);
}
return new_g;
}
int DirectedGraph::numVertices() const{
return this->_vertices.size();
}
int DirectedGraph::numEdges() const{
return this->_weights.size();
}
std::unordered_set<int> DirectedGraph::vertices() const{
return this->_vertices;
}
std::unordered_map<std::pair<int, int>, int> DirectedGraph::edges() const{
std::unordered_map<std::pair<int, int>, int> weights;
for(std::pair<const std::pair<int, int>, int> p : this->_weights){
weights[p.first] = p.second;
}
return weights;
}
bool DirectedGraph::isEdge(int v1, int v2) const{
if(this->_vertices.find(v1) == this->_vertices.end() || this->_vertices.find(v2) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
return this->_weights.find(std::make_pair(v1, v2)) != this->_weights.end();
}
int DirectedGraph::inDegree(int v) const{
if(this->_vertices.find(v) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
return this->_inbounds.at(v).size();
}
int DirectedGraph::outDegree(int v) const{
if(this->_vertices.find(v) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
return this->_outbounds.at(v).size();
}
std::unordered_set<int> DirectedGraph::inbounds(int v) const{
if(this->_vertices.find(v) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
return this->_inbounds.at(v);
}
std::unordered_set<int> DirectedGraph::outbounds(int v) const{
if(this->_vertices.find(v) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
return this->_outbounds.at(v);
}
int DirectedGraph::weight(int v1, int v2) const{
if(this->_vertices.find(v1) == this->_vertices.end() || this->_vertices.find(v2) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
if(this->_weights.find(std::make_pair(v1, v2)) == this->_weights.end())
throw std::invalid_argument("Edge not found");
return this->_weights.at(std::make_pair(v1, v2));
}
void DirectedGraph::weight(int v1, int v2, int w){
if(this->_vertices.find(v1) == this->_vertices.end() || this->_vertices.find(v2) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
if(this->_weights.find(std::make_pair(v1, v2)) == this->_weights.end())
throw std::invalid_argument("Edge not found");
this->_weights[std::make_pair(v1, v2)] = w;
}
void DirectedGraph::addVertex(int v){
if(this->_vertices.find(v) != this->_vertices.end())
throw std::invalid_argument("Vertex already exists");
this->_vertices.insert(v);
this->_inbounds[v] = std::unordered_set<int>();
this->_outbounds[v] = std::unordered_set<int>();
}
void DirectedGraph::removeVertex(int v){
if(this->_vertices.find(v) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
this->_vertices.erase(v);
for(int i : this->_inbounds[v]){
this->_outbounds[i].erase(v);
this->_weights.erase(std::make_pair(i, v));
}
for(int i : this->_outbounds[v]){
this->_inbounds[i].erase(v);
this->_weights.erase(std::make_pair(v, i));
}
this->_inbounds.erase(v);
this->_outbounds.erase(v);
}
void DirectedGraph::addEdge(int v1, int v2, int w){
if(this->_vertices.find(v1) == this->_vertices.end() || this->_vertices.find(v2) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
if(this->_weights.find(std::make_pair(v1, v2)) != this->_weights.end())
throw std::invalid_argument("Edge already exists");
this->_weights[std::make_pair(v1, v2)] = w;
this->_inbounds[v2].insert(v1);
this->_outbounds[v1].insert(v2);
}
void DirectedGraph::removeEdge(int v1, int v2){
if(this->_vertices.find(v1) == this->_vertices.end() || this->_vertices.find(v2) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
if(this->_weights.find(std::make_pair(v1, v2)) == this->_weights.end())
throw std::invalid_argument("Edge not found");
this->_weights.erase(std::make_pair(v1, v2));
this->_inbounds[v2].erase(v1);
this->_outbounds[v1].erase(v2);
}
DirectedGraph read_from_file(std::string filename){
std::ifstream file(filename);
if(!file.is_open())
throw std::invalid_argument("File not found");
DirectedGraph g;
int num_vertices=0;
file >> num_vertices;
for(int i = 0; i < num_vertices; i++){
g.addVertex(i);
}
int num_edges=0;
file >> num_edges;
int v1, v2, w;
for(int i = 0; i < num_edges; i++){
file >> v1 >> v2 >> w;
g.addEdge(v1, v2, w);
}
file.close();
return g;
}
void write_to_file(const DirectedGraph& g, std::string filename){
DirectedGraph new_g = g.reindex();
std::ofstream file(filename);
if(!file.is_open())
throw std::invalid_argument("File could not be opened");
file << new_g.numVertices() << " " << new_g.numEdges() << std::endl;
for(std::pair<const std::pair<int, int>, int> p : new_g.edges()){
file << p.first.first << " " << p.first.second << " " << p.second << std::endl;
}
file.close();
}
DirectedGraph random_graph(int num_vertices, int num_edges){
DirectedGraph g;
for(int i = 0; i < num_vertices; i++){
g.addVertex(i);
}
for(int i = 0; i < num_edges; i++){
int v1 = rand() % num_vertices;
int v2 = rand() % num_vertices;
int w = rand() % 100;
if (g.isEdge(v1, v2)){
i--;
continue;
}
g.addEdge(v1, v2, w);
}
return g;
}
@@ -0,0 +1,47 @@
#pragma once
#include<unordered_set>
#include<unordered_map>
#include<string>
namespace std{
template<>
struct hash<std::pair<int,int>>{
size_t operator()(const std::pair<int,int>& p) const{
return (std::hash<int>()(p.first)<<1) ^ std::hash<int>()(p.second);
}
};
}
class DirectedGraph{
private:
std::unordered_set<int> _vertices;
std::unordered_map<int,std::unordered_set<int>> _inbounds;
std::unordered_map<int,std::unordered_set<int>> _outbounds;
std::unordered_map<std::pair<int,int>,int> _weights;
public:
DirectedGraph();
~DirectedGraph();
DirectedGraph(const DirectedGraph& g);
DirectedGraph operator=(const DirectedGraph& g);
DirectedGraph reindex() const;
int numVertices() const;
int numEdges() const;
std::unordered_set<int> vertices() const;
std::unordered_map<std::pair<int,int>,int> edges() const;
bool isEdge(int v1, int v2) const;
int inDegree(int v) const;
int outDegree(int v) const;
std::unordered_set<int> inbounds(int v) const;
std::unordered_set<int> outbounds(int v) const;
int weight(int v1, int v2) const;
void weight(int v1, int v2, int w);
void addVertex(int v);
void removeVertex(int v);
void addEdge(int v1, int v2, int w);
void removeEdge(int v1, int v2);
};
DirectedGraph read_from_file(std::string filename);
void write_to_file(const DirectedGraph& g, std::string filename);
DirectedGraph random_graph(int num_vertices, int num_edges);
@@ -0,0 +1,12 @@
#include "directed_graph.h"
#include "ui.h"
#include <utility>
#include <vector>
#include <unordered_map>
#include <iostream>
int main(){
UI ui;
ui.run();
return 0;
}
@@ -0,0 +1,282 @@
#include "directed_graph.h"
#include "ui.h"
#include <unordered_set>
#include <unordered_map>
#include <iostream>
UI::UI(){
// nothing to do
}
UI::~UI(){
// nothing to do
}
void UI::run(){
int command;
while(true){
if(this->_graph.numVertices() == 0)
std::cout << std::endl << "Graph is empty" << std::endl;
std::cout << std::endl;
std::cout << "1. Load graph from file" << std::endl;
std::cout << "2. Save graph to file" << std::endl;
std::cout << "3. Generate a graph" << std::endl;
std::cout << "4. Add vertex" << std::endl;
std::cout << "5. Remove vertex" << std::endl;
std::cout << "6. Add edge" << std::endl;
std::cout << "7. Remove edge" << std::endl;
std::cout << "8. Get in degree" << std::endl;
std::cout << "9. Get out degree" << std::endl;
std::cout << "10. Get cost" << std::endl;
std::cout << "11. Set cost" << std::endl;
std::cout << "12. Get number of vertices" << std::endl;
std::cout << "13. Get number of edges" << std::endl;
std::cout << "14. Get vertices" << std::endl;
std::cout << "15. Get edges" << std::endl;
std::cout << "16. Get inbounds" << std::endl;
std::cout << "17. Get outbounds" << std::endl;
std::cout << "18. Futeti-l " << std::endl;
std::cout << "0. Exit" << std::endl;
std::cout << "Command: ";
std::cin >> command;
std::cout << std::endl;
switch(command){
case 1:{
std::string filename;
std::cout << "Filename: ";
std::cin >> filename;
try{
this->_graph = read_from_file(filename);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 2:{
std::string filename;
std::cout << "Filename: ";
std::cin >> filename;
try{
write_to_file(this->_graph, filename);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 3:{
int num_vertices, num_edges;
std::cout << "Number of vertices: ";
std::cin >> num_vertices;
std::cout << "Number of edges: ";
std::cin >> num_edges;
try{
this->_graph = random_graph(num_vertices, num_edges);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 4:{
int v;
std::cout << "Vertex: ";
std::cin >> v;
try{
this->_graph.addVertex(v);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 5:{
int v;
std::cout << "Vertex: ";
std::cin >> v;
try{
this->_graph.removeVertex(v);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 6:{
int v1, v2, w;
std::cout << "Vertex 1: ";
std::cin >> v1;
std::cout << "Vertex 2: ";
std::cin >> v2;
std::cout << "Weight: ";
std::cin >> w;
try{
this->_graph.addEdge(v1, v2, w);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 7:{
int v1, v2;
std::cout << "Vertex 1: ";
std::cin >> v1;
std::cout << "Vertex 2: ";
std::cin >> v2;
try{
this->_graph.removeEdge(v1, v2);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 8:{
int v;
std::cout << "Vertex: ";
std::cin >> v;
try{
std::cout << "In degree: " << this->_graph.inDegree(v) << std::endl;
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 9:{
int v;
std::cout << "Vertex: ";
std::cin >> v;
try{
std::cout << "Out degree: " << this->_graph.outDegree(v) << std::endl;
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 10:{
int v1, v2;
std::cout << "Vertex 1: ";
std::cin >> v1;
std::cout << "Vertex 2: ";
std::cin >> v2;
try{
std::cout << "Cost: " << this->_graph.weight(v1, v2) << std::endl;
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 11:{
int v1, v2, w;
std::cout << "Vertex 1: ";
std::cin >> v1;
std::cout << "Vertex 2: ";
std::cin >> v2;
std::cout << "Weight: ";
std::cin >> w;
try{
this->_graph.weight(v1, v2, w);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 12:{
std::cout << "Number of vertices: " << this->_graph.numVertices() << std::endl;
break;
}
case 13:{
std::cout << "Number of edges: " << this->_graph.numEdges() << std::endl;
break;
}
case 14:{
std::unordered_set<int> vertices = this->_graph.vertices();
for(int vertex : vertices){
std::cout << vertex << " ";
}
std::cout << std::endl;
break;
}
case 15:{
std::unordered_map<std::pair<int, int>, int> edges = this->_graph.edges();
for(std::pair<std::pair<int, int>, int> edge : edges){
std::cout << edge.first.first << " " << edge.first.second << " " << edge.second << std::endl;
}
break;
}
case 16:{
int v;
std::cout << "Vertex: ";
std::cin >> v;
try{
std::unordered_set<int> inbounds = this->_graph.inbounds(v);
for(int vertex : inbounds){
std::cout << vertex << " ";
}
std::cout << std::endl;
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 17:{
int v;
std::cout << "Vertex: ";
std::cin >> v;
try{
std::unordered_set<int> outbounds = this->_graph.outbounds(v);
for(int vertex : outbounds){
std::cout << vertex << " ";
}
std::cout << std::endl;
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 18:{
std::cout<<"Inbound: \n";
std::unordered_set<int> vertices = this->_graph.vertices();
for(int vertex : vertices){
std::cout << vertex << ": ";
for(int in : this->_graph.inbounds(vertex)){
std::cout << in << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
vertices = this->_graph.vertices();
std::cout<<"Outbound: \n";
for(int vertex : vertices){
std::cout << vertex << ": ";
for(int out : this->_graph.outbounds(vertex)){
std::cout << out << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
std::cout<<"Edges: \n";
std::unordered_map<std::pair<int, int>, int> edges = this->_graph.edges();
for(std::pair<std::pair<int, int>, int> edge : edges){
std::cout << edge.first.first << " " << edge.first.second << " " << edge.second << std::endl;
}
break;
}
case 0:{
return;
}
default:{
std::cout << "Invalid command" << std::endl;
break;
}
}
}
}
@@ -0,0 +1,11 @@
#pragma once
#include "directed_graph.h"
class UI{
private:
DirectedGraph _graph;
public:
UI();
~UI();
void run();
};