/// <summary> /// Funcion que manda a combinar el string con un array booleano /// </summary> /// <param name="s"></param> public void Combinacion(string s, List <Vertice> vertices1, Matriz matrizAdyacencia1 , Matriz matrizAdyacencia2, ref bool encuentraRelacion, ref List <funcion> listaFunciones) { bool[] esIgual = new bool[s.Length]; Combinaciones(s, "", esIgual, vertices1, matrizAdyacencia1, matrizAdyacencia2, ref encuentraRelacion, ref listaFunciones); }
/// <summary> /// Columna de matriz /// </summary> /// <param name="n"> Número de columna </param> /// <param name="m"> Matriz de la cuál se obtendrá la columna</param> /// <returns> Lista con columna correspondiente al número ingresado</returns> public static List <int> obtenerColumna(int n, Matriz m) { List <int> resultado = new List <int>(); for (int i = 0; i < m.matriz.Count; i++) { resultado.Add(m.matriz[i][n]); } return(resultado); }
/// <summary> /// Fila de matriz /// </summary> /// <param name="n"> Número de fila </param> /// <param name="matriz"> Matriz de la cuál se obtendrá la fila </param> /// <returns> Lista con fila correspondiente al número ingresado </returns> public static List <int> obtenerFila(int n, Matriz matriz) { List <int> resultado = new List <int>(); for (int i = 0; i < matriz.matriz[0].Count; i++) { resultado.Add(matriz.matriz[n][i]); } return(resultado); }
/// <summary> /// Transposición de matriz /// </summary> /// <param name="m"> Matriz a transponer </param> /// <returns> Matriz transpuesta de m </returns> public static Matriz transpose(Matriz m) { Matriz resultado = new Matriz(); for (int i = 0; i < m.matriz.Count(); i++) { List <int> tmpFila = obtenerColumna(i, m); resultado.matriz.Add(tmpFila); } return(resultado); }
/// <summary> /// Verifica que dos matrices sean equivaltnes /// </summary> /// <param name="cmp"> Matriz a comparar </param> /// <returns> Verdadero si las matrices contienen los mismos datos en el mismo /// orden</returns> public bool equivalent(Matriz cmp) { // Compara cada una de las posiciones en las dos matrices. for (int i = 0; i < matriz.Count; i++) { for (int j = 0; j < matriz[0].Count; j++) { if (matriz[i][j] != cmp.matriz[i][j]) { return(false); } } } return(true); }
/// <summary> /// Obtiene cada caracter de la cadena y según el ID así ingresa los vertices /// a una lista /// </summary> /// <param name="permutacion"></param> public void agregarListaProb(string permutacion, List <Vertice> vertices1, Matriz matrizAdyacencia1, Matriz matrizAdyacencia2, ref bool encuentraRelacion, ref List <funcion> listaFunciones) { for (int i = 0; i < permutacion.Length; i++) { for (int j = 0; j < listaVertices.Count; j++) { if ((int)permutacion[i] == listaVertices[j].ID) { // Si el ID de la cadena es igual al ID de un vertice se agrega // ese vertice al array numeros.Add(listaVertices[j]); break; } } } List <Vertice> vertices2 = new List <Vertice>(numeros); if (vertices1.Count > 9) { // En caso de que la cantidad de vértices sea mayor a nueve, solo se // genera una función de isomorfismo. Matriz posibleMatriz = OperacionesMatriz.generarMatrizPosible(vertices1, vertices2); if (Isomorfismo.gradosListasCoinciden(vertices1, vertices2) && // Es verdadero si paras el producto de // (posibleMatriz)*(matrizAdyacencia2)*(matryzAdyacencia2Transpuesta) // se genera la matriz de adyacencia del primer grafo. matrizAdyacencia1.equivalent(OperacionesMatriz.multiplicar( posibleMatriz, matrizAdyacencia2, OperacionesMatriz.transpose( posibleMatriz)))) { encuentraRelacion = true; funcion f = new funcion(); f.V1 = vertices1; f.V2 = vertices2; listaFunciones.Add(f); funcionIsomorfica = listaFunciones; } } else { listasProbabilidades.Add(vertices2); } }
/// <summary> /// Multiplicación de dos matrices /// </summary> /// <param name="m1"> Primera matriz </param> /// <param name="m2"> Segunda matriz </param> /// <returns> Devuelve el producto punto entre dos matrices. </returns> public static Matriz multiplicar(Matriz m1, Matriz m2) { Matriz resultado = new Matriz(); for (int i = 0; i < m1.matriz.Count; i++) { List <int> tmpFila = new List <int>(); for (int j = 0; j < m1.matriz[0].Count; j++) { tmpFila.Add(productoFilaColumna(obtenerFila(i, m1), obtenerColumna(j, m2))); } resultado.matriz.Add(tmpFila); } return(resultado); }
/// <summary> /// Funcion que combina el string y devuelve todas las combinaciones posibles /// del mismo tamaño del string que recibe. /// </summary> /// <param name="cadena"></param> /// <param name="combinacion"></param> /// <param name="iguales"></param> public void Combinaciones(string cadena, string combinacion, bool[] iguales, List <Vertice> vertices1, Matriz matrizAdyacencia1, Matriz matrizAdyacencia2, ref bool encuentraRelacion, ref List <funcion> listaFunciones) { if (encuentraRelacion) { return; } if (cadena.Length == combinacion.Length) { // Se manda a agregar la combinación en las utilidades del permutador. PermutadorUtilities.getInstancia().agregarListaProb(combinacion, vertices1, matrizAdyacencia1, matrizAdyacencia2, ref encuentraRelacion, ref listaFunciones); /* Se limpia el array que se utilizo para agregar cada vertice según * su ID en la cadena enviada. */ PermutadorUtilities.getInstancia().clearNumeros(); } //Se generan todas las combinaciones y si son iguales se descartan for (int i = 0; i < iguales.Length; i++) { if (encuentraRelacion) { return; } if (!iguales[i]) { if (encuentraRelacion) { break; } iguales[i] = true; Combinaciones(cadena, combinacion + cadena[i], iguales, vertices1, matrizAdyacencia1, matrizAdyacencia2, ref encuentraRelacion, ref listaFunciones); iguales[i] = false; } } }
/// <summary> /// Matriz de incidencia entre vértices de distintos grafos /// </summary> /// <param name="v1"> Vértices de primer grafo </param> /// <param name="v2"> Vértices de segundo grafo </param> /// <returns> Matriz de incidencia entre vértices de distintos grafos </returns> public static Matriz generarMatrizPosible(List <Vertice> v1, List <Vertice> v2) { Matriz matrix = new Matriz(); // Llena la matriz con ceros for (int i = 0; i < v1.Count; i++) { List <int> fila = new List <int>(); for (int j = 0; j < v2.Count; j++) { fila.Add(0); } matrix.matriz.Add(fila); } // Agrega unos por cada coincidencia entre vértice del primer grafo y // vértice del segundo grafo. for (int i = 0; i < v1.Count; i++) { matrix.matriz[int.Parse(v1[i].etiqueta)][int.Parse(v2[i].etiqueta)] = 1; } return(matrix); }
/// <summary> /// Mulstiplicación de tres matrices /// </summary> /// <param name="m1"> Primera matriz </param> /// <param name="m2"> Segudna matriz </param> /// <param name="m3"> Tercera matriz </param> /// <returns> Producto punto de las tres matrices operadas de izquierda a derecha /// </returns> public static Matriz multiplicar(Matriz m1, Matriz m2, Matriz m3) { return(multiplicar(multiplicar(m1, m2), m3)); }
/// <summary> /// Función encargada de buscar y, en caso de encontrar, generar tantas funciones /// de isomorfismo como sean posibles. /// </summary> /// <param name="g1"> Primer grafo </param> /// <param name="g2"> Segundo grafo </param> /// <param name="barraProgreso"> Barra que indicará el progreso de la búsqueda de /// las funciones de isomorfismo </param> /// <param name="cbFunciones"> comboBox en el que se almacenarán los nombres de /// las funciones a medida que vayan siendo encontradas </param> /// <param name="listaFunciones"> Lista en la que se almacenará la información de /// cada una de las funciones encontradas</param> /// <returns></returns> static bool encuentraFuncionAdyacencia(Grafo g1, Grafo g2, ProgressBar barraProgreso, ComboBox cbFunciones, ref List <funcion> listaFunciones) { // Variable booleana que indica si se encontró o no al menos una función de // isomorfismo para los dos grafos dados bool pruebaSuperada = false; // Instancia e inicia un stopWatch para verificar el tiempo de que el algo- // ritmo tarda en encontrar las funciones Stopwatch sw = new Stopwatch(); sw.Start(); // Lista que almacena las funciones generadas. List <funcion> lstFuncionesEncontradas = new List <funcion>(); // Instancia que servirá para obtener todas las permutaciones de vértices en // un grafo PermutadorVertices p = new PermutadorVertices(); // Lista que almacena los vértices del primer grafo List <Vertice> vertices1 = g1.lstVertices; // Se crean las matrices de adyacencia de los dos grafos Matriz matrizAdyacencia1 = g1.matrizAdyacencia(); Matriz matrizAdyacencia2 = g2.matrizAdyacencia(); // Lista de que almacena todas las posibles permutaciones de vértices del // primer grafo List <List <Vertice> > permutacionesV2 = p.combinar(g2.lstVertices, vertices1, matrizAdyacencia1, matrizAdyacencia2, ref pruebaSuperada, ref listaFunciones); barraProgreso.Maximum = permutacionesV2.Count; int numeroFunciones = 0; // Realiza el proceso por cada una de las permutaciones realizadas para el // listado de vértices del segundo grafo if (pruebaSuperada) { cbFunciones.Items.Add(string.Format("Funcion #1", numeroFunciones)); sw.Stop(); } else { foreach (List <Vertice> vertices2 in permutacionesV2) { barraProgreso.Value++; // Se genera una posible matriz con los dos listados de vértices Matriz posibleMatriz = OperacionesMatriz.generarMatrizPosible(vertices1, vertices2); // Verifica que en la permutación actual almenos coincidan los grados de // los vértices, de lo contrario es inútil continuar buscando la matriz. if (gradosListasCoinciden(vertices1, vertices2) && // Es verdadero si para el producto de // (posibleMatriz)*(matrizAdyacencia2)*(matryzAdyacencia2Transpuesta) // se genera la matriz de adyacencia del primer grafo. matrizAdyacencia1.equivalent(OperacionesMatriz.multiplicar( posibleMatriz, matrizAdyacencia2, OperacionesMatriz.transpose( posibleMatriz)))) { funcion funcionNueva = new funcion(); // Se crea una nueva función funcionNueva.V1 = vertices1; funcionNueva.V2 = vertices2; // La función creada se añade a la lista de funciones lstFuncionesEncontradas.Add(funcionNueva); numeroFunciones++; cbFunciones.Items.Add(string.Format("Funcion #{0}", numeroFunciones)); pruebaSuperada = true; if (vertices1.Count > 9) { break; } } } } listaFunciones = lstFuncionesEncontradas; sw.Stop(); // Muestra información del proceso al usuario string msg = String.Format("El programa tardó {0} minutos {1} segundos con {2} milisegu" + "ndos en intentar encontrar las funciones", sw.Elapsed.Minutes, sw.Elapsed.Seconds, sw.Elapsed.Milliseconds); if (vertices1.Count > 9) { msg = msg + "\nEl proyecto aún no puede generar todas las funciones de isomorfismo " + "para una cantidad de vértices mayor a 9.\nSi desea colaborar al proyecto puede " + "aportar al siguiente repositorio: https://github.com/MynorXico/ProyectoIsomorfismo"; } MessageBox.Show(msg, "Información", MessageBoxButtons.OK, MessageBoxIcon.Information); return(pruebaSuperada); }