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

// 🔴

// O(ElogE)

// pq<pair> はfirstが大きい順に出てくるのですか？
// s:= 開始ノード  v:= 頂点数  adjlist:= 隣接リスト (first:= コスト   second:= 行先)
vector<double> dijk(int s, int v, vector<vector<pair<double, int> > > adjlist){
    
    priority_queue <pair<double, int> > wait;
    vector<double> result(v, INF);

    //スタート地点を追加
    result[s] = 0;
    wait.push(make_pair(0, s));

    //ダイクストラ本体
    while(!wait.empty()){    //waitが空になるまで

        int nowpoint = wait.top().second;
        double nowcost = -wait.top().first;
        wait.pop();

        if(result[nowpoint] < nowcost) continue;


        //今いる頂点と隣接しているすべての頂点をなめる
        for(int i = 0; i < adjlist[nowpoint].size(); i++){

            int nextpoint = adjlist[nowpoint][i].second;
            double nextcost = nowcost + adjlist[nowpoint][i].first;
            //現時点より安く到達できそうであれば、結果を更新して優先度付きキューに格納
            if(result[nextpoint] > nextcost){
                result[nextpoint] = nextcost;
                wait.push(make_pair(-nextcost, nextpoint));
            }
        }
    }
    
    return result;         //結果列を返す
}

int main(){


    while(1){
        int n, m; cin >> n >> m;
        if(!n) break;
        int s, g; cin >> s >> g;
        s--;
        g--;
        vector<vector<vector<int> > > Map(n, vector<vector<int> > (n, vector<int> (31)));
        int idx = 1;
        for(int i = 0; i < n; i++){
            for(int j = 0; j < n; j++){
                for(int k = 1; k <= 30; k++){
                    Map[i][j][k] = idx;
                    idx++;
                }
            }
        }

        vector<vector<pair<double, int> > > adjlist(30000);      //first := コスト　second := 行先

        for(int i = 0; i < m; i++){
            int x, y, c; double d; cin >> x >> y >> d >> c;
            x--;
            y--;

            if(x == s){
                int now = 0;
                int next = Map[y][x][1];
                double cost = d;
                adjlist[now].push_back(make_pair(cost, next));                
            }

            if(y == s){
                int now = 0;
                int next = Map[x][y][1];
                double cost = d;
                adjlist[now].push_back(make_pair(cost, next));                
            }

            for(int pre = 0; pre < n; pre++){
            for(int v = 1; v <= 30; v++){

                int now = Map[x][pre][v];
                if(pre == y || pre == x) continue;
                
                //三方向
                //-1
                int next_v = v - 1;
                if(0 < next_v && next_v <= c){
                    int next = Map[y][x][next_v];
                    double cost = d / next_v;
                    adjlist[now].push_back(make_pair(cost, next));                    
                }

                //そのまま
                next_v = v;
                if(0 < next_v && next_v <= c){
                    int next = Map[y][x][next_v];
                    double cost = d / next_v;
                    adjlist[now].push_back(make_pair(cost, next));                    
                }

                //+1
                next_v = v + 1;
                if(0 < next_v && next_v <= c){
                    int next = Map[y][x][next_v];
                    double cost = d / next_v;
                    adjlist[now].push_back(make_pair(cost, next));                    
                }

            }
            }

            for(int pre = 0; pre < n; pre++){
            for(int v = 1; v <= 30; v++){

                int now = Map[y][pre][v];
                if(pre == x || pre == y) continue;

                //三方向
                //-1
                int next_v = v - 1;
                if(0 < next_v && next_v <= c){
                    int next = Map[x][y][next_v];
                    double cost = d / next_v;
                    adjlist[now].push_back(make_pair(cost, next));                    
                }

                //そのまま
                next_v = v;
                if(0 < next_v && next_v <= c){
                    int next = Map[x][y][next_v];
                    double cost = d / next_v;
                    adjlist[now].push_back(make_pair(cost, next));                    
                }

                //+1
                next_v = v + 1;
                if(0 < next_v && next_v <= c){
                    int next = Map[x][y][next_v];
                    double cost = d / next_v;
                    adjlist[now].push_back(make_pair(cost, next));                    
                }
            }
        }
        }
        
        int S = 0;
        double ans = INF;
        vector<double> result(30000);
        result = dijk(0, 30000, adjlist);

        for(int i = 0; i < n; i++){
            if(i == g) continue;
            int G = Map[g][i][1];
            ans = min(ans, result[G]);
        }

        if(ans >= INF) cout << "unreachable" << endl; 
        else printf("%.10f\n", ans);
    }

    return 0;
}



Measured memory_bytes: 90152