// set Language and Country for movies that do not have the value set // for every movie find the mojority language/country in 1-hop neighborhood and set it void TImdbNet::SetLangCntryByMajority() { // set language while (true) { TIntPrV NIdToVal; for (TNodeI NI = BegNI(); NI < EndNI(); NI++) { if (NI().GetLang() != 0) { continue; } int Nbhs=0; TIntH LangCntH; for (int e = 0; e < NI.GetOutDeg(); e++) { LangCntH.AddDat(NI.GetOutNDat(e).GetLang()) += 1; Nbhs++; } for (int e = 0; e < NI.GetInDeg(); e++) { LangCntH.AddDat(NI.GetInNDat(e).GetLang()) += 1; Nbhs++; } if (LangCntH.IsKey(0)) { Nbhs-=LangCntH.GetDat(0); LangCntH.GetDat(0)=0; } LangCntH.SortByDat(false); if (LangCntH.GetKey(0) == 0) { continue; } if (LangCntH[0]*2 >= Nbhs) { NIdToVal.Add(TIntPr(NI.GetId(), LangCntH.GetKey(0))); } } if (NIdToVal.Empty()) { break; } // done for (int i = 0; i < NIdToVal.Len(); i++) { GetNDat(NIdToVal[i].Val1).Lang = NIdToVal[i].Val2; } printf(" language set: %d\n", NIdToVal.Len()); } int cnt=0; for (TNodeI NI = BegNI(); NI < EndNI(); NI++) { if (NI().GetLang()==0) cnt++; } printf(" NO language: %d\n\n", cnt); // set country while (true) { TIntPrV NIdToVal; for (TNodeI NI = BegNI(); NI < EndNI(); NI++) { if (NI().GetCntry() != 0) { continue; } int Nbhs=0; TIntH CntryCntH; for (int e = 0; e < NI.GetOutDeg(); e++) { CntryCntH.AddDat(NI.GetOutNDat(e).GetCntry()) += 1; Nbhs++; } for (int e = 0; e < NI.GetInDeg(); e++) { CntryCntH.AddDat(NI.GetInNDat(e).GetCntry()) += 1; Nbhs++; } if (CntryCntH.IsKey(0)) { Nbhs-=CntryCntH.GetDat(0); CntryCntH.GetDat(0)=0; } CntryCntH.SortByDat(false); if (CntryCntH.GetKey(0) == 0) { continue; } if (CntryCntH[0]*2 >= Nbhs) { NIdToVal.Add(TIntPr(NI.GetId(), CntryCntH.GetKey(0))); } } if (NIdToVal.Empty()) { break; } // done for (int i = 0; i < NIdToVal.Len(); i++) { GetNDat(NIdToVal[i].Val1).Cntry = NIdToVal[i].Val2; } printf(" country set: %d\n", NIdToVal.Len()); } cnt=0; for (TNodeI NI = BegNI(); NI < EndNI(); NI++) { if (NI().GetCntry()==0) cnt++; } printf(" NO country: %d\n\n", cnt); }
void TCycBs::_SaveTaxonomyTxt(FILE* fOut, const int& Lev, TIntPrV& RelIdVIdPrV, TIntIntH& VIdToLevH){ for (int VidN=0; VidN<RelIdVIdPrV.Len(); VidN++){ int FromRelId=RelIdVIdPrV[VidN].Val1; int SrcVId=RelIdVIdPrV[VidN].Val2; TStr SrcVNm=GetVNm(SrcVId); TCycVrtx& SrcVrtx=GetVrtx(SrcVId); if (!SrcVrtx.IsFlag(cvfHumanOk)){continue;} TStr FlagStr=SrcVrtx.GetFlagStr(); if (FromRelId==-1){ if (Lev>0){fprintf(fOut, "===upper");} else {fprintf(fOut, "===lower");} fprintf(fOut, "=======================================================\n"); fprintf(fOut, "%s - %s\n", SrcVNm.CStr(), FlagStr.CStr()); } else { TStr FromRelNm=GetVNm(FromRelId); fprintf(fOut, "%*c[%s] --> %s\n", (Lev-1)*5, ' ', FromRelNm.CStr(), SrcVNm.CStr()); } TIntPrV UpRelIdVIdPrV; for (int EdgeN=0; EdgeN<SrcVrtx.GetEdges(); EdgeN++){ TCycEdge& Edge=SrcVrtx.GetEdge(EdgeN); int RelId=Edge.GetRelId(); int DstVId=Edge.GetDstVId(); TStr RelNm=GetVNm(RelId); TStr DstVNm=GetVNm(DstVId); if (Lev>0){ // upper taxonomy if ((RelNm=="#$isa")||(RelNm=="#$genls")){ if (!VIdToLevH.IsKey(DstVId)){ VIdToLevH.AddDat(DstVId, Lev+1); UpRelIdVIdPrV.Add(TIntPr(RelId, DstVId)); } } } else { // lower taxonomy if ((RelNm=="~#$isa")||(RelNm=="~#$genls")){ if (!VIdToLevH.IsKey(DstVId)){ VIdToLevH.AddDat(DstVId, Lev-1); UpRelIdVIdPrV.Add(TIntPr(RelId, DstVId)); } } } } // recursive call if (Lev>0){ _SaveTaxonomyTxt(fOut, Lev+1, UpRelIdVIdPrV, VIdToLevH); } else { _SaveTaxonomyTxt(fOut, Lev-1, UpRelIdVIdPrV, VIdToLevH); } } }
TIntPrV TTrawling::PlotMinFqVsMaxSet(const TStr& OutFNm) { InitItemSets(); TIntPrV SzCntH; SzCntH.Add(TIntPr(1, CurItemH.Len())); for (int ItemSetSz = 2; ItemSetSz < 100; ItemSetSz++) { printf("\nItemset size %d: ", ItemSetSz); GetNextFqItemSets(); if (CurItemH.Empty()) { break; } SzCntH.Add(TIntPr(ItemSetSz, CurItemH.Len())); TGnuPlot::PlotValV(SzCntH, "itemSet-"+OutFNm, TStr::Fmt("Minimum Suport = %d", MinSup), "Itemset size", "Number of itemsets > Minimum Support"); } printf("\n\n"); return SzCntH; }
TFfGGen::TStopReason TUndirFFire::AddNodes(const int& GraphNodes, const bool& FloodStop) { printf("\n***Undirected GEO ForestFire: graph(%d,%d) add %d nodes, burn prob %.3f\n", Graph->GetNodes(), Graph->GetEdges(), GraphNodes, BurnProb); TExeTm ExeTm; int Burned1 = 0, Burned2 = 0, Burned3 = 0; // last 3 fire sizes TIntPrV NodesEdgesV; // create initial set of nodes if (Graph.Empty()) { Graph = PUNGraph::New(); } if (Graph->GetNodes() == 0) { Graph->AddNode(); } int NEdges = Graph->GetEdges(); // forest fire for (int NNodes = Graph->GetNodes() + 1; NNodes <= GraphNodes; NNodes++) { const int NewNId = Graph->AddNode(-1); IAssert(NewNId == Graph->GetNodes() - 1); // node ids have to be 0...N const int StartNId = Rnd.GetUniDevInt(NewNId); const int NBurned = BurnGeoFire(StartNId); // add edges to burned nodes for (int e = 0; e < NBurned; e++) { Graph->AddEdge(NewNId, GetBurnedNId(e)); } NEdges += NBurned; Burned1 = Burned2; Burned2 = Burned3; Burned3 = NBurned; if (NNodes % Kilo(1) == 0) { printf("(%d, %d) burned: [%d,%d,%d] [%s]\n", NNodes, NEdges, Burned1, Burned2, Burned3, ExeTm.GetStr()); NodesEdgesV.Add(TIntPr(NNodes, NEdges)); } if (FloodStop && NEdges>1000 && NEdges / double(NNodes)>100.0) { // average node degree is more than 50 printf("!!! FLOOD. G(%6d, %6d)\n", NNodes, NEdges); return TFfGGen::srFlood; } } printf("\n"); IAssert(Graph->GetEdges() == NEdges); return TFfGGen::srOk; }
// set actor's language and country void TImdbNet::SetActorCntryLangByMajority() { // set language TIntPrV NIdToVal; for (TNodeI NI = BegNI(); NI < EndNI(); NI++) { if (! NI().IsActor()) { continue; } IAssert(NI().GetLang() == 0); // no language set IAssert(NI.GetInDeg() == 0); // actors point to movies int Nbhs=0; TIntH LangCntH; for (int e = 0; e < NI.GetOutDeg(); e++) { LangCntH.AddDat(NI.GetOutNDat(e).GetLang()) += 1; Nbhs++; } if (LangCntH.IsKey(0)) { Nbhs-=LangCntH.GetDat(0); LangCntH.GetDat(0)=0; } LangCntH.SortByDat(false); if (LangCntH.GetKey(0) == 0) { continue; } if (LangCntH[0]*2 >= Nbhs) { NIdToVal.Add(TIntPr(NI.GetId(), LangCntH.GetKey(0))); } } for (int i = 0; i < NIdToVal.Len(); i++) { GetNDat(NIdToVal[i].Val1).Lang = NIdToVal[i].Val2; } printf(" language set: %d\n", NIdToVal.Len()); int cnt=0; for (TNodeI NI = BegNI(); NI < EndNI(); NI++) { if (NI().IsActor() && NI().GetLang()==0) cnt++; } printf(" Actors NO language: %d\n\n", cnt); // set country NIdToVal.Clr(true); for (TNodeI NI = BegNI(); NI < EndNI(); NI++) { if (! NI().IsActor()) { continue; } IAssert(NI().GetCntry() == 0); // no country set IAssert(NI.GetInDeg() == 0); // actors point to movies int Nbhs=0; TIntH CntryCntH; for (int e = 0; e < NI.GetOutDeg(); e++) { CntryCntH.AddDat(NI.GetOutNDat(e).GetCntry()) += 1; Nbhs++; } if (CntryCntH.IsKey(0)) { Nbhs-=CntryCntH.GetDat(0); CntryCntH.GetDat(0)=0; } CntryCntH.SortByDat(false); if (CntryCntH.GetKey(0) == 0) { continue; } if (CntryCntH[0]*2 >= Nbhs) { NIdToVal.Add(TIntPr(NI.GetId(), CntryCntH.GetKey(0))); } } for (int i = 0; i < NIdToVal.Len(); i++) { GetNDat(NIdToVal[i].Val1).Cntry = NIdToVal[i].Val2; } printf(" country set: %d\n", NIdToVal.Len()); cnt=0; for (TNodeI NI = BegNI(); NI < EndNI(); NI++) { if (NI().IsActor() && NI().GetCntry()==0) cnt++; } printf(" Actors NO country: %d\n\n", cnt); }
void TCycBs::SaveTaxonomyTxt(const TStr& FNm){ TFOut FOut(FNm); FILE* fOut=FOut.GetFileId(); for (int VId=0; VId<GetVIds(); VId++){ printf("%d/%d (%.1f%%)\r", 1+VId, GetVIds(), 100.0*(1+VId)/GetVIds()); //if (VId>10){break;} // upper taxonomy {int Lev=0; TIntIntH VIdToLevH; VIdToLevH.AddDat(VId, Lev); TIntPrV UpRelIdVIdPrV; UpRelIdVIdPrV.Add(TIntPr(-1, VId)); _SaveTaxonomyTxt(fOut, Lev+1, UpRelIdVIdPrV, VIdToLevH);} // lower taxonomy {int Lev=0; TIntIntH VIdToLevH; VIdToLevH.AddDat(VId, Lev); TIntPrV UpRelIdVIdPrV; UpRelIdVIdPrV.Add(TIntPr(-1, VId)); _SaveTaxonomyTxt(fOut, Lev-1, UpRelIdVIdPrV, VIdToLevH);} } printf("\n"); }
// Wgt == -1 : take the weight of the edge in the opposite direction void TWgtNet::AddBiDirEdges(const double& Wgt) { TIntPrV EdgeV; for (TNodeI NI = BegNI(); NI < EndNI(); NI++) { for (int e = 0; e < NI.GetOutDeg(); e++) { if (! IsEdge(NI.GetOutNId(e), NI.GetId())) { EdgeV.Add(TIntPr(NI.GetOutNId(e), NI.GetId())); } } } for (int e = 0; e < EdgeV.Len(); e++) { if (Wgt != -1) { AddEdge(EdgeV[e].Val1, EdgeV[e].Val2, Wgt); } else { // edge weight in the opposite direction AddEdge(EdgeV[e].Val1, EdgeV[e].Val2, GetEDat(EdgeV[e].Val2, EdgeV[e].Val1)); } } }
// network cascade: add spurious edges // for more details see "Correcting for Missing Data in Information Cascades" by E. Sadikov, M. Medina, J. Leskovec, H. Garcia-Molina. WSDM, 2011 PNGraph AddSpuriousEdges(const PUNGraph& Graph, const PNGraph& Casc, TIntH NIdTmH) { TIntPrV EdgeV; for (TNGraph::TNodeI NI = Casc->BegNI(); NI < Casc->EndNI(); NI++) { TUNGraph::TNodeI GNI = Graph->GetNI(NI.GetId()); const int Tm = NIdTmH.GetDat(NI.GetId()); for (int i=0,j=0; i < GNI.GetOutDeg(); i++) { const int Dst = GNI.GetOutNId(i); if (NIdTmH.IsKey(Dst) && Tm<NIdTmH.GetDat(Dst) && ! NI.IsNbhNId(Dst)) { EdgeV.Add(TIntPr(GNI.GetId(), Dst)); } } } PNGraph NetCasc = TNGraph::New(); *NetCasc = *Casc; for (int e = 0; e < EdgeV.Len(); e++) { NetCasc->AddEdge(EdgeV[e].Val1, EdgeV[e].Val2); } return NetCasc; }
void TGraphKey::TakeGraph(const PNGraph& Graph, TIntPrV& NodeMap) { TIntSet NodeIdH; int n = 0; NodeMap.Gen(Graph->GetNodes(), 0); for (TNGraph::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++, n++) { NodeIdH.AddKey(NI.GetId()); NodeMap.Add(TIntPr(NI.GetId(), n)); } Nodes = Graph->GetNodes(); EdgeV.Gen(Nodes, 0); for (TNGraph::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { const int NewNId = NodeIdH.GetKeyId(NI.GetId()); for (int i = 0; i < NI.GetOutDeg(); i++) { EdgeV.Add(TIntPr(NewNId, NodeIdH.GetKeyId(NI.GetOutNId(i)))); } } EdgeV.Sort(true); EdgeV.Pack(); }
// get degrees from current and add it to degrees void AddDegreeStat(const TFltPrV& current, TFltPrV& degrees, TIntPrV& samples){ for (int j = 0; j < current.Len(); j++){ const TFltPr& elem = current[j]; const double& deg = elem.Val1.Val, &nodesCount = elem.Val2.Val; bool wasFound = false; // silly search for (int k = 0; k < degrees.Len(); k++){ if (degrees[k].Val1.Val == deg){ degrees[k].Val2.Val += nodesCount; samples[k].Val2.Val++; wasFound = true; break; } } if (!wasFound){ TFlt d(deg), n(nodesCount); TFltPr val(d,n); degrees.Add(val); TInt di(static_cast<int>(deg)); TIntPr valI(di, 1); samples.Add(valI); } } }
void TNetInfBs::GenNoisyCascade(TCascade& C, const int& TModel, const double &window, TIntPrIntH& EdgesUsed, const double& std_waiting_time, const double& std_beta, const double& PercRndNodes, const double& PercRndRemoval) { TIntPrIntH EdgesUsedC; // list of used edges for a single cascade GenCascade(C, TModel, window, EdgesUsedC, delta, std_waiting_time, std_beta); // store keys TIntV KeyV; C.NIdHitH.GetKeyV(KeyV); // store first and last time double tbeg = TFlt::Mx, tend = TFlt::Mn; for (int i=0; i < KeyV.Len(); i++) { if (tbeg > C.NIdHitH.GetDat(KeyV[i]).Tm) tbeg = C.NIdHitH.GetDat(KeyV[i]).Tm; if (tend < C.NIdHitH.GetDat(KeyV[i]).Tm) tend = C.NIdHitH.GetDat(KeyV[i]).Tm; } // remove PercRndRemoval% of the nodes of the cascades if (PercRndRemoval > 0) { for (int i=KeyV.Len()-1; i >= 0; i--) { if (TFlt::Rnd.GetUniDev() < PercRndRemoval) { // remove from the EdgesUsedC the ones affected by the removal TIntPrV EdgesToRemove; for (TIntPrIntH::TIter EI = EdgesUsedC.BegI(); EI < EdgesUsedC.EndI(); EI++) { if ( (KeyV[i]==EI.GetKey().Val1 && C.IsNode(EI.GetKey().Val2) && C.GetTm(KeyV[i]) < C.GetTm(EI.GetKey().Val2)) || (KeyV[i]==EI.GetKey().Val2 && C.IsNode(EI.GetKey().Val1) && C.GetTm(KeyV[i]) > C.GetTm(EI.GetKey().Val1)) ) { EI.GetDat() = EI.GetDat()-1; if (EI.GetDat()==0) EdgesToRemove.Add(EI.GetKey()); } } for (int er=0; er<EdgesToRemove.Len(); er++) EdgesUsedC.DelKey(EdgesToRemove[er]); C.Del(KeyV[i]); } } // defrag the hash table, otherwise other functions can crash C.NIdHitH.Defrag(); } // Substitute PercRndNodes% of the nodes for a random node at a random time if (PercRndNodes > 0) { for (int i=KeyV.Len()-1; i >= 0; i--) { if (TFlt::Rnd.GetUniDev() < PercRndNodes) { // remove from the EdgesUsedC the ones affected by the change TIntPrV EdgesToRemove; for (TIntPrIntH::TIter EI = EdgesUsedC.BegI(); EI < EdgesUsedC.EndI(); EI++) { if ( (KeyV[i]==EI.GetKey().Val1 && C.IsNode(EI.GetKey().Val2) && C.GetTm(KeyV[i]) < C.GetTm(EI.GetKey().Val2)) || (KeyV[i]==EI.GetKey().Val2 && C.IsNode(EI.GetKey().Val1) && C.GetTm(KeyV[i]) > C.GetTm(EI.GetKey().Val1)) ) { EI.GetDat() = EI.GetDat()-1; if (EI.GetDat()==0) EdgesToRemove.Add(EI.GetKey()); } } for (int er=0; er<EdgesToRemove.Len(); er++) EdgesUsedC.DelKey(EdgesToRemove[er]); printf("Old node n:%d t:%f --", KeyV[i].Val, C.GetTm(KeyV[i])); C.Del(KeyV[i]); // not repeating a label double tnew = 0; int keynew = -1; do { tnew = tbeg + TFlt::Rnd.GetUniDev()*(tend-tbeg); keynew = Graph->GetRndNId(); } while (KeyV.IsIn(keynew)); printf("New node n:%d t:%f\n", keynew, tnew); C.Add(keynew, tnew); KeyV.Add(keynew); } } } // add to the aggregate list (EdgesUsed) EdgesUsedC.Defrag(); for (int i=0; i<EdgesUsedC.Len(); i++) { if (!EdgesUsed.IsKey(EdgesUsedC.GetKey(i))) EdgesUsed.AddDat(EdgesUsedC.GetKey(i)) = 0; EdgesUsed.GetDat(EdgesUsedC.GetKey(i)) += 1; } }
void TNGramBs::GetNGramIdV( const TStr& HtmlStr, TIntV& NGramIdV, TIntPrV& NGramBEChXPrV) const { // create MxNGramLen queues TVec<TIntQ> WIdQV(MxNGramLen); TVec<TIntPrQ> BEChXPrQV(MxNGramLen); for (int NGramLen=1; NGramLen<MxNGramLen; NGramLen++){ WIdQV[NGramLen].Gen(100*NGramLen, NGramLen+1); BEChXPrQV[NGramLen].Gen(100*NGramLen, NGramLen+1); } bool AllWIdQClrP=true; // extract words from text-string PSIn HtmlSIn=TStrIn::New(HtmlStr, false); THtmlLx HtmlLx(HtmlSIn); while (HtmlLx.Sym!=hsyEof){ if ((HtmlLx.Sym==hsyStr)||(HtmlLx.Sym==hsyNum)){ // get word-string & word-id TStr WordStr=HtmlLx.UcChA; int WId; int SymBChX=HtmlLx.SymBChX; int SymEChX=HtmlLx.SymEChX; if ((SwSet.Empty())||(!SwSet->IsIn(WordStr))){ if (!Stemmer.Empty()){ WordStr=Stemmer->GetStem(WordStr);} if (IsWord(WordStr, WId)){ if (!IsSkipWord(WId)){ NGramIdV.Add(0+WId); // add single word NGramBEChXPrV.Add(TIntPr(SymBChX, SymEChX)); // add positions for (int NGramLen=1; NGramLen<MxNGramLen; NGramLen++){ TIntQ& WIdQ=WIdQV[NGramLen]; TIntPrQ& BEChXPrQ=BEChXPrQV[NGramLen]; WIdQ.Push(WId); BEChXPrQ.Push(TIntPr(SymBChX, SymEChX)); AllWIdQClrP=false; // if queue full if (WIdQ.Len()==NGramLen+1){ // create sequence TIntV WIdV; WIdQ.GetSubValVec(0, WIdQ.Len()-1, WIdV); TIntPrV BEChXPrV; BEChXPrQ.GetSubValVec(0, BEChXPrQ.Len()-1, BEChXPrV); // add ngram-id or reset queues int WIdVP; if (WIdVToFqH.IsKey(WIdV, WIdVP)){ // if sequence is frequent int NGramId=GetWords()+WIdVP; // get sequence ngram-id NGramIdV.Add(NGramId); // add sequence ngram-id NGramBEChXPrV.Add(TIntPr(BEChXPrV[0].Val1, BEChXPrV.Last().Val2)); // add positions } } } } } else { // break queue sequences if infrequent word occures if (!AllWIdQClrP){ for (int NGramLen=1; NGramLen<MxNGramLen; NGramLen++){ TIntQ& WIdQ=WIdQV[NGramLen]; TIntPrQ& BEChXPrQ=BEChXPrQV[NGramLen]; if (!WIdQ.Empty()){WIdQ.Clr(); BEChXPrQ.Clr();} } AllWIdQClrP=true; } } } } // get next symbol HtmlLx.GetSym(); } }
///////////////////////////////////////////////// // Best-Paths void GetBestPaths( const TStr& SrcNmObjStr, const TStr& DstNmObjStr, const PNmObjBs& NmObjBs){ int SrcNmObjId=NmObjBs->GetNmObjId(SrcNmObjStr); int DstNmObjId=NmObjBs->GetNmObjId(DstNmObjStr); int NmObjs=NmObjBs->GetNmObjs(); TIntPrV ParLevPrV(NmObjs); TIntPrV DstParLevPrV; ParLevPrV.PutAll(TIntPr(-1, -1)); int CurLev=0; ParLevPrV[SrcNmObjId]=TIntPr(SrcNmObjId, CurLev); forever{ CurLev++; int NewEdges=0; for (int NmObjId1=0; NmObjId1<NmObjs; NmObjId1++){ if (ParLevPrV[NmObjId1].Val2==CurLev-1){ TIntV DocIdV1; NmObjBs->GetNmObjDocIdV(NmObjId1, DocIdV1); for (int NmObjId2=0; NmObjId2<NmObjs; NmObjId2++){ if ((NmObjId2==DstNmObjId)||(ParLevPrV[NmObjId2].Val2==-1)){ TIntV DocIdV2; NmObjBs->GetNmObjDocIdV(NmObjId2, DocIdV2); TIntV IntrsDocIdV; DocIdV1.Intrs(DocIdV2, IntrsDocIdV); if (!IntrsDocIdV.Empty()){ ParLevPrV[NmObjId2]=TIntPr(NmObjId1, CurLev); NewEdges++; if (NmObjId2==DstNmObjId){ DstParLevPrV.Add(TIntPr(NmObjId1, CurLev)); } } } } } } if ((NewEdges==0)||(ParLevPrV[DstNmObjId].Val2!=-1)){ break; } } // prepare graph THash<TStr, PVrtx> VrtxNmToVrtxH; TStrPrV VrtxNmPrV; VrtxNmToVrtxH.AddKey(SrcNmObjStr); VrtxNmToVrtxH.AddKey(DstNmObjStr); // write path ContexterF->NmObjLinkageREd->Clear(); for (int DstParLevPrN=0; DstParLevPrN<DstParLevPrV.Len(); DstParLevPrN++){ ParLevPrV[DstNmObjId]=DstParLevPrV[DstParLevPrN]; int DstParLev=ParLevPrV[DstNmObjId].Val2; TStr DstNmObjStr=NmObjBs->GetNmObjStr(DstNmObjId); ContexterF->NmObjLinkageREd->Lines->Add(DstNmObjStr.CStr()); int ParNmObjId=DstNmObjId; TStr PrevNmObjStr=DstNmObjStr; forever { if (ParNmObjId==SrcNmObjId){break;} ParNmObjId=ParLevPrV[ParNmObjId].Val1; int ParLev=ParLevPrV[ParNmObjId].Val2; TStr CurNmObjStr=NmObjBs->GetNmObjStr(ParNmObjId); TStr ParNmObjStr=TStr::GetSpaceStr((DstParLev-ParLev)*4)+CurNmObjStr; ContexterF->NmObjLinkageREd->Lines->Add(ParNmObjStr.CStr()); // create vertex & edge VrtxNmToVrtxH.AddKey(CurNmObjStr); if (!PrevNmObjStr.Empty()){ if (PrevNmObjStr<CurNmObjStr){ VrtxNmPrV.AddUnique(TStrPr(PrevNmObjStr, CurNmObjStr)); } else if (PrevNmObjStr>CurNmObjStr){ VrtxNmPrV.AddUnique(TStrPr(CurNmObjStr, PrevNmObjStr)); } } // save curent named-object PrevNmObjStr=CurNmObjStr; } } // generate graph // create graph PGraph Graph=TGGraph::New(); // create vertices for (int VrtxN=0; VrtxN<VrtxNmToVrtxH.Len(); VrtxN++){ TStr VrtxNm=VrtxNmToVrtxH.GetKey(VrtxN); PVrtx Vrtx=TGVrtx::New(VrtxNm); VrtxNmToVrtxH.GetDat(VrtxNm)=Vrtx; Graph->AddVrtx(Vrtx); } // create edges for (int EdgeN=0; EdgeN<VrtxNmPrV.Len(); EdgeN++){ PVrtx Vrtx1=VrtxNmToVrtxH.GetDat(VrtxNmPrV[EdgeN].Val1); PVrtx Vrtx2=VrtxNmToVrtxH.GetDat(VrtxNmPrV[EdgeN].Val2); PEdge Edge=new TGEdge(Vrtx1, Vrtx2, TStr::Fmt("_%d", EdgeN), false); Graph->AddEdge(Edge); } // place graph ContexterF->State->ElGraph=Graph; TRnd Rnd(1); ContexterF->State->ElGraph->PlaceSimAnnXY(Rnd, ContexterF->State->ElGks); // draw graph ContexterF->State->ElGks->Clr(); ContexterF->ElPbPaint(NULL); }