#include <iostream>
#include <queue>
#include <utility>
#include <cfloat>
#include <cmath>
#include <cstdio>
using namespace std;
#define EPS 1e-8
 
struct P{
  double t;
  char v,p,pre;
  P(double T=0.0,int V=0,int pp=0,int PRE=0){
    t=T;v=V;p=pp;pre=PRE;
  };
  bool operator<(const P &p)const{
    return t>p.t;
  }
};
struct Path{
  char d,c;
  Path(int D=0,int C=0){ d=D;c=C;};
};
 
int main(){
  int n,m, s,g, x,y,d,c;
  Path path[30][30];

 
  while( cin>>n>>m && (n|m) ){
    cin >> s >> g;
    s--; g--;
    for( int i=0;i<n;i++ )
      for( int j=0;j<n;j++ ){
	path[i][j].d=-1.0; path[i][j].c=-1;
      }
 
    for( int i=0;i<m;i++ ){
      cin >> x >> y >> d >> c;
      x--;y--;
      path[x][y].d=d; path[x][y].c=c;
      path[y][x] = path[x][y];
    }
 
    double cost[30][35][30]; // place,velocity, pre
    int dv[3] = {1,0,-1};
    for( int i=0;i<n;i++ )
      for( int j=1;j<31;j++ )
	for( int k=0;k<n;k++ )
	  cost[i][j][k] = DBL_MAX;

    priority_queue<P> q;//    while( !q.empty() ) q.pop();
    for( int i=0;i<n;i++ ){
      if( path[s][i].c<0 ) continue;
      q.push( P(path[s][i].d,1,i,s) );//t ,v, np, pre
      cost[i][1][s] = path[s][i].d;
    }

    double ans = DBL_MAX; 
    while( !q.empty() ){
      P p = q.top(); q.pop();
      double t = p.t;
      int v=p.v, np=p.p, pre=p.pre;
      if( np==g && v==1 ){
	ans = t;
	break;
      }
 
      for( int i=0;i<n;i++ ){
	if( path[np][i].c<0 ) continue;// たどり着けないノード
	if( i==pre ) continue; // 前回のノード
	
	for( int j=0;j<3;j++ ){
	  int nv = v + dv[j];
	  if( nv==0 || nv>path[np][i].c )    continue;
	  double nCost = t + (double)path[np][i].d/nv;
	  if( nCost>cost[g][1][np] || fabs(nCost-cost[g][1][np])<EPS ) continue;
	  if( cost[i][nv][np] < nCost ) continue;
	  if( fabs(cost[i][nv][np]-nCost)<EPS ) continue;
	  cost[i][nv][np]=nCost;
	  
	  q.push( P(nCost,nv,i,np) );
	}
      }
      
    }
    if( fabs(ans-DBL_MAX)<EPS )
      cout << "unreachable" << endl;
    else
      printf("%.6lf\n",ans);
 
  }
  return 0;
}