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

int N,M;

double H[33][33][33];
const double INF = 1e100;

struct state{
  int n,p,v;
  double c;
  state(int n,int p,int v,double c) : n(n),p(p),v(v),c(c) {}
  bool operator<(const state &st) const{
    return c > st.c;
  }
};

struct edge {
  int to,d,c;
  edge(int to,int d,int c) : to(to),d(d),c(c) {}
};

vector<edge> G[33];

void dijk(int s,int g){
  fill(H[0][0],H[32][32],INF);

  priority_queue<state> q;
  q.push( state( s, s, 0, 0.0 ) );
  H[s][s][0] = 0.0;
  while( !q.empty() ){
    state p = q.top(); q.pop();
    if( p.c > H[p.n][p.p][p.v] ) continue;
    if( p.n == g && p.v == 1 ) {
      printf("%.9lf\n", p.c); return;
    }
    for(int i=0;i<(int)G[p.n].size();i++){
      edge e = G[p.n][i];
      if( e.to == p.p ) continue;
      for(int nv=p.v-1;nv<=p.v+1;nv++){
        if( 0 < nv && nv <= e.c ) {
          double nc = p.c + (double)e.d/(double)nv;
          if( H[e.to][p.n][nv] > nc ){
            H[e.to][p.n][nv] = nc;
            q.push( state( e.to, p.n, nv , nc ) );
          }
        }
      }
    }
  }
  cout << "unreachable" << endl;
}

int main(){
  int s,g;
  while(cin >> N >> M && (N|M) ){
    cin >> s >> g;
    --s; --g;
    for(int i=0;i<M;i++){
      int x,y,d,c;
      cin >> x >> y >> d >> c;
      --x;--y;
      G[x].push_back( edge(y,d,c) );
      G[y].push_back( edge(x,d,c) );
    }
    dijk( s, g );
    for(int i=0;i<N;i++)
      G[i].clear();
  }
}