#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <queue>

using namespace std;

#define MAX 30
#define INF 10000000.0
struct S{
	int e,s,b;
};

struct S2{
	int d,c,to;
};

int main(){

	int n,m;
	int s,g;
	int x,y,d,c;
	int min;
	float cost[MAX+1][MAX+1][MAX+1];
	S point,tmp;
	S2 nod;
	vector<S2> ed[MAX+1];
	queue<S> no;

	while(1){

		cin>>n>>m;
		if(n==0&&m==0) break;

		for(int i=1;i<=n;i++){
			if(!ed[i].empty()) ed[i].clear();
		}

		for(int i=0;i<=30;i++){
			for(int j=0;j<=30;j++){
				for(int k=0;k<=30;k++){
					cost[i][j][k]=INF;
				}
			}
		}

		cin>>s>>g;
		point.e=s,point.s=0,point.b=0;
		cost[0][s][0]=0;

		for(int i=0;i<m;i++){
			cin>>x>>y>>d>>c;
			nod.c=c,nod.d=d,nod.to=y;;
			ed[x].push_back(nod);
			nod.to=x;
			ed[y].push_back(nod);
		}

		no.push(point);
		while(!no.empty()){
			point=no.front();
			no.pop();
			for(int i=0;i<ed[point.e].size();i++){
				if(point.b!=ed[point.e][i].to){
					for(int j=-1;j<=1;j++){
						if(point.s+j>0&&point.s+j<=30){
							//if(point.s+j==1&&ed[point.e][i].to==g) cout<<cost[point.s][point.e]+((double)ed[point.e][i].d/(point.s+j))<<endl;
							if(ed[point.e][i].c>=point.s+j){
								//cout<<point.e<<","<<point.b<<","<<point.s<<","<<ed[point.e][i].to<<","<<cost[point.s][point.e]<<"^^"<<cost[point.s][point.e]+(double)ed[point.e][i].d/(point.s+j)<<endl;
								if(cost[point.s+j][ed[point.e][i].to][point.e]>cost[point.s][point.e][point.b]+((float)ed[point.e][i].d/(point.s+j))){
									cost[point.s+j][ed[point.e][i].to][point.e]=cost[point.s][point.e][point.b]+((float)ed[point.e][i].d/(point.s+j));
									tmp.e=ed[point.e][i].to;
									tmp.s=point.s+j;
									tmp.b=point.e;
									no.push(tmp);
								}
							}
						}
					}
				}
			}
		}
		min=0;
		for(int i=1;i<=30;i++){
			if(cost[1][g][i]<cost[1][g][min]) min=i;
		}
		if(min==0) printf("unreachable\n");
		else printf("%.5f\n",cost[1][g][min]);
	}

}