#include <iostream>
#include <vector>
#include <queue>
#include <cstdio>
#define INF 2e+9
#define EPS 1e-14
#define mp make_pair
using namespace std;

struct edge{ int to,cost,limit; };
typedef pair<int,int> SV;//prev,vertex
typedef pair<int,SV> VV;//speed
typedef pair<double,VV> P;//cost

int main(){
	int n,m,s,g;
	while(cin >> n >> m,n){
		cin >> s >> g; s--;g--;
		vector<edge> G[30];
		double d[30][31][30];
		bool used[30][31][30] = {};
		for(int i = 0;i < n;i++){
			for(int j = 0;j <= 30;j++) {
				for(int k = 0;k < 30;k++){
					d[i][j][k] = INF;
				}
			}
		}
		d[s][0][s] = 0.0;
		for(int i = 0;i < m;i++) {
			int x,y,d,c;
			cin >> x >> y >> d >> c; x--;y--;
			G[x].push_back({y,d,c});
			G[y].push_back({x,d,c});
		}
		priority_queue<P,vector<P>,greater<P> > que;
		que.push(mp(0.0,mp(0,mp(s,s))));
		while(!que.empty()){
			P p = que.top();que.pop();
			double cost = p.first;
			int speed = p.second.first,prev = p.second.second.first,v = p.second.second.second;
			if(used[v][speed][prev]) continue;
			used[v][speed][prev] = false;
			for(int i = 0;i < G[v].size();i++){
				edge e = G[v][i];
				if(e.to == prev) continue;
				for(int j = max(1,speed - 1);j <= min(e.limit,speed + 1);j++){
					if(!used[e.to][j][v] && d[v][speed][prev] + (double)e.cost / (double)j < d[e.to][j][v]){
						d[e.to][j][v] = d[v][speed][prev] + (double)e.cost / (double)j;
						que.push(mp(d[e.to][j][v],mp(j,mp(v,e.to))));
					}
				}
			}
		}
		double mi = INF;
		for(int i = 0;i < n;i++) mi = min(d[g][1][i],mi);
		if(mi > (1e+9)) cout << "unreachable" << endl;
		else printf("%.8f\n",mi);
	}
	return 0;
}