Пример #1
0
/**
 * @brief Update the data constraints in @g with eq constraints.
 * 
 * The (in-)equality constraints on data are pushed.
 */
void
noll_graph_sat_dform (noll_graph_t * g)
{
  assert (g != NULL);

  if (g->data == NULL)
    g->data = noll_dform_array_new ();
  noll_dform_array *res = g->data;
  // go through all equality constraints and push them for data
  for (uint_t vi = 1;           // ignore 'nil' 
       vi < noll_vector_size (g->lvars); vi++)
    {
      noll_type_t *ty_vi = noll_var_type (g->lvars, vi);
      if (ty_vi->kind == NOLL_TYP_RECORD)
        continue;
      // it is a data variable
      // see relation of vi with all other data variables vj
      for (uint_t vj = vi + 1;  // ignore 'nil' 
           vj < noll_vector_size (g->lvars); vj++)
        {
          noll_type_t *ty_vj = noll_var_type (g->lvars, vj);
          if ((ty_vj->kind == NOLL_TYP_RECORD)
              || (ty_vi->kind != ty_vj->kind))
            continue;
          uint_t ni = g->var2node[vi];
          uint_t nj = g->var2node[vj];
          assert (ni < g->nodes_size);
          assert (nj < g->nodes_size);
          if (ni == nj)
            {
              noll_dform_t *df =
                noll_dform_new_eq (noll_dterm_new_var (vi, ty_vi->kind),
                                   noll_dterm_new_var (vj,
                                                       ty_vj->kind));
              noll_dform_array_push (res, df);
            }
          // no difference constraints in the logic of msets
          if ((ty_vi->kind == NOLL_TYP_INT)
              && (noll_graph_is_diff (g, ni, nj) == true))
            {
              noll_dform_t *df =
                noll_dform_new_eq (noll_dterm_new_var (vi, ty_vi->kind),
                                   noll_dterm_new_var (vj,
                                                       ty_vj->kind));
              df->kind = NOLL_DATA_NEQ;
              noll_dform_array_push (res, df);
            }
        }
    }
  g->isDataComplete = true;
}
Пример #2
0
/**
 * Return the edge of @p g2 having label @p label between nodes @p args.
 * 
 * @param args [inout] contains the mapping of arguments of the edge 
 *                     on nodes of @p g or UNDEFINED_ID
 * @param df   [inout] collect the equality constraints between data 
 *                     required by the mapping found
 * @return the identifier of the edge matched or UNDEFINED_ID
 */
uint_t
noll_graph_get_edge (noll_graph_t * g, noll_edge_e kind, uint_t label,
                     noll_uid_array * args, noll_dform_array * df)
{
  // store of edge identifier matching the searched edge 
  uint_t uid_res = UNDEFINED_ID;
  // source and destination nodes for edge searched
  uint_t nroot = noll_vector_at (args, 0);
  // a new intermediary node
  uint_t nend = noll_vector_at (args, 1);
  uint_t fargs = noll_vector_size (args);
  uint_t shift_j = 0;
  if (noll_pred_isUnaryLoc (label) == true)
    {
      nend = 0;
      fargs++;
      shift_j++;
    }
#ifndef NDEBUG
  fprintf (stdout,
           "\n---- Search for edge n%d---(kind=%d, label=%d)-->n%d:\n",
           nroot, kind, label, nend);
#endif

  if (g->mat[nroot] != NULL)
    {
      for (uint_t i = 0;
           (i < noll_vector_size (g->mat[nroot])) &&
           (uid_res == UNDEFINED_ID); i++)
        {
          uint_t ei = noll_vector_at (g->mat[nroot], i);
          noll_edge_t *edge_i = noll_vector_at (g->edges, ei);
          if ((edge_i->kind == kind) && (edge_i->label == label)
              && (noll_vector_size (edge_i->args) == fargs))
            {
#ifndef NDEBUG
              fprintf (stdout, "\t found e%d, same kind, label and root\n",
                       ei);
#endif
              // edge found with the same kind, label and root,
              // check the other arguments than source are equal
              bool ishom = true;
              for (uint_t j = 1;
                   j < noll_vector_size (args) && (ishom == true); j++)
                {
                  uint_t naj = noll_vector_at (args, j);
                  uint_t nej = noll_vector_at (edge_i->args, j + shift_j);
                  if (naj == UNDEFINED_ID)
                    {
#ifndef NDEBUG
                      fprintf (stdout, "\t\t update arg %d to n%d\n", j, nej);
#endif
                      noll_uid_array_set (args, j, nej);
                    }
                  else if (naj != nej)
                    {
                      noll_typ_t ty = noll_graph_get_node_type (g, naj);
                      if ((ty == NOLL_TYP_INT) || (ty == NOLL_TYP_BAGINT))
                        {
                          // generate an equality constraint 
                          uid_t vaj = noll_graph_get_var (g, naj);
                          uid_t vej = noll_graph_get_var (g, naj);
                          noll_dform_t *df_eq =
                            noll_dform_new_eq (noll_dterm_new_var (vaj, ty),
                                               noll_dterm_new_var (vej, ty));
                          noll_dform_array_push (df, df_eq);
                        }
                      else
                        {
                          // if it is a location node, then error
#ifndef NDEBUG
                          fprintf (stdout,
                                   "\t\t but different arg %d (n%d != n%d)\n",
                                   j, naj, nej);
#endif
                          ishom = false;
                        }
                    }
                }
              if (ishom == true)
                {
#ifndef NDEBUG
                  fprintf (stdout, "\t\t , the same args, and the df = ");
                  noll_dform_array_fprint (stdout, g->lvars, df);
#endif
                  uid_res = ei;
                }
            }
        }
    }

#ifndef NDEBUG
  fprintf (stdout, "\t edge-%d matches!\n", uid_res);
#endif
  if (uid_res == UNDEFINED_ID)
    noll_dform_array_clear (df);        // TODO: free also the pointers inside
  return uid_res;
}
Пример #3
0
/**
 * @brief Check that @p diff entails @p f->m[@p m].
 * 
 * @return 0 if some constraint not entailed, 1 otherwise
 */
int
noll_pure_check_entl (bool ** diff, uint_t dsize, noll_pure_t * f,
                      noll_uid_array * lmap,
                      noll_var_array * exvars, noll_uid_array * map,
                      noll_dform_array * df)
{
  /// this procedure could also be called for the pure part
  /// of a recursive rule, where @p f->m includes also existential vars,
  /// all shall be included in @p m 
  assert (noll_vector_size (exvars) == noll_vector_size (map));
  assert (f->size == noll_vector_size (lmap));
  noll_dform_array *dfn = noll_dform_array_new ();
  int res = 1;
  for (uint_t lv2 = 1; (lv2 < noll_vector_size (lmap)) && res; lv2++)
    {
      uint_t v2 = noll_vector_at (lmap, lv2);
      noll_type_t *ty2 = noll_var_type (exvars, v2);
      for (uint_t lv1 = 0; (lv1 < lv2) && res; lv1++)
        {
          uint_t v1 = noll_vector_at (lmap, lv1);
          noll_type_t *ty1 = noll_var_type (exvars, v1);
          noll_pure_op_t rhs_op = noll_pure_matrix_at (f, lv1, lv2);
          if (rhs_op == NOLL_PURE_OTHER)
            continue;
          uint_t nv1 = noll_vector_at (map, v1);
          uint_t nv2 = noll_vector_at (map, v2);
          if (rhs_op == NOLL_PURE_EQ)
            {
              if (ty1->kind != ty2->kind)
                {
#ifndef NDEBUG
                  fprintf (stdout,
                           "\n**** pure_check_entl: fails (typing) to prove (n%d == n%d)\n",
                           nv1, nv2);
#endif
                  res = 0;
                }
              else
                /// one or both of variables is not yet bounded to a node, 
                /// update m if the other is bounded
              if (nv1 < dsize && nv2 >= dsize)
                noll_uid_array_set (map, v2, nv1);
              else if (nv2 < dsize && nv1 >= dsize)
                noll_uid_array_set (map, v1, nv2);
              else if (ty1->kind == NOLL_TYP_RECORD)
                {
                  /// shall be equal and less than dsize
                  res = ((nv1 < dsize) && (nv2 < dsize)
                         && (nv1 == nv2)) ? 1 : 0;
#ifndef NDEBUG
                  if (res == 0)
                    fprintf (stdout,
                             "\n**** pure_check_entl: fails (record) to prove (n%d == n%d)\n",
                             nv1, nv2);
#endif

                }
              else
                {
                  /// there are nodes for data variables, generate a data constraint

                  noll_dform_t *df_eq =
                    noll_dform_new_eq (noll_dterm_new_var (v1, ty1->kind),
                                       noll_dterm_new_var (v2,
                                                           ty2->kind));
                  noll_dform_array_push (dfn, df_eq);
                }
            }
          else if ((nv1 < dsize) && (nv2 < dsize))
            {
              assert (rhs_op == NOLL_PURE_NEQ);
              bool lhs_isDiff = (nv1 != nv2);
              if (nv1 < nv2)
                lhs_isDiff = diff[nv2][nv1];
              else if (nv2 < nv1)
                lhs_isDiff = diff[nv1][nv2];
              res = (lhs_isDiff) ? 1 : 0;
            }
          else
            {
              /// inequality between unmapped vars
              /// push the constraint if vars are integer vars
              if ((ty1->kind == ty2->kind) && (ty1->kind == NOLL_TYP_INT))
                /// generate an inequality constraint for data vars
                {
                  noll_dform_t *df_eq =
                    noll_dform_new_eq (noll_dterm_new_var (v1, ty1->kind),
                                       noll_dterm_new_var (v2,
                                                           ty2->kind));
                  df_eq->kind = NOLL_DATA_NEQ;
                  noll_dform_array_push (dfn, df_eq);
                }
              else
                /// cannot be checked
                assert (0);
            }
        }
    }
  if (res == 1)
    noll_dform_array_cup_all (df, dfn);
  noll_dform_array_clear (dfn);
  return res;
}