static mclv* get_closure ( mclx* mx /* caller must have invoked mclgUnionvReset before */ , const mclv* nbls ) { mclv* nbls_closure = mclvCopy(NULL, nbls), *wave1 = mclvCopy(NULL, nbls_closure), *wave2 = NULL ; mclgUnionvInitList(mx, nbls_closure) ; while (wave1->n_ivps) { wave2 = mclgUnionv(mx, wave1, NULL, SCRATCH_UPDATE, NULL) ; mcldMerge(nbls_closure, wave2, nbls_closure) ; mclvFree(&wave1) ; wave1 = wave2 ; } mclgUnionvResetList(mx, nbls_closure) ; mclvFree(&wave1) ; return nbls_closure ; }
static int calc_depth ( mclx* m_transient ) { mclx* m_inverse = mclxTranspose(m_transient) ; dim c, depth = 0 ; if(0)puts("") ; for (c=0; c<N_COLS(m_inverse); c++) { dim this_depth = 0 ; if (!m_inverse->cols[c].n_ivps) /* no incoming nodes */ { mclv* next = mclxGetVector(m_transient, m_inverse->cols[c].vid, RETURN_ON_FAIL, NULL) ; if (!next) continue ; mclgUnionvInitList(m_transient, next) ; do { mclv* next2 = mclgUnionv(m_transient, next, NULL, SCRATCH_UPDATE, NULL) ; if (0 && next->ivps) fprintf(stdout, "chain %d ->\n", (int) m_inverse->cols[c].vid) , mclvaDump(next, stdout, -1, " ", 0) ; if (this_depth) /* otherwise starting vector in matrix */ mclvFree(&next) ; next = next2 ; this_depth++ ; } while (next->n_ivps) ; mclvFree(&next) /* did loop at least once, so not the starting vector */ ; mclgUnionvReset(m_transient) ; } if (this_depth > depth) depth = this_depth ; } mclxFree(&m_inverse) ; return depth ; }
mclMatrix* mclInterpret ( mclMatrix* dag ) { mclv* v_attr = mclvCopy(NULL, dag->dom_cols) ; mclx* m_attr = NULL, *m_cls = NULL, *m_clst = NULL ; dim d ; mclvMakeCharacteristic(v_attr) ; for (d=0;d<N_COLS(dag);d++) { mclv* col = dag->cols+d ; if (mclvGetIvp(col, col->vid, NULL)) /* deemed attractor */ mclvInsertIdx(v_attr, col->vid, 2.0) ; } mclvSelectGqBar(v_attr, 1.5) ; m_attr = mclxSub(dag, v_attr, v_attr) ; mclxAddTranspose(m_attr, 1.0) ; m_cls = clmUGraphComponents(m_attr, NULL) /* attractor systems as clusters */ ; mclvCopy(m_cls->dom_rows, dag->dom_cols) /* add all nodes to this cluster matrix */ ; m_clst = mclxTranspose(m_cls) /* nodes(columns) with zero neighbours need to be classified */ ; mclgUnionvReset(dag) /* make mx->dom-rows characteristic */ ; mclxFree(&m_cls) ; for (d=0;d<N_COLS(dag);d++) { mclv* closure, *clsids ; if (mclvGetIvp(v_attr, dag->cols[d].vid, NULL)) continue /* attractor already classified */ ; closure = get_closure(dag, dag->cols+d) /* take all [neighbours of [neighbours of [..]]] */ ; clsids = mclgUnionv(m_clst, closure, NULL, SCRATCH_READY, NULL) ; mclvAdd(m_clst->cols+d, clsids, m_clst->cols+d) ; mclvFree(&clsids) ; mclvFree(&closure) ; } m_cls = mclxTranspose(m_clst) ; mclxFree(&m_attr) ; mclxFree(&m_clst) ; mclvFree(&v_attr) ; return m_cls ; }