#include<bits/stdc++.h>
using namespace std;
inline int read(){
int ret=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-f;for(;isdigit(ch);ch=getchar())ret=(ret<<1)+(ret<<3)+(ch&15);return ret*f;
}
#define maxn 500005
#define maxe 2000005
const int TT (1e9+7);
struct AC{
	int x,y;
}e[maxe];
bool dif(AC a,AC b){
	return ((a.x==b.y)and(a.y==b.x))or((a.x==b.x)and(a.y==b.y));
}
int n,m,vis[24],ab[24],que[30],son[maxe],lnk[maxn],nxt[maxe],tot;void add(int x,int y){nxt[++tot]=lnk[x],son[lnk[x]=tot]=y;}
int mi[24];
void init(){mi[0]=1;
	for(int i=1;i<=m;i++)mi[i]=(mi[i-1]<<1)%TT;
	for(int i=1;i<=m;i++)add(e[i].x=read()-1,e[i].y=read()-1),add(e[i].y,e[i].x);;int ans=0;
	for(int now=1;now<(1<<n);now++){
		int all=0;for(int j=0;j<n;j++)if(now &(1<<j)){ab[que[1]=j]=1;break;}
		for(int i=1;i<=m;i++){memset(ab,0, sizeof ab);ab[que[1]]=1;
			for(int head=0,tail=1;head<=tail;)for(int j=lnk[que[++head]];j;j=nxt[j])if(!ab[son[j]] and !dif((AC){que[head],son[j]},e[i]))ab[que[++tail]=son[j]]=1;
		for(int j=0;j<n;j++)if((now &(1<<j))and !ab[j]){all++;break;};
		}ans=(ans+mi[m-all])%TT;
	}printf("%d",ans);
}
void init2(){
	mi[0]=1;
	for(int i=1;i<=m;i++)mi[i]=(mi[i-1]<<1)%TT;printf("%lld\n",(n*(n-1)*mi[n-3]+n*mi[n-1])%TT);
}
int main(){
	freopen("barrack.in","r",stdin);
	freopen("barrack.out","w",stdout);
	n=read(),m=read();
	if(n<=20)init();else init2();
	return 0;
} 