void build_connectivity_graph()

in grolp/gen/ff_planner/inst_final.c [1925:2794]


void build_connectivity_graph( void )

{

  int i, j, k, l, n_op, n_ef, fl, ef, ef_, m;
  float val;
  Action *a;
  ActionEffect *e;

  gnum_ft_conn = gnum_relevant_facts;
  gnum_fl_conn = gnum_relevant_fluents;
  gnum_op_conn = gnum_actions;
  gft_conn = ( FtConn * ) calloc( gnum_ft_conn, sizeof( FtConn ) );
  gfl_conn = ( FlConn * ) calloc( gnum_fl_conn, sizeof( FlConn ) );
  gop_conn = ( OpConn * ) calloc( gnum_op_conn, sizeof( OpConn ) );
  gef_conn = ( EfConn * ) calloc( lnum_effects, sizeof( EfConn ) );
  gnum_ef_conn = 0;

  for ( i = 0; i < gnum_ft_conn; i++ ) {
    gft_conn[i].num_PC = 0;
    gft_conn[i].num_A = 0;
    gft_conn[i].num_D = 0;

    gft_conn[i].axiom_added = FALSE;

    gft_conn[i].rand = random() % BIG_INT;
  }

  gnum_real_fl_conn = 0;
  for ( i = 0; i < gnum_fl_conn; i++ ) {
    gfl_conn[i].num_PC = 0;
    gfl_conn[i].num_IN = 0;
    gfl_conn[i].num_AS = 0;

    if ( grelevant_fluents_lnf[i] == NULL ) {
      gfl_conn[i].artificial = FALSE;
      gnum_real_fl_conn++;
      gfl_conn[i].rand = random() % BIG_INT;
    } else {
      /* once we're in here we'll stay as all artificial 
       * fluents are appended to the end.
       */
      gfl_conn[i].artificial = TRUE;
      gfl_conn[i].lnf_F = ( int * ) 
	calloc( grelevant_fluents_lnf[i]->num_pF, sizeof( int ) );
      gfl_conn[i].lnf_C = ( float * ) 
	calloc( grelevant_fluents_lnf[i]->num_pF, sizeof( float ) );
      for ( j = 0; j < grelevant_fluents_lnf[i]->num_pF; j++ ) {
	gfl_conn[i].lnf_F[j] = grelevant_fluents_lnf[i]->pF[j];
	gfl_conn[i].lnf_C[j] = grelevant_fluents_lnf[i]->pC[j];
      }
      gfl_conn[i].num_lnf = grelevant_fluents_lnf[i]->num_pF;
    }
  }


  /* why not do this here?
   */
  gmneed_start_D = ( Bool * ) calloc( gnum_real_fl_conn, sizeof( Bool ) );
  gmneed_start_V = ( float * ) calloc( gnum_real_fl_conn, sizeof( float ) );


  for ( i = 0; i < gnum_op_conn; i++ ) {
    gop_conn[i].num_E = 0;
  }

  for ( i = 0; i < lnum_effects; i++ ) {
    gef_conn[i].num_PC = 0;
    gef_conn[i].num_f_PC = 0;
    gef_conn[i].num_A = 0;
    gef_conn[i].num_D = 0;
    gef_conn[i].num_I = 0;
    gef_conn[i].num_IN = 0;
    gef_conn[i].num_AS = 0;

    gef_conn[i].illegal = FALSE;
    gef_conn[i].removed = FALSE;
  }


  /* determine if there are conditional effects.
   */
  gconditional_effects = FALSE;
  for ( a = gactions; a; a = a->next ) {
    for ( i = 0; i < a->num_effects; i++ ) {
      e = &(a->effects[i]);
      if ( e->num_conditions > 0 ) {
	break;
      }
      if ( e->num_lnf_conditions > 0 ) {
	break;
      }
    }
    if ( i < a->num_effects ) break;
  }
  if ( a ) {
    printf("\n\ntask contains conditional effects. turning off state domination.\n\n");
    gconditional_effects = TRUE;
  }

  n_op = 0;
  n_ef = 0;
  for ( a = gactions; a; a = a->next ) {
    gop_conn[n_op].action = a;
    gop_conn[n_op].axiom = a->axiom;
    if ( a->num_effects == 0 ) {
      continue;
    }

    gop_conn[n_op].E = ( int * ) calloc( a->num_effects, sizeof( int ) );
    for ( i = 0; i < a->num_effects; i++ ) {
      e = &(a->effects[i]);
      gef_conn[n_ef].cost = e->cost;
      if ( e->removed ) {
	/* this one disappeared through summarization
	 */
	continue;
      }
      gop_conn[n_op].E[gop_conn[n_op].num_E++] = n_ef;
      gef_conn[n_ef].op = n_op;
      if ( e->illegal ) {
	gef_conn[n_ef].illegal = TRUE;
      }

      /*****************************CONDS********************************/
      gef_conn[n_ef].PC = ( int * ) 
	calloc( e->num_conditions + a->num_preconds, sizeof( int ) );
      for ( j = 0; j < a->num_preconds; j++ ) {
	for ( k = 0; k < gef_conn[n_ef].num_PC; k++ ) {
	  if ( gef_conn[n_ef].PC[k] == a->preconds[j] ) break;
	}
	if ( k < gef_conn[n_ef].num_PC ) continue;
	gef_conn[n_ef].PC[gef_conn[n_ef].num_PC++] = a->preconds[j];
      }
      for ( j = 0; j < e->num_conditions; j++ ) {
	for ( k = 0; k < gef_conn[n_ef].num_PC; k++ ) {
	  if ( gef_conn[n_ef].PC[k] == e->conditions[j] ) break;
	}
	if ( k < gef_conn[n_ef].num_PC ) continue;
	gef_conn[n_ef].PC[gef_conn[n_ef].num_PC++] = e->conditions[j];
      }
      /* similar thing for numeric conditions.
       */
      gef_conn[n_ef].f_PC_comp = ( Comparator * ) 
	calloc( e->num_lnf_conditions + a->num_lnf_preconds, sizeof( Comparator ) );
      gef_conn[n_ef].f_PC_fl = ( int * ) 
	calloc( e->num_lnf_conditions + a->num_lnf_preconds, sizeof( int ) );
      gef_conn[n_ef].f_PC_c = ( float * ) 
	calloc( e->num_lnf_conditions + a->num_lnf_preconds, sizeof( float ) );
      gef_conn[n_ef].f_PC_direct_comp = ( Comparator * ) calloc( gnum_fl_conn, sizeof( Comparator ) );
      for ( j = 0; j < gnum_fl_conn; j++ ) {
	gef_conn[n_ef].f_PC_direct_comp[j] = IGUAL;
      }
      gef_conn[n_ef].f_PC_direct_c = ( float * ) calloc( gnum_fl_conn, sizeof( float ) );
      for ( j = 0; j < a->num_lnf_preconds; j++ ) {
	if ( a->lnf_preconds_lh[j]->num_pF != 1 ) {
	  printf("\n\nnon 1 card. in comp lh final pre copyover.\n\n");
	  exit( 1 );
	}
	for ( k = 0; k < gef_conn[n_ef].num_f_PC; k++ ) {
	  if ( gef_conn[n_ef].f_PC_fl[k] == a->lnf_preconds_lh[j]->pF[0] ) break;
	}
	if ( k < gef_conn[n_ef].num_f_PC ) {
	  if ( a->lnf_preconds_rh[j] < gef_conn[n_ef].f_PC_c[k] ) {
	    /* weaker cond
	     */
	    continue;
	  }
	  if ( a->lnf_preconds_rh[j] > gef_conn[n_ef].f_PC_c[k] ) {
	    /* stronger cond
	     */
	    gef_conn[n_ef].f_PC_c[k] = a->lnf_preconds_rh[j];
	    gef_conn[n_ef].f_PC_comp[k] = a->lnf_preconds_comp[j];
	    continue;
	  }
	  if ( a->lnf_preconds_comp[j] == GE ) {
	    /* we might need to strengthen our comp
	     */
	    gef_conn[n_ef].f_PC_comp[k] = GE;
	  }
	} else {
	  gef_conn[n_ef].f_PC_comp[gef_conn[n_ef].num_f_PC] = a->lnf_preconds_comp[j];
	  gef_conn[n_ef].f_PC_fl[gef_conn[n_ef].num_f_PC] = a->lnf_preconds_lh[j]->pF[0];
	  gef_conn[n_ef].f_PC_c[gef_conn[n_ef].num_f_PC++] = a->lnf_preconds_rh[j];
	}
      }
      for ( j = 0; j < e->num_lnf_conditions; j++ ) {
	if ( e->lnf_conditions_lh[j]->num_pF != 1 ) {
	  printf("\n\nnon 1 card. in comp lh final cond copyover.\n\n");
	  exit( 1 );
	}
	for ( k = 0; k < gef_conn[n_ef].num_f_PC; k++ ) {
	  if ( gef_conn[n_ef].f_PC_fl[k] == e->lnf_conditions_lh[j]->pF[0] ) break;
	}
	if ( k < gef_conn[n_ef].num_f_PC ) {
	  if ( e->lnf_conditions_rh[j] < gef_conn[n_ef].f_PC_c[k] ) {
	    continue;
	  }
	  if ( e->lnf_conditions_rh[j] > gef_conn[n_ef].f_PC_c[k] ) {
	    gef_conn[n_ef].f_PC_c[k] = e->lnf_conditions_rh[j];
	    gef_conn[n_ef].f_PC_comp[k] = e->lnf_conditions_comp[j];
	    continue;
	  }
	  if ( e->lnf_conditions_comp[j] == GE ) {
	    gef_conn[n_ef].f_PC_comp[k] = GE;
	  }
	} else {
	  gef_conn[n_ef].f_PC_comp[gef_conn[n_ef].num_f_PC] = e->lnf_conditions_comp[j];
	  gef_conn[n_ef].f_PC_fl[gef_conn[n_ef].num_f_PC] = e->lnf_conditions_lh[j]->pF[0];
	  gef_conn[n_ef].f_PC_c[gef_conn[n_ef].num_f_PC++] = e->lnf_conditions_rh[j];
	}
      }
      /* now arrange the direct access structures from that.
       */
      for ( j = 0; j < gef_conn[n_ef].num_f_PC; j++ ) {
	gef_conn[n_ef].f_PC_direct_comp[gef_conn[n_ef].f_PC_fl[j]] = gef_conn[n_ef].f_PC_comp[j]; 
	gef_conn[n_ef].f_PC_direct_c[gef_conn[n_ef].f_PC_fl[j]] = gef_conn[n_ef].f_PC_c[j]; 
      }
     /*****************************CONDS - END********************************/


      if ( e->illegal ) {
	/* we don't care about the effects if they're illegal -
	 * all we care about is whether the condition is true or not.
	 */
	n_ef++;
	gnum_ef_conn++;
	continue;
      }
      /*****************************EFFECTS********************************/
      gef_conn[n_ef].A = ( int * ) calloc( e->num_adds, sizeof( int ) );
      gef_conn[n_ef].D = ( int * ) calloc( e->num_dels, sizeof( int ) );
      gef_conn[n_ef].IN_fl = ( int * ) calloc( e->num_lnf_effects, sizeof( int ) );
      gef_conn[n_ef].IN_fl_ = ( int * ) calloc( e->num_lnf_effects, sizeof( int ) );
      gef_conn[n_ef].IN_c = ( float * ) calloc( e->num_lnf_effects, sizeof( float ) );
      gef_conn[n_ef].AS_fl = ( int * ) calloc( e->num_lnf_effects, sizeof( int ) );
      gef_conn[n_ef].AS_fl_ = ( int * ) calloc( e->num_lnf_effects, sizeof( int ) );
      gef_conn[n_ef].AS_c = ( float * ) calloc( e->num_lnf_effects, sizeof( float ) );

      /* duplicates removed in summarize already.
       *
       * but don't include adds that are in the conds.
       * --- those are true anyway.
       *
       * and don't include dels that are in the adds
       * --- those will be re-added anyway.
       *
       * NOTE: it is important that we use the *original* add list
       *       not the already reduced one, for the delete check!
       *       otherwise it may be that a delete that's in the add
       *       and also in the cond stays in!
       *
       *       IT IS ALSO IMPORTANT THAT WE DO BOTH!!!, i.e. if we do 
       *       the ads reduction then we *must* also do the dels 
       *       reduction to avoid that things are deleted that 
       *       would otherwise have been re-added.       
       */
      for ( j = 0; j < e->num_adds; j++ ) {
	for ( k = 0; k < gef_conn[n_ef].num_PC; k++ ) {
	  if ( gef_conn[n_ef].PC[k] == e->adds[j] ) break;
	}
	if ( k < gef_conn[n_ef].num_PC ) continue;
	gef_conn[n_ef].A[gef_conn[n_ef].num_A++] = e->adds[j];
      }
      for ( j = 0; j < e->num_dels; j++ ) {
	for ( k = 0; k < e->num_adds; k++ ) {
	  if ( e->adds[k] == e->dels[j] ) break;
	}
	if ( k < e->num_adds ) continue;
	gef_conn[n_ef].D[gef_conn[n_ef].num_D++] = e->dels[j];
      }

      /* numeric part
       */
      for ( j = 0; j < e->num_lnf_effects; j++ ) {
	if ( e->lnf_effects_neft[j] != INCREASE ) continue;
	gef_conn[n_ef].IN_fl[gef_conn[n_ef].num_IN] = e->lnf_effects_fl[j];
	if ( e->lnf_effects_rh[j]->num_pF == 1 ) {
	  if ( e->lnf_effects_rh[j]->pF[0] < 0 ) {
	    printf("\n\nnon-relevant fluent in final copying to conn.\n\n");
	    exit( 1 );
	  }
	  gef_conn[n_ef].IN_fl_[gef_conn[n_ef].num_IN] = e->lnf_effects_rh[j]->pF[0];
	} else {
	  if ( e->lnf_effects_rh[j]->num_pF != 0 ) {
	    printf("\n\nnon-1 or 0 number of fl_ in copying to conn\n\n");
	    exit( 1 );
	  }
	  gef_conn[n_ef].IN_fl_[gef_conn[n_ef].num_IN] = -1;
	}
	gef_conn[n_ef].IN_c[gef_conn[n_ef].num_IN++] = e->lnf_effects_rh[j]->c;
      }
      /* now remove increasers by nothing.
       */
      j = 0;
      while ( j < gef_conn[n_ef].num_IN ) {
	if ( gef_conn[n_ef].IN_fl_[j] != -1 ||
	     gef_conn[n_ef].IN_c[j] != 0 ) {
	  j++;
	  continue;
	}
	for ( k = j; k < gef_conn[n_ef].num_IN - 1; k++ ) {
	  gef_conn[n_ef].IN_fl[k] = gef_conn[n_ef].IN_fl[k+1];
	  gef_conn[n_ef].IN_fl_[k] = gef_conn[n_ef].IN_fl_[k+1];
	  gef_conn[n_ef].IN_c[k] = gef_conn[n_ef].IN_c[k+1];
	}
	gef_conn[n_ef].num_IN--;
      }
      /* now: the assigners...
       */
      for ( j = 0; j < e->num_lnf_effects; j++ ) {
	if ( e->lnf_effects_neft[j] != ASSIGN ) continue;
	gef_conn[n_ef].AS_fl[gef_conn[n_ef].num_AS] = e->lnf_effects_fl[j];
	if ( e->lnf_effects_rh[j]->num_pF == 1 ) {
	  if ( e->lnf_effects_rh[j]->pF[0] < 0 ) {
	    printf("\n\nnon-relevant fluent in final copying to conn.\n\n");
	    exit( 1 );
	  }
	  gef_conn[n_ef].AS_fl_[gef_conn[n_ef].num_AS] = e->lnf_effects_rh[j]->pF[0];
	} else {
	  if ( e->lnf_effects_rh[j]->num_pF != 0 ) {
	    printf("\n\nnon-1 or 0 number of fl_ in copying to conn\n\n");
	    exit( 1 );
	  }
	  gef_conn[n_ef].AS_fl_[gef_conn[n_ef].num_AS] = -1;
	}
	gef_conn[n_ef].AS_c[gef_conn[n_ef].num_AS++] = e->lnf_effects_rh[j]->c;
      }
      /*****************************EFFECTS - END********************************/
      
      n_ef++;
      gnum_ef_conn++;
    }/* end all a->effects */


    /*****************************EMPTY EFFECTS********************************/
    if ( gop_conn[n_op].num_E >= 1 ) {
      /* CHECK EMPTY EFFECTS!
       *
       * two step process --- first, remove all effects that are entirely empty.
       *                      second, check if all remaining effects are illegal
       *                      or only delete:
       *                      in that case, the op will never do any good so we 
       *                      remove all its effects.
       */
      i = 0;
      while ( i < gop_conn[n_op].num_E ) {
	/* illegal effects *must* stay in!!!
	 */
	if ( gef_conn[gop_conn[n_op].E[i]].illegal ) {
	  i++;
	  continue;
	}
	if ( gef_conn[gop_conn[n_op].E[i]].num_A != 0 ||
	     gef_conn[gop_conn[n_op].E[i]].num_D != 0 ||
	     gef_conn[gop_conn[n_op].E[i]].num_IN != 0 ||
	     gef_conn[gop_conn[n_op].E[i]].num_AS != 0 ) {
	  i++;
	  continue;
	}
	/* we keep it in the gef_conn (seems easier), 
	 * but mark it as removed, which will exclude it from everything.
	 */
	gef_conn[gop_conn[n_op].E[i]].removed = TRUE;
	for ( j = i; j < gop_conn[n_op].num_E - 1; j++ ) {
	  gop_conn[n_op].E[j] = gop_conn[n_op].E[j+1];
	}
	gop_conn[n_op].num_E--;
      }

      m = 0;
      for ( i = 0; i < gop_conn[n_op].num_E; i++ ) {
	if ( gef_conn[gop_conn[n_op].E[i]].illegal ) {
	  m++;
	  continue;
	}
	if ( gef_conn[gop_conn[n_op].E[i]].num_A == 0 &&
	     gef_conn[gop_conn[n_op].E[i]].num_IN == 0 &&
	     gef_conn[gop_conn[n_op].E[i]].num_AS == 0 ) {
	  m++;
	}
      }
      if ( m == gop_conn[n_op].num_E ) {
	/* all remaining effects illegal or solely-deleters.
	 */
	for ( i = 0; i < gop_conn[n_op].num_E; i++ ) {
	  gef_conn[gop_conn[n_op].E[i]].removed = TRUE;
	}
	gop_conn[n_op].num_E = 0;
      }
    }
    /*****************************EMPTY EFFECTS - END********************************/


    /*****************************IMPLIED EFFECTS********************************/
    if ( gop_conn[n_op].num_E > 1 ) {
      for ( i = 0; i < gop_conn[n_op].num_E; i++ ) {
	ef = gop_conn[n_op].E[i];
	gef_conn[ef].I = ( int * ) calloc( gop_conn[n_op].num_E, sizeof( int ) );
	gef_conn[ef].num_I = 0;
      }    
      for ( i = 0; i < gop_conn[n_op].num_E - 1; i++ ) {
	ef = gop_conn[n_op].E[i];
	for ( j = i+1; j < gop_conn[n_op].num_E; j++ ) {
	  ef_ = gop_conn[n_op].E[j];
	  /* ef ==> ef_ ? */
	  for ( k = 0; k < gef_conn[ef_].num_PC; k++ ) {
	    for ( l = 0; l < gef_conn[ef].num_PC; l++ ) {
	      if ( gef_conn[ef].PC[l] == gef_conn[ef_].PC[k] ) break;
	    }
	    if ( l == gef_conn[ef].num_PC ) break;
	  }
	  if ( k == gef_conn[ef_].num_PC ) {
	    for ( k = 0; k < gnum_fl_conn; k++ ) {
	      if ( gef_conn[ef_].f_PC_direct_comp[k] == IGUAL ) continue;
	      if ( gef_conn[ef].f_PC_direct_comp[k] == IGUAL ||
		   gef_conn[ef].f_PC_direct_c[k] < gef_conn[ef_].f_PC_direct_c[k] ||
		   ( gef_conn[ef].f_PC_direct_c[k] == gef_conn[ef_].f_PC_direct_c[k] &&
		     gef_conn[ef].f_PC_direct_comp[k] == GEQ && 
		     gef_conn[ef_].f_PC_direct_comp[k] == GE ) ) break;
	    }
	    if ( k == gnum_fl_conn ) {
	      gef_conn[ef].I[gef_conn[ef].num_I++] = ef_;
	    }
	  }
	  /* ef_ ==> ef ? */
	  for ( k = 0; k < gef_conn[ef].num_PC; k++ ) {
	    for ( l = 0; l < gef_conn[ef_].num_PC; l++ ) {
	      if ( gef_conn[ef_].PC[l] == gef_conn[ef].PC[k] ) break;
	    }
	    if ( l == gef_conn[ef_].num_PC ) break;
	  }
	  if ( k == gef_conn[ef].num_PC ) {
	    for ( k = 0; k < gnum_fl_conn; k++ ) {
	      if ( gef_conn[ef].f_PC_direct_comp[k] == IGUAL ) continue;
	      if ( gef_conn[ef_].f_PC_direct_comp[k] == IGUAL ||
		   gef_conn[ef_].f_PC_direct_c[k] < gef_conn[ef].f_PC_direct_c[k] ||
		   ( gef_conn[ef_].f_PC_direct_c[k] == gef_conn[ef].f_PC_direct_c[k] &&
		     gef_conn[ef_].f_PC_direct_comp[k] == GEQ && 
		     gef_conn[ef].f_PC_direct_comp[k] == GE ) ) break;
	    }
	    if ( k == gnum_fl_conn ) {
	      gef_conn[ef_].I[gef_conn[ef_].num_I++] = ef;
	    }
	  }
	}
      }
    }
    /*****************************IMPLIED EFFECTS - END********************************/

    /* op cost is sum of eff costs + gtt*1:
     * [gtt is multiplicator of TOTAL-TIME in final metric; if no
     * total-time part in metric, it is 0]
     * ie eff-costs plus the cost for the time taken by 1 more step.
     */
    gop_conn[n_op].cost = gtt;
    if ( gop_conn[n_op].num_E > 0 ) {
      for ( i = 0; i < gop_conn[n_op].num_E; i++ ) {
	ef = gop_conn[n_op].E[i];
	if ( gef_conn[ef].illegal ) {
	  continue;
	}
	if ( gef_conn[ef].removed ) {
	  continue;
	}
	gop_conn[n_op].cost += gef_conn[ef].cost;
      }
    }

    /* first sweep: only count the space we need for the fact arrays !
     */
    if ( gop_conn[n_op].num_E > 0 ) {
      for ( i = 0; i < gop_conn[n_op].num_E; i++ ) {
	ef = gop_conn[n_op].E[i];
	for ( j = 0; j < gef_conn[ef].num_PC; j++ ) {
	  gft_conn[gef_conn[ef].PC[j]].num_PC++;
	}
 	for ( j = 0; j < gef_conn[ef].num_A; j++ ) {
	  gft_conn[gef_conn[ef].A[j]].num_A++;
	  if ( gop_conn[n_op].axiom ) {
	      gft_conn[gef_conn[ef].A[j]].axiom_added = TRUE;
	  }
	}
	for ( j = 0; j < gef_conn[ef].num_D; j++ ) {
	  gft_conn[gef_conn[ef].D[j]].num_D++;
	}
	/* similar increments for flconn
	 */
	for ( j = 0; j < gef_conn[ef].num_f_PC; j++ ) {
	  gfl_conn[gef_conn[ef].f_PC_fl[j]].num_PC++;
	}
 	for ( j = 0; j < gef_conn[ef].num_IN; j++ ) {
	  gfl_conn[gef_conn[ef].IN_fl[j]].num_IN++;
	}
 	for ( j = 0; j < gef_conn[ef].num_AS; j++ ) {
	  gfl_conn[gef_conn[ef].AS_fl[j]].num_AS++;
	}
      }
    }
    

    n_op++;
  }

  /*****************************FLCONN********************************/
  for ( i = 0; i < gnum_ft_conn; i++ ) {
    if ( gft_conn[i].num_PC > 0 ) {
      gft_conn[i].PC = ( int * ) calloc( gft_conn[i].num_PC, sizeof( int ) );
    }
    gft_conn[i].num_PC = 0;
    if ( gft_conn[i].num_A > 0 ) {
      gft_conn[i].A = ( int * ) calloc( gft_conn[i].num_A, sizeof( int ) );
    }
    gft_conn[i].num_A = 0;
    if ( gft_conn[i].num_D > 0 ) {
      gft_conn[i].D = ( int * ) calloc( gft_conn[i].num_D, sizeof( int ) );
    }
    gft_conn[i].num_D = 0;
  }
  for ( i = 0; i < gnum_ef_conn; i++ ) {
    if ( gef_conn[i].removed ) continue;
    for ( j = 0; j < gef_conn[i].num_PC; j++ ) {
      gft_conn[gef_conn[i].PC[j]].PC[gft_conn[gef_conn[i].PC[j]].num_PC++] = i;
    }
    for ( j = 0; j < gef_conn[i].num_A; j++ ) {
      gft_conn[gef_conn[i].A[j]].A[gft_conn[gef_conn[i].A[j]].num_A++] = i;
    }
    for ( j = 0; j < gef_conn[i].num_D; j++ ) {
      gft_conn[gef_conn[i].D[j]].D[gft_conn[gef_conn[i].D[j]].num_D++] = i;
    }
  }
  /*****************************FTCONN - END********************************/


  /*****************************FLCONN********************************/
  /* similar thing for flconn
   */
  for ( i = 0; i < gnum_fl_conn; i++ ) {
    if ( gfl_conn[i].num_PC > 0 ) {
      gfl_conn[i].PC = ( int * ) calloc( gfl_conn[i].num_PC, sizeof( int ) );
    }
    gfl_conn[i].num_PC = 0;
    if ( gfl_conn[i].num_IN > 0 ) {
      gfl_conn[i].IN = ( int * ) calloc( gfl_conn[i].num_IN, sizeof( int ) );
      gfl_conn[i].IN_fl_ = ( int * ) calloc( gfl_conn[i].num_IN, sizeof( int ) );
      gfl_conn[i].IN_c = ( float * ) calloc( gfl_conn[i].num_IN, sizeof( float ) );
    }
    gfl_conn[i].num_IN = 0;
    if ( gfl_conn[i].num_AS > 0 ) {
      gfl_conn[i].AS = ( int * ) calloc( gfl_conn[i].num_AS, sizeof( int ) );
      gfl_conn[i].AS_fl_ = ( int * ) calloc( gfl_conn[i].num_AS, sizeof( int ) );
      gfl_conn[i].AS_c = ( float * ) calloc( gfl_conn[i].num_AS, sizeof( float ) );
    }
    gfl_conn[i].num_AS = 0;
  }
  for ( i = 0; i < gnum_ef_conn; i++ ) {
    if ( gef_conn[i].removed ) continue;
    /* PCs
     */
    for ( j = 0; j < gef_conn[i].num_f_PC; j++ ) {
      fl = gef_conn[i].f_PC_fl[j];
      gfl_conn[fl].PC[gfl_conn[fl].num_PC++] = i;
    }
    /* insert increasers by decreasing amount --> 
     * "best" - at least for constant part - are first!
     */
    for ( j = 0; j < gef_conn[i].num_IN; j++ ) {
      fl = gef_conn[i].IN_fl[j];
      val = gef_conn[i].IN_c[j];
      for ( k = 0; k < gfl_conn[fl].num_IN; k++ ) {
	if ( gfl_conn[fl].IN_c[k] < val ) break;
      }
      for ( l = gfl_conn[fl].num_IN; l > k; l-- ) {
	gfl_conn[fl].IN[l] = gfl_conn[fl].IN[l-1];
	gfl_conn[fl].IN_fl_[l] = gfl_conn[fl].IN_fl_[l-1];
	gfl_conn[fl].IN_c[l] = gfl_conn[fl].IN_c[l-1];
      }
      gfl_conn[fl].IN[k] = i;
      gfl_conn[fl].IN_fl_[k] = gef_conn[i].IN_fl_[j];/* the rh fluent */
      gfl_conn[fl].IN_c[k] = val;
      gfl_conn[fl].num_IN++;
    }
    /* insert assigners by decreasing amount --> 
     * "best" - at least for constant part - are first!
     */
    for ( j = 0; j < gef_conn[i].num_AS; j++ ) {
      fl = gef_conn[i].AS_fl[j];
      val = gef_conn[i].AS_c[j];
      for ( k = 0; k < gfl_conn[fl].num_AS; k++ ) {
	if ( gfl_conn[fl].AS_c[k] < val ) break;
      }
      for ( l = gfl_conn[fl].num_AS; l > k; l-- ) {
	gfl_conn[fl].AS[l] = gfl_conn[fl].AS[l-1];
	gfl_conn[fl].AS_fl_[l] = gfl_conn[fl].AS_fl_[l-1];
	gfl_conn[fl].AS_c[l] = gfl_conn[fl].AS_c[l-1];
      }
      gfl_conn[fl].AS[k] = i;
      gfl_conn[fl].AS_fl_[k] = gef_conn[i].AS_fl_[j];/* the rh fluent */
      gfl_conn[fl].AS_c[k] = val;
      gfl_conn[fl].num_AS++;
    }
  }
  /*****************************FLCONN - END********************************/


  /*****************************GOAL********************************/
  gflogic_goal = ( int * ) calloc( gnum_logic_goal, sizeof( int ) );
  for ( j = 0; j < gnum_logic_goal; j++ ) {
    for ( k = 0; k < gnum_flogic_goal; k++ ) {
      if ( gflogic_goal[k] == glogic_goal[j] ) break;
    }
    if ( k < gnum_flogic_goal ) continue;
    gflogic_goal[gnum_flogic_goal++] = glogic_goal[j];
  }
  /* numeric part
   */
  gfnumeric_goal_comp = ( Comparator * ) calloc( gnum_lnf_goal, sizeof( Comparator ) );
  gfnumeric_goal_fl = ( int * ) calloc( gnum_lnf_goal, sizeof( int ) );
  gfnumeric_goal_c = ( float * ) calloc( gnum_lnf_goal, sizeof( float ) );
  for ( j = 0; j < gnum_lnf_goal; j++ ) {
    if ( glnf_goal_lh[j]->num_pF != 1 ) {
      printf("\n\nnon 1 card. in comp lh final goal copyover.\n\n");
      exit( 1 );
    }
    for ( k = 0; k < gnum_fnumeric_goal; k++ ) {
      if ( gfnumeric_goal_fl[k] == glnf_goal_lh[j]->pF[0] ) break;
    }
    if ( k < gnum_fnumeric_goal ) {
      if ( glnf_goal_rh[j] < gfnumeric_goal_c[k] ) continue;
      if ( glnf_goal_rh[j] > gfnumeric_goal_c[k] ) {
	gfnumeric_goal_comp[k] = glnf_goal_comp[j];
	gfnumeric_goal_c[k] = glnf_goal_rh[j];
	continue;
      }
      if ( glnf_goal_comp[j] == GE ) {
	gfnumeric_goal_comp[k] = GE;
      }
    } else {
      gfnumeric_goal_comp[gnum_fnumeric_goal] = glnf_goal_comp[j];
      gfnumeric_goal_fl[gnum_fnumeric_goal] = glnf_goal_lh[j]->pF[0];
      gfnumeric_goal_c[gnum_fnumeric_goal++] = glnf_goal_rh[j];
    }
  }
  gfnumeric_goal_direct_comp = ( Comparator * ) calloc( gnum_fl_conn, sizeof( Comparator ) );
  for ( j = 0; j < gnum_fl_conn; j++ ) {
    gfnumeric_goal_direct_comp[j] = IGUAL;
  }
  gfnumeric_goal_direct_c = ( float * ) calloc( gnum_fl_conn, sizeof( float ) );
  for ( k = 0; k < gnum_fnumeric_goal; k++ ) {
    gfnumeric_goal_direct_comp[gfnumeric_goal_fl[k]] = gfnumeric_goal_comp[k];
    gfnumeric_goal_direct_c[gfnumeric_goal_fl[k]] = gfnumeric_goal_c[k];
  }
  /*****************************GOAL - END********************************/



  /********************
   * safety: if there are numeric precs/goals, need to turn 
   * cost-minimizing rplans off!!!
   * (see comments with def of gcost_rplans
   */
  for ( i = 0; i < gnum_ef_conn; i++ ) {
    if ( gcost_rplans && gef_conn[i].num_f_PC > 0 ) {
      printf("\nwarning: numeric precondition. turning cost-minimizing relaxed plans OFF.");
      gcost_rplans = FALSE;
      break;
    }
  }
  if ( gcost_rplans && gnum_fnumeric_goal > 0 ) {
    printf("\nwarning: numeric goal. turning cost-minimizing relaxed plans OFF.");
    gcost_rplans = FALSE;
  }




  if ( gcmd_line.display_info == 125 ) {
    printf("\n\ncreated connectivity graph as follows:");

    printf("\n\n------------------OP ARRAY:-----------------------");
    for ( i = 0; i < gnum_op_conn; i++ ) {
      printf("\n\nOP %d: ", i);
      if ( gop_conn[i].axiom ) printf("(axiom) ");
      print_op_name( i );
      printf(" cost %f", gop_conn[i].cost);
      printf("\n----------EFFS:");
      for ( j = 0; j < gop_conn[i].num_E; j++ ) {
	printf("\neffect %d", gop_conn[i].E[j]);
      }
    }
    
    printf("\n\n-------------------EFFECT ARRAY:----------------------");
    for ( i = 0; i < gnum_ef_conn; i++ ) {
      printf("\n\neffect %d of op %d cost %f: ", i, gef_conn[i].op, gef_conn[i].cost);
      print_op_name( gef_conn[i].op );
      if ( gef_conn[i].illegal ) printf(" ******ILLEGAL************************");
      if ( gef_conn[i].removed ) printf(" ******REMOVED************************");
      printf("\n----------PCS:");
      for ( j = 0; j < gef_conn[i].num_PC; j++ ) {
	printf("\n");
	print_ft_name( gef_conn[i].PC[j] );
      }
      printf("\n----------f_PCS:");
      for ( j = 0; j < gef_conn[i].num_f_PC; j++ ) {
	printf("\n");
	print_fl_name( gef_conn[i].f_PC_fl[j] );
	if ( gef_conn[i].f_PC_comp[j] == GEQ ) {
	  printf(" >= ");
	} else {
	  printf(" > ");
	}
	printf("%f", gef_conn[i].f_PC_c[j]);
      }
      printf("\nDIRECT: ");
      for ( j = 0; j < gnum_fl_conn; j++ ) {
	if ( gef_conn[i].f_PC_direct_comp[j] == IGUAL ) {
	  printf("IGUAL  |  ");
	}
	if ( gef_conn[i].f_PC_direct_comp[j] == GEQ ) {
	  printf(">= %f  |  ", gef_conn[i].f_PC_direct_c[j]);
	}
	if ( gef_conn[i].f_PC_direct_comp[j] == GE ) {
	  printf("> %f  |  ", gef_conn[i].f_PC_direct_c[j]);
	}
      }
      if ( gef_conn[i].illegal ) continue;
      printf("\n----------ADDS:");
      for ( j = 0; j < gef_conn[i].num_A; j++ ) {
	printf("\n");
	print_ft_name( gef_conn[i].A[j] );
      }
      printf("\n----------DELS:");
      for ( j = 0; j < gef_conn[i].num_D; j++ ) {
	printf("\n");
	print_ft_name( gef_conn[i].D[j] );
      }
      printf("\n----------INCREASE:");
      for ( j = 0; j < gef_conn[i].num_IN; j++ ) {
	printf("\n");
	print_fl_name( gef_conn[i].IN_fl[j] );
	printf(" by ");
	if ( gef_conn[i].IN_fl_[j] >= 0 ) {
	  print_fl_name( gef_conn[i].IN_fl_[j] );
	  printf(" + %f", gef_conn[i].IN_c[j]);
	} else {
	  printf("%f", gef_conn[i].IN_c[j]);
	}
      }
      printf("\n----------ASSIGN:");
      for ( j = 0; j < gef_conn[i].num_AS; j++ ) {
	printf("\n");
	print_fl_name( gef_conn[i].AS_fl[j] );
	printf(" to ");
	if ( gef_conn[i].AS_fl_[j] >= 0 ) {
	  print_fl_name( gef_conn[i].AS_fl_[j] );
	  printf(" + %f", gef_conn[i].AS_c[j]);
	} else {
	  printf("%f", gef_conn[i].AS_c[j]);
	}
      }
      printf("\n----------IMPLIEDS:");
      for ( j = 0; j < gef_conn[i].num_I; j++ ) {
	printf("\nimplied effect %d of op %d: ", 
	       gef_conn[i].I[j], gef_conn[gef_conn[i].I[j]].op);
	print_op_name( gef_conn[gef_conn[i].I[j]].op );
      }
    }
    
    printf("\n\n----------------------FT ARRAY:-----------------------------");
    for ( i = 0; i < gnum_ft_conn; i++ ) {
      printf("\n\nFT: ");
      print_ft_name( i );
      printf(" rand: %d", gft_conn[i].rand);
      printf(" --------- AXIOM ADDED %d", gft_conn[i].axiom_added);
      printf("\n----------PRE COND OF:");
      for ( j = 0; j < gft_conn[i].num_PC; j++ ) {
	printf("\neffect %d", gft_conn[i].PC[j]);
	printf(" - op "); print_op_name( gef_conn[gft_conn[i].PC[j]].op );
      }
      printf("\n----------ADD BY:");
      for ( j = 0; j < gft_conn[i].num_A; j++ ) {
	printf("\neffect %d", gft_conn[i].A[j]);
	printf(" - op "); print_op_name( gef_conn[gft_conn[i].A[j]].op );
      }
      printf("\n----------DEL BY:");
      for ( j = 0; j < gft_conn[i].num_D; j++ ) {
	printf("\neffect %d", gft_conn[i].D[j]);
	printf(" - op "); print_op_name( gef_conn[gft_conn[i].D[j]].op );
      }
    }
    
    printf("\n\n----------------------FLUENT ARRAY:-----------------------------");
    for ( i = 0; i < gnum_fl_conn; i++ ) {
      printf("\n\nFL: ");
      print_fl_name( i );
      printf("\n----------PRE COND OF:");
      for ( j = 0; j < gfl_conn[i].num_PC; j++ ) {
	printf("\neffect %d", gfl_conn[i].PC[j]);
	printf(" - op "); print_op_name( gef_conn[gfl_conn[i].PC[j]].op );
      }
      printf("\n----------INCREASED BY:");
      for ( j = 0; j < gfl_conn[i].num_IN; j++ ) {
	if ( gfl_conn[i].IN_fl_[j] == -1 ) {
	  printf("\neffect %d  ---  %f", gfl_conn[i].IN[j], gfl_conn[i].IN_c[j]);
	  printf("  ---  op "); print_op_name( gef_conn[gfl_conn[i].IN[j]].op );
	} else {
	  printf("\neffect %d  ---  ", gfl_conn[i].IN[j]);
	  print_fl_name( gfl_conn[i].IN_fl_[j] );
	  printf(" + %f", gfl_conn[i].IN_c[j]);
	  printf("  ---  op "); print_op_name( gef_conn[gfl_conn[i].IN[j]].op );
	}
      }
      printf("\n----------ASSIGNED BY:");
      for ( j = 0; j < gfl_conn[i].num_AS; j++ ) {
	if ( gfl_conn[i].AS_fl_[j] == -1 ) {
	  printf("\neffect %d  ---  %f", gfl_conn[i].AS[j], gfl_conn[i].AS_c[j]);
	  printf("  ---  op "); print_op_name( gef_conn[gfl_conn[i].AS[j]].op );
	} else {
	  printf("\neffect %d  ---  ", gfl_conn[i].AS[j]);
	  print_fl_name( gfl_conn[i].AS_fl_[j] );
	  printf(" + %f", gfl_conn[i].AS_c[j]);
	  printf("  ---  op "); print_op_name( gef_conn[gfl_conn[i].AS[j]].op );
	}
      }
      if ( gfl_conn[i].artificial ) {
	printf("\n----------ARTIFICIAL FOR:");
	for ( j = 0; j < gfl_conn[i].num_lnf; j++ ) {
	  printf(" %f*", gfl_conn[i].lnf_C[j]);
	  print_fl_name( gfl_conn[i].lnf_F[j] );
	  if ( j < gfl_conn[i].num_lnf - 1 ) {
	    printf(" +");
	  }
	}
      } else {
	printf("\n----------REAL");
      }
    }

    printf("\n\n----------------------GOAL:-----------------------------");
    for ( j = 0; j < gnum_flogic_goal; j++ ) {
      printf("\n");
      print_ft_name( gflogic_goal[j] );
    }
    for ( j = 0; j < gnum_fnumeric_goal; j++ ) {
      printf("\n");
      print_fl_name( gfnumeric_goal_fl[j] );
      if ( gfnumeric_goal_comp[j] == GEQ ) {
	printf(" >= ");
      } else {
	printf(" > ");
      }
      printf("%f", gfnumeric_goal_c[j]);
    }
    printf("\nDIRECT: ");
    for ( j = 0; j < gnum_fl_conn; j++ ) {
      if ( gfnumeric_goal_direct_comp[j] == IGUAL ) {
	printf("IGUAL  |  ");
      }
      if ( gfnumeric_goal_direct_comp[j] == GEQ ) {
	printf(">= %f  |  ", gfnumeric_goal_direct_c[j]);
      }
      if ( gfnumeric_goal_direct_comp[j] == GE ) {
	printf("> %f  |  ", gfnumeric_goal_direct_c[j]);
      }
    }
    
    printf("\n\n");
  }
    
}