% Red Regulatoria Genética
% Tenemos una serie de genes y sus interacciones representado por un grafo de influencia G=(N,E,s) dónde los vértices N son los genes, las aristas E son las interacciones y s:E-->{-,+} una función parcial.
% Tenemos una serie de datos experimentales que sabemos ciertos y queremos imponer que nuestro modelo los cumpla. No solo esto, sino que a ser posible buscamos encontrar el menor número de pasos necesario para modificar nuestro modelo y convertirlo en uno consistente.
% Importante!!!
% El grafo G es dirigido y debe cumplir que si (u,v) es una arista, entonces el producto signo(u)*signo(u,v)=signo(v).
%%%%%%%%%%%%%%%%
%% Predicados %%
%%%%%%%%%%%%%%%%
% vertice(X): X es un vértice.
% arco(X,Y): G tiene un arco de X en Y.
% entrada(X): X es un vértice de entrada.
% signoV(X,S): El modelo tiene signo S en el vértice X.
% signoA(X,Y,S): El modelo tiene signo S en el arco de X a Y.
% observadoV(X,S): Se ha observado que el vértice X tiene signo S.
% observadoA(X,Y,S): Se ha observado que el arco de X a Y tiene signo S.
% Definimos los signos
signo(mas;menos).
% Añadimos que son opuestos para hacer el "producto" de signos
opuesto(mas,menos).
opuesto(menos,mas).
%%%%%%%%%%%%%%%%
%% Generación %%
%%%%%%%%%%%%%%%%
% Asignar signos a arcos y vértices para nuestros múltiples modelos:
1 {signoV(V,S): signo(S)} 1 :- vertice(V).
1 {signoA(U,V,S): signo(S)} 1 :- arco(U,V).
%%%%%%%%%%%%%%%%%%%
%% Restricciones %%
%%%%%%%%%%%%%%%%%%%
% Si se observa un signo en un vértice, debe aparecer en el modelo:
signoV(V,S) :- observadoV(V,S).
% Si se observa un signo en un arco, debe aparecer en el modelo siempre que sea consistente:
signoA(U,V,S) :- observadoA(U,V,S), not error(U,V).
signoA(U,V,S) :- observadoA(U,V,T), opuesto(S,T), error(U,V).
%%%%%%%%%%%
%% Signo %%
%%%%%%%%%%%
% Si tenemos un arco (u,v), entonces signo(u)*signo(u,v)=signo(v):
resultado(V,mas) :- arco(U,V), signoA(U,V,S), signoV(U,S).
resultado(V,menos) :- arco(U,V), signoA(U,V,T), signoV(U,S), opuesto(S,T).
%%%%%%%%%%%%%%%%%%
%% Consistencia %%
%%%%%%%%%%%%%%%%%%
% No podemos tener un vértice que no sea añadido (entrada) y le asignemos un signo sin una razón (resultado):
:- signoV(U,S), not resultado(U,S), not entrada(U).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Generación de arcos erroneos %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Hacemos partes de E para considerar todas las posibilidades:
{error(U,V)} :- arco(U,V).
%%%%%%%%%%%%%%%%%%
%% Optimización %%
%%%%%%%%%%%%%%%%%%
%errores(N) :- N = #count{1 : error(U,V)}.
%#minimize{1,U,V : error(U,V)}.
%%%%%%%%%%%%%%%%%%%
%% Visualización %%
%%%%%%%%%%%%%%%%%%%
%#show error/2.
#show signoV/2.
#show signoA/3.
%#show resultado/2.
% Paso a realizar:
% 1. Generar un modelo
% Simplemente comentamos la sección de optimización.
% 2. Añadir observaciones distintas
% En función del modelo jugamos con cambiar algún signo.
% 3. Estudiar el número de modificaciones necesarias.
% 4. Es interesante escoger un subconjunto del modelo y ver si hay varias soluciones
% Para ello debemos imponer un solo resultado por vertice.
:- signo(S), opuesto(S,T), vertice(V),
resultado(V,S), resultado(V,T).