#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N=5e5+10;
const int mod=1e9+7;
struct graph{
	int cnte,head[N],to[N<<1],nxt[N<<1];
	void add_edge(int u,int v){
		to[++cnte]=v;
		nxt[cnte]=head[u];
		head[u]=cnte;
	}
}gp;
int n,m,cnt,u[N],v[N];
int ans,c[N];
int bridge[30][30],reach[30][30],dfn[N],low[N];
int lnk[N][2],f[N][2];
int read(){
	char ch=getchar();
	int x=0;
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return x;
}
void tarjan(int p,int from){
	dfn[p]=low[p]=++cnt;
	for(int i=gp.head[p];i;i=gp.nxt[i]){
		int v=gp.to[i];
		if(v==from)continue;
		if(!dfn[v]){
			tarjan(v,p);
			low[p]=min(low[p],low[v]);
		}
		else low[p]=min(low[p],dfn[v]);
		if(low[v]>dfn[p])bridge[v][p]=bridge[p][v]=1;
	}
}
int getc(int p,int col){
	int res=0;
	c[p]=col;
	for(int i=gp.head[p];i;i=gp.nxt[i]){
		int v=gp.to[i];
		if(c[v])continue;
		if(bridge[p][v]&&!reach[p][v])continue;
		res+=getc(v,col);
	}
	return res+1;
}
void check(){
	int col=0;
	for(int i=1;i<=n;i++){
		if(c[i])continue;
		int hv=getc(i,++col);
		ans=(ans+(1<<hv)-1)%mod;
	}
	for(int i=1;i<=n;i++)c[i]=0;
}
void dfs(int p){
	if(p==m+1){
		check();
		return ;
	}
	dfs(p+1);
	reach[u[p]][v[p]]=reach[v[p]][u[p]]=1;
	dfs(p+1);
	reach[u[p]][v[p]]=reach[v[p]][u[p]]=0;
}
void getans(int p,int from){
	if(!gp.nxt[gp.head[p]]){
	//	f[p]=lnk[p]=1;
		return ;
	}
	for(int i=gp.head[p];i;i=gp.nxt[i]){
		int v=gp.to[i];
		if(v==from)continue;
		getans(v,p);
		
	}
}
signed main(){
	freopen("barrack.in","r",stdin);
	freopen("barrack.out","w",stdout);
	n=read(),m=read();
	for(int i=1;i<=m;i++){
		u[i]=read(),v[i]=read();
		gp.add_edge(u[i],v[i]);
		gp.add_edge(v[i],u[i]);
	}
	if(n<=16&&m<=25){
		tarjan(1,0);
		dfs(1);
		cout<<ans;
	}
//	else
//	if(m==n-1){
//		getans(1,0);
//	}
	return 0;
}