#include <bits/stdc++.h>
using namespace std;

const double INF = 1e8;

struct Edge {
	int dst, cost, lim;
	Edge(){}
	Edge(int dst, int cost, int lim): dst(dst), cost(cost), lim(lim){}
};

struct State {
	int pos, prev, speed;
	double sum;
	State(){}
	State(int pos, int prev, int speed, double sum): pos(pos), prev(prev), speed(speed), sum(sum){}
	bool operator < (const State &t) const {return sum > t.sum;}
};

int n, m;
int st, gl;
vector<Edge> g[30];
double dist[30][30][31];

void solve()
{
	priority_queue<State> pq;
	fill_n(**dist, 30 * 30 * 31, INF);
	dist[st][st][0] = 0.0;
	pq.push(State(st, st, 0, 0.0));
	double res = INF;
	while (pq.size()){
		auto s = pq.top(); pq.pop();
		if (s.pos == gl && s.speed == 1) res = min(res, s.sum);
		if (dist[s.pos][s.prev][s.speed] < s.sum) continue;
		for (auto &e : g[s.pos]){
			if (e.dst == s.prev) continue;
			for (int ns = s.speed - 1; ns <= s.speed + 1; ns++){
				if (ns <= 0 || ns > e.lim) continue;
				double cost = (double)e.cost / ns;
				if (dist[e.dst][s.pos][ns] > s.sum + cost){
					dist[e.dst][s.pos][ns] = s.sum + cost;
					pq.push(State(e.dst, s.pos, ns, s.sum + cost));
				}
			}
		}
	}
	if (res == INF) puts("unreachable");
	else printf("%.20f\n", res);
}

int main()
{
	while (scanf("%d %d", &n, &m), n){
		scanf("%d %d", &st, &gl); --st; --gl;
		for (int i = 0; i < 30; i++) g[i].clear();
		for (int i = 0; i < m; i++){
			int x, y, d, c;
			scanf("%d %d %d %d", &x, &y, &d, &c); --x; --y;
			g[x].push_back(Edge(y, d, c));
			g[y].push_back(Edge(x, d, c));
		}
		solve();
	}
}