// AOJ 1162
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1162&lang=jp

#include <iostream>
#include <set>
#include <queue>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;

const double eps = 1e-9;
const double inf = (double)(1<<24);

class Node {
public:
    double time;
    int v, town, prev;
    Node() {}
    Node( double time_, int v_, int town_, int prev_ ) 
    {
        time = time_;
        v = v_;
        town = town_;
        prev = prev_;
    }
    bool operator < ( const Node& right ) const 
    {
        return time > right.time;
    }
    bool operator > ( const Node& right ) const
    {
        return time < right.time;
    }
    bool operator == ( const Node& right ) const
    {
        return v == right.v && town == right.town && prev == right.prev;
    }
};
typedef priority_queue <Node> QUEUE;
const int size = 31;

int n, m;
bool P[size][size];
double G[size][size];
double MC[size][size][size];
int L[size][size];
int CN[size][size];
int CN_count[size];

// dijkstra
void solve( int start, int goal )
{
    // init
    QUEUE Q;
    Node start_node( 0.0, 1, start, -1 );
    Q.push( start_node );

    // proc
    while ( !Q.empty() ) {
        Node node = Q.top();
        Q.pop();

        // proc init
        double time = node.time;
        int v = node.v;
        int town = node.town;
        int prev = node.prev;

        // goal
        if ( town == goal && v == 1 ) {
            printf( "%.5f\n", time );
            return;
        }

        // move
        for ( int i = 0; i < CN_count[town]; i++ ) {
            int next_town = CN[town][i];
            if ( next_town == prev ) continue;
            for ( int j = 1; j >= -1; j-- ) {
                int next_v = v + j;
                if ( prev == -1 && next_v != 1 ) continue;
                if ( next_v <= 0 || next_v > L[town][next_town] ) continue;
                double cost = (double)G[town][next_town] / next_v;
                double next_time = time + cost;
                int next_prev = town;

                if ( next_time > MC[town][next_v][next_town] || fabs( next_time - MC[town][next_v][next_town] ) < eps ) continue;
                MC[town][next_v][next_town] = next_time;
                Node next_node( next_time, next_v, next_town, next_prev );
                Q.push( next_node );
            }
        }
    }

    cout << "unreachable" << endl;
}

int main( void )
{
    while ( cin >> n >> m ) {
        // quit
        if ( n == 0 && m == 0 ) break;

        // init
        for ( int i = 0; i < size; i++ ) {
            CN_count[i] = 0;
            for ( int j = 0; j < size; j++ ) {
                P[i][j] = false;
                for ( int k = 0; k < size; k++ ) MC[k][i][j] = inf;
                G[i][j] = inf;
                L[i][j] = 0;
            }
        }

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

            P[x][y] = P[y][x] = true;
            G[x][y] = G[y][x] = d;
            L[x][y] = L[y][x] = c;
        }

        for ( int i = 0; i < n; i++ ) {
            for ( int j = 0; j < n; j++ ) {
                if ( i == j ) continue;
                if ( P[i][j] ) CN[i][CN_count[i]++] = j;
            }
        }

        solve( s-1, g-1 );
    }
    return 0;
}

Measured memory_bytes: 1712