/** * This method tests if there are at most <i>k</i> two-paths from <i>i</i> * to <i>j</i>. * If the test is positive, the number of such paths is stored * in the variable <i>twoPathCount</i>. */ bool OneModeNetwork::atMostKTwoPaths(int i, int j, int k, int & twoPathCount) const { this->checkSenderRange(i); this->checkReceiverRange(j); // Iterate the outgoing ties of i and incoming ties of j simultaneously // and count the number of matching neighbors. Stop as soon as their number // exceeds k. IncidentTieIterator outIter = this->outTies(i); IncidentTieIterator inIter = this->inTies(j); twoPathCount = 0; while (outIter.valid() && inIter.valid() && twoPathCount <= k) { if (outIter.actor() < inIter.actor()) { outIter.next(); } else if (outIter.actor() > inIter.actor()) { inIter.next(); } else { twoPathCount++; outIter.next(); inIter.next(); } } return twoPathCount <= k; }
/** * Returns the statistic corresponding to the given ego with respect to the * given values of the behavior variable. */ double AverageSimmelianAlterEffect::egoStatistic(int i, double * currentValues) { double statistic = 0; clearSimmelian(); updateSimmelian((const OneModeNetwork*) this->pNetwork()); // simulated state const Network * pNetwork = this->pNetwork(); int simmelianOutdegree = 0; for (IncidentTieIterator iter = pNetwork->outTies(i); iter.valid(); iter.next()) { if (pSimmelian->tieValue(i, iter.actor()) > 0) { statistic += currentValues[iter.actor()]; simmelianOutdegree ++; } } if (simmelianOutdegree > 0) { statistic *= currentValues[i]; if (this->ldivide) { statistic /= simmelianOutdegree; } } return statistic; }
/** * Create primary setting based on a network */ std::vector<int> * primarySetting(const Network * pNetwork, int ego) { std::vector<int> *setting = new std::vector<int>; std::set<int> neighbors; for (IncidentTieIterator iter = pNetwork->outTies(ego); iter.valid(); iter.next()) { neighbors.insert(iter.actor()); } for (IncidentTieIterator iter = pNetwork->inTies(ego); iter.valid(); iter.next()) { neighbors.insert(iter.actor()); } neighbors.insert(ego); // when finished (not all done here) copy to the vector for (std::set<int>::const_iterator iter1 = neighbors.begin(); iter1 != neighbors.end(); iter1++) { setting->push_back(*iter1); } return setting; }
/** * Returns the number of two-paths from <i>i</i> to <i>j</i> truncated at the * given threshold value. */ int OneModeNetwork::truncatedTwoPathCount(int i, int j, int threshold) const { this->checkSenderRange(i); this->checkReceiverRange(j); // Iterate the outgoing ties of i and incoming ties of j simultaneously // and count the number of matching neighbors. Stop as soon as the // threshold value is reached. IncidentTieIterator outIter = this->outTies(i); IncidentTieIterator inIter = this->inTies(j); int count = 0; while (outIter.valid() && inIter.valid() && count < threshold) { if (outIter.actor() < inIter.actor()) { outIter.next(); } else if (outIter.actor() > inIter.actor()) { inIter.next(); } else { count++; outIter.next(); inIter.next(); } } return count; }
/** * Modifies the two-path count given the case the observed network is a * two mode network. * @param[in] rNetwork The observed network * @param[in] ego The ego of the modified tie * @param[in] alter The alter of the modified tie * @param[in[ val The magnitude of modification */ void DistanceTwoLayer::modify2PathCountTwoMode(const Network& rNetwork, int ego, int alter, int val) { // in a two mode network the exist no triangles, therefore it is // sufficient to iterate over all incoming ties of alter for (IncidentTieIterator iter = rNetwork.inTies(alter); iter.valid(); iter.next()) { if (iter.actor() != ego) { modifyTieValue(ego, iter.actor(), val); } } }
/** * Calculates the contribution of a tie flip to the given actor. */ double SameCovariateActivityEffect::calculateContribution(int alter) const { double myvalue = this->value(this->ego()); double contribution = 0; const Network * pNetwork = this->pNetwork(); if ((lsame) && (fabs(this->value(alter) - myvalue) < EPSILON)) { for (IncidentTieIterator iter = pNetwork->outTies(this->ego()); iter.valid(); iter.next()) { // Get the receiver of the outgoing tie. int h = iter.actor(); if (fabs(this->value(h) - myvalue) < EPSILON) { contribution++; } } if (this->outTieExists(alter)) { contribution--; } contribution *= 2; contribution++; } if ((!lsame) && (fabs(this->value(alter) - myvalue) >= EPSILON)) { for (IncidentTieIterator iter = pNetwork->outTies(this->ego()); iter.valid(); iter.next()) { // Get the receiver of the outgoing tie. int h = iter.actor(); if (fabs(this->value(h) - myvalue) >= EPSILON) { contribution++; } } if (this->outTieExists(alter)) { contribution--; } contribution *= 2; contribution++; } return contribution; }
/** * This method marks as invalid all actors that are iterated over by the given * iterator. The fact that an actor i is invalid is represented by setting * lflag[i] = lround. It is assumed that lflag[i] <= lround for all actors, * meaning that lflag[i] < lround holds for valid actors. The variable * validActorCount keeps track of the still valid actors. */ void InStructuralEquivalenceEffect::markInvalidActors(IncidentTieIterator iter, int & validActorCount) { while (iter.valid()) { if (this->lflag[iter.actor()] < this->lround) { this->lflag[iter.actor()] = this->lround; validActorCount--; } iter.next(); } }
/** * Calculates the double degree, for use in both calculateChangeContribution * and egoStatistic */ int DoubleDegreeBehaviorEffect::calculateDoubleDegree(int actor) const { int statistic = 0; IncidentTieIterator iter; const Network * pFirstNetwork = this->pFirstNetwork(); const Network * pSecondNetwork = this->pSecondNetwork(); if (this->lfirstDirection) // "F" { iter = pFirstNetwork->outTies(actor); } else // "B" { iter = pFirstNetwork->inTies(actor); } if (this->lsecondDirection <= 0) // "F" { for ( ; iter.valid(); iter.next()) { if (pSecondNetwork->tieValue(actor, iter.actor()) >= 1) { statistic++; } } } else if (this->lsecondDirection <= 1) // "B" { for ( ; iter.valid(); iter.next()) { if (pSecondNetwork->tieValue(iter.actor(), actor) >= 1) { statistic++; } } } else // (lsecondDirection == 2) // "R" { for ( ; iter.valid(); iter.next()) { if ((pSecondNetwork->tieValue(iter.actor(), actor) >= 1) && (pSecondNetwork->tieValue(actor, iter.actor()) >= 1)) { statistic++; } } } return statistic; }
/** * The contribution of the tie from the implicit ego to the given alter * to the statistic. It is assumed that preprocessEgo(ego) has been * called before. */ double SameCovariateActivityEffect::tieStatistic(int alter) { double contribution = 0; const Network * pNetwork = this->pNetwork(); if (!((this->missing(alter)) || (this->missing(this->ego())))) { double myvalue = this->value(this->ego()); if (lsame) { if (fabs(this->value(alter) - myvalue) < EPSILON) { for (IncidentTieIterator iter = pNetwork->outTies(this->ego()); iter.valid(); iter.next()) { // Get the receiver of the outgoing tie. int h = iter.actor(); if ((!this->missing(h)) && (fabs(this->value(h) - myvalue) < EPSILON)) { contribution++; } } } } else { if (fabs(this->value(alter) - myvalue) >= EPSILON) { for (IncidentTieIterator iter = pNetwork->outTies(this->ego()); iter.valid(); iter.next()) { // Get the receiver of the outgoing tie. int h = iter.actor(); if ((!this->missing(h)) && (fabs(this->value(h) - myvalue) >= EPSILON)) { contribution++; } } } } } return contribution; }
/** * Does the necessary preprocessing work for calculating the tie flip * contributions for a specific ego. This method must be invoked before * calling NetworkEffect::calculateTieFlipContribution(...). */ void TwoNetworkDependentBehaviorEffect::preprocessEgo(int ego) { // set up the covariate based on current values of the network and behavior const Network * pFirstNetwork = this->pFirstNetwork(); for (int i = 0; i < pFirstNetwork->n(); i++) { this->lfirstTotalAlterValues[i] = 0; if (pFirstNetwork->outDegree(i) > 0) { for (IncidentTieIterator iter = pFirstNetwork->outTies(i); iter.valid(); iter.next()) { int j = iter.actor(); this->lfirstTotalAlterValues[i] += this->centeredValue(j); // Rprintf("%d %f %d %d %d %d\n", // j, // this->centeredValue(j), // this->period(), } } else { this->lfirstTotalAlterValues[i] = 0; } // Rprintf("%d %f\n", i,this->ltotalAlterValues[i]); } for (int i = 0; i < pFirstNetwork->m(); i++) { this->lfirstTotalInAlterValues[i] = 0; if (pFirstNetwork->inDegree(i) > 0) { for (IncidentTieIterator iter = pFirstNetwork->inTies(i); iter.valid(); iter.next()) { int j = iter.actor(); this->lfirstTotalInAlterValues[i] += this->centeredValue(j); } } else { this->lfirstTotalInAlterValues[i] = 0; } } }
/** * Returns the statistic corresponding to the given ego with respect to the * given values of the behavior variable. */ double AltersCovariateAvAltEffect::egoStatistic(int ego, double * currentValues) { double statistic = 0; const Network * pNetwork = this->pNetwork(); int neighborCount = 0; for (IncidentTieIterator iter = pNetwork->outTies(ego); iter.valid(); iter.next()) { int j = iter.actor(); if (!this->missing(this->period(), j) && !this->missing(this->period() + 1, j) && !this->missingCovariate(j,this->period())) { statistic += currentValues[j] * this->covariateValue(j); neighborCount++; } } if ((neighborCount > 0) && (this->ldivide)) { statistic *= currentValues[ego] / neighborCount; } return statistic; }
/** * Calculates the change in the statistic corresponding to this effect if * the given actor would change his behavior by the given amount. */ double AltersCovariateAvAltEffect::calculateChangeContribution(int actor, int difference) { double contribution = 0; const Network * pNetwork = this->pNetwork(); if (pNetwork->outDegree(actor) > 0) { double totalAlterValue = 0; for (IncidentTieIterator iter = pNetwork->outTies(actor); iter.valid(); iter.next()) { int j = iter.actor(); // identifies alter double alterValue = this->centeredValue(j) * this->covariateValue(j); totalAlterValue += alterValue; } if (this->ldivide) { contribution = difference * totalAlterValue / pNetwork->outDegree(actor); } else { contribution = difference * totalAlterValue; } } return contribution; }
/** * Returns the statistic corresponding to the given ego as part of * the endowment function with respect to the initial values of a * behavior variable and the current values. */ double AltersCovariateAvAltEffect::egoEndowmentStatistic(int ego, const int * difference, double * currentValues) { double statistic = 0; const Network * pNetwork = this->pNetwork(); if (difference[ego] > 0 && !this->missingDummy(ego) && (pNetwork->outDegree(ego) > 0)) // otherwise, nothing to calculate... { double totalAlterValue = 0; for (IncidentTieIterator iter = pNetwork->outTies(ego); iter.valid(); iter.next()) { int j = iter.actor(); // identifies alter double alterValue = this->centeredValue(j) * this->covariateValue(j); totalAlterValue += alterValue; } if (this->ldivide) { statistic -= difference[ego] * totalAlterValue / pNetwork->outDegree(ego); } else { statistic -= difference[ego] * totalAlterValue; } } return statistic; }
/** * Calculates the change in the statistic corresponding to this effect if * the given actor would change his behavior by the given amount. */ double SimilarityEffect::calculateChangeContribution(int actor, int difference) { double contribution = 0; const Network * pNetwork = this->pNetwork(); if (pNetwork->outDegree(actor) > 0) { // The formula for the average similarity effect: // s_i(x) = avg(sim(v_i, v_j) - centeringConstant) over all neighbors // j of i. // sim(v_i, v_j) = 1.0 - |v_i - v_j| / observedRange // We need to calculate the change delta in s_i(x), if we changed // v_i to v_i + d (d being the given amount of change in v_i). // To this end, we can disregard the centering constant and // compute the average change in similarity, namely, // avg(sim(v_i + d, v_j) - sim(v_i, v_j)) = // avg(1 - |v_i+d-v_j|/range - 1 + |v_i-v_j|/range) = // avg(|v_i-v_j| - |v_i+d-v_j|) / range, // the average being taken over all neighbors of i. // The reasoning for avg. similarity x popularity alter effect is // similar. // This is what is calculated below. int oldValue = this->value(actor); int newValue = oldValue + difference; int totalChange = 0; for (IncidentTieIterator iter = pNetwork->outTies(actor); iter.valid(); iter.next()) { int j = iter.actor(); int alterValue = this->value(j); int change = std::abs(oldValue - alterValue) - std::abs(newValue - alterValue); if (this->lalterPopularity) { change *= pNetwork->inDegree(j); } totalChange += change; } contribution = ((double) totalChange) / this->range(); if (this->laverage) { contribution /= pNetwork->outDegree(actor); } if (this->legoPopularity) { contribution *= pNetwork->inDegree(actor); } } return contribution; }
/** * Returns the statistic corresponding to the given ego with respect to the * given values of the behavior variable. */ double AltersCovariateAvSimEffect::egoStatistic(int ego, double * currentValues) { const Network * pNetwork = this->pNetwork(); double statistic = 0; int neighborCount = 0; for (IncidentTieIterator iter = pNetwork->outTies(ego); iter.valid(); iter.next()) { int j = iter.actor(); if (!this->missing(this->period(), j) && !this->missing(this->period() + 1, j) && !this->missingCovariate(j, this->period())) { double tieStatistic = this->similarity(currentValues[ego], currentValues[j]); statistic += tieStatistic * this->covariateValue(j); neighborCount++; } } if (neighborCount > 0) { statistic /= neighborCount; } return statistic; }
/** * Returns the statistic corresponding to the given ego as part of * the endowment function with respect to the initial values of a * behavior variable and the current values. */ double AltersCovariateAvSimEffect::egoEndowmentStatistic(int ego, const int * difference, double * currentValues) { double statistic = 0; const Network * pNetwork = this->pNetwork(); if (difference[ego] > 0 && !this->missingDummy(ego) && (pNetwork->outDegree(ego) > 0)) // otherwise, nothing to calculate... { int oldValue = this->value(ego); // ego's behavior value before moving on behavior scale int newValue = oldValue + difference[ego]; // ego's behavior value after moving on behavior scale double totalChange = 0; // will keep track of changes for (IncidentTieIterator iter = pNetwork->outTies(ego); // loops over outgoing ties of ego iter.valid(); iter.next()) { int j = iter.actor(); // identifies alter int alterValue = this->value(j); // identifies behavior value of alter int change = std::abs(oldValue - alterValue) - std::abs(newValue - alterValue); // calculates impact of ego's movement on absolute difference to alter totalChange += change * this->covariateValue(j); // weighting change statistic acc. to covariate value of alter } statistic -= totalChange / this->range(); // standardize by behavior range for SIMILARITY function statistic /= pNetwork->outDegree(ego); // divide by outdegree to get AVERAGE similarity change statistic } return statistic; }
/** * Returns the value of this function for the given alter. It is assumed * that the function has been initialized before and pre-processed with * respect to a certain ego. */ double DifferentCovariateOutStarFunction::value(int alter) { int statistic = 0; if (!(this->lexcludeMissing && this->missing(alter))) { const Network * pNetwork = this->pNetwork(); // Iterate over incoming ties in network W for (IncidentTieIterator iter = pNetwork->inTies(this->ego()); iter.valid(); iter.next()) { // Get the sender of the incoming tie. int h = iter.actor(); // in-2-stars: if (!(this->lexcludeMissing && this->missing(h))) { if ((fabs(this->CovariateNetworkAlterFunction::value(h) - this->CovariateNetworkAlterFunction::value(this->ego())) > EPSILON) && ((lnotBothDifferent) || (fabs(this->CovariateNetworkAlterFunction::value(h) - this->CovariateNetworkAlterFunction::value(alter)) > EPSILON)) && (pNetwork->tieValue(alter, h) >= 1)) { statistic++ ; } } } } return statistic; }
/** * Calculates the change in the statistic corresponding to this effect if * the given actor would change his behavior by the given amount. */ double AltersCovariateAvSimEffect::calculateChangeContribution(int actor, int difference) { double contribution = 0; const Network * pNetwork = this->pNetwork(); if (pNetwork->outDegree(actor) > 0) // otherwise, nothing to calculate... { int oldValue = this->value(actor); // ego's behavior value before moving on behavior scale int newValue = oldValue + difference; // ego's behavior value after moving on behavior scale double totalChange = 0; // will keep track of changes for (IncidentTieIterator iter = pNetwork->outTies(actor); // loops over outgoing ties of ego iter.valid(); iter.next()) { int j = iter.actor(); // identifies alter int alterValue = this->value(j); // identifies behavior value of alter int change = std::abs(oldValue - alterValue) - std::abs(newValue - alterValue); // calculates impact of ego's movement on absolute difference to alter totalChange += change * this->covariateValue(j); // weighting change statistic acc. to covariate value of alter } contribution = totalChange / this->range(); // standardize by behavior range for SIMILARITY function contribution /= pNetwork->outDegree(actor); // divide by outdegree to get AVERAGE similarity change statistic } return contribution; }
/** * Returns the value of this function for the given alter. It is assumed * that the function has been initialized before and pre-processed with * respect to a certain ego. */ double SameCovariateMixedTwoPathFunction::value(int alter) { int statistic = 0; if (!(this->lexcludeMissing && this->missing(alter))) { const Network * pFirstNetwork = this->pFirstNetwork(); const Network * pSecondNetwork = this->pSecondNetwork(); for (IncidentTieIterator iter = pSecondNetwork->outTies(this->ego()); iter.valid(); iter.next()) { // Get the receiver of the outgoing tie. int h = iter.actor(); // 2-paths: if (!(this->lexcludeMissing && this->missing(h))) { if ((fabs(this->CovariateMixedNetworkAlterFunction::value(h) - this->CovariateMixedNetworkAlterFunction::value(this->ego())) < EPSILON) && (pFirstNetwork->tieValue(h, alter) >= 1)) { statistic++ ; } } } } return statistic; }
/** * Calculates the contribution of a tie flip to the given actor. */ double SameCovariateTransitiveTripletsEffect::calculateContribution( int alter) const { // If we are introducing a tie from the ego i to the alter j, then each // two-path from i to j with v_i = v_j contributes one unit; // in addition, each in-star i -> h <- j with v_i = v_h // also contributes one unit. // This number is not stored in a table and is calculated from scratch. int contribution1 = 0; const Network * pNetwork = this->pNetwork(); if (this->inequalityCondition(this->value(alter) - this->value(this->ego()))) { contribution1 = this->pTwoPathTable()->get(alter); } // The following probably can be done more efficiently // using CommonNeighborIterator. // Iterate over ego's outgoing ties for (IncidentTieIterator iter = pNetwork->outTies(this->ego()); iter.valid(); iter.next()) { // Get the receiver of the outgoing tie. int h = iter.actor(); if (this->inequalityCondition(this->value(h) - this->value(this->ego())) && pNetwork->tieValue(alter, h) >= 1) { contribution1++ ; } } return contribution1; }
/** * For each j and the given i, this method calculates the sum * sum_h w_{ih} x_{hj}. */ void WXXClosureEffect::calculateSums(int i, const Network * pNetwork, double * sums) const { int n = pNetwork->n(); // Initialize for (int j = 0; j < n; j++) { sums[j] = 0; } // Iterate over all h with non-zero non-missing w_{ih} for (DyadicCovariateValueIterator iterH = this->rowValues(i); iterH.valid(); iterH.next()) { int h = iterH.actor(); // Iterate over all j with a tie from h for (IncidentTieIterator iterJ = pNetwork->outTies(h); iterJ.valid(); iterJ.next()) { int j = iterJ.actor(); // Add the term w_{ih} x_{hj} (= w_{ih}) sums[j] += iterH.value(); } } }
/** * Returns the statistic corresponding to the given ego as part of * the endowment function with respect to the initial values of a * behavior variable and the current values. */ double AverageSimmelianAlterEffect::egoEndowmentStatistic(int ego, const int * difference, double * currentValues) { double statistic = 0; int simmelianOutdegree = 0; clearSimmelian(); updateSimmelian((const OneModeNetwork*) this->pNetwork()); // simulated state const Network * pNetwork = this->pNetwork(); if (difference[ego] > 0) { if (pNetwork->outDegree(ego) > 0) { double thisStatistic = 0; double previousStatistic = 0; for (IncidentTieIterator iter = pNetwork->outTies(ego); iter.valid(); iter.next()) { double alterValue = currentValues[iter.actor()]; double alterPreviousValue = currentValues[iter.actor()] + difference[iter.actor()]; if (pSimmelian->tieValue(ego, iter.actor()) > 0) { simmelianOutdegree ++; thisStatistic += alterValue; previousStatistic += alterPreviousValue; } } if (simmelianOutdegree >= 1) { thisStatistic *= currentValues[ego]; previousStatistic *= (currentValues[ego] + difference[ego]); statistic = thisStatistic - previousStatistic; if (this->ldivide) { statistic /= simmelianOutdegree; } } } } return statistic; }
/** * Returns the statistic corresponding to the given ego with respect to the * currentValues given for the behavior variable. */ double AverageAlterDist2Effect::egoStatistic(int i, double * currentValues) { double statistic = 0; const Network * pNetwork = this->pNetwork(); int neighborCount = 0; for (IncidentTieIterator iter = pNetwork->outTies(i); iter.valid(); iter.next()) { int j = iter.actor(); double alterValue = 0; int tieToi = 0; for (IncidentTieIterator iteri = pNetwork->outTies(j); iteri.valid(); iteri.next()) { if (i != iteri.actor()) { alterValue += currentValues[iteri.actor()]; } else { tieToi = 1; } } // tieToi = this->pNetwork()->tieValue(iter.actor(), i); if ((pNetwork->outDegree(j) > tieToi) & (this->ldivide2)) { alterValue /= (pNetwork->outDegree(j) - tieToi); } statistic += alterValue; neighborCount++; } if (neighborCount > 0) { statistic *= currentValues[i]; if (this->ldivide1) { statistic /= neighborCount; } } return statistic; }
/** * Calculates the change in the statistic corresponding to this effect if * the given actor would change his behavior by the given amount. * It is assumed that preprocessEgo(ego) has been called before. */ double AverageAlterDist2Effect::calculateChangeContribution(int actor, int difference) { double contribution = 0; const Network * pNetwork = this->pNetwork(); if (pNetwork->outDegree(actor) > 0) { // The formula for the effect: // s_i(x) = v_i * avg(v_j) over all neighbors j of i, // where v_j is the average behavior of j's neighbors, // excluding i. // We need to calculate the change delta in s_i(x), if we changed // v_i to v_i + d (d being the given amount of change in v_i). // This is d * avg(v_j) and is calculated below. // if (not divide1) or (not divide2), // instead of "avg" or "average" the total is used. double sumAlterValue = 0; for (IncidentTieIterator iter = pNetwork->outTies(actor); iter.valid(); iter.next()) { double alterValue = this->totalAlterValue(iter.actor()); int tieValue = this->pNetwork()->tieValue(iter.actor(), actor); if (tieValue == 1) { alterValue -= this->centeredValue(actor); } if (((pNetwork->outDegree(iter.actor()) - tieValue)> 0) & (this->ldivide2)) { alterValue /= (pNetwork->outDegree(iter.actor()) - tieValue); } sumAlterValue += alterValue; } contribution = difference * sumAlterValue; if (this->ldivide1) { contribution /= pNetwork->outDegree(actor); } } return contribution; }
/** * Returns the statistic corresponding to the given ego with respect to the * currentValues given for the behavior variable. */ double AverageAlterInDist2Effect::egoStatistic(int i, double * currentValues) { double statistic = 0; const Network * pNetwork = this->pNetwork(); int neighborCount = 0; for (IncidentTieIterator iter = pNetwork->outTies(i); iter.valid(); iter.next()) { int j = iter.actor(); double alterValue = 0; for (IncidentTieIterator iteri = pNetwork->inTies(j); iteri.valid(); iteri.next()) { if (i != iteri.actor()) { alterValue += currentValues[iteri.actor()]; } } // tieFromi = this->pNetwork()->tieValue(i, iter.actor()); if ((pNetwork->inDegree(j) > 1) & (this->ldivide2)) { alterValue /= (pNetwork->inDegree(j) - 1); // there always is a tie i -> iteri.actor() } statistic += alterValue; neighborCount++; } if (neighborCount > 0) { statistic *= currentValues[i]; if (this->ldivide1) { statistic /= neighborCount; } } return statistic; }
/** * This method indicated that there are no two-paths from <i>i</i> to <i>j</i> * via an intermediate actor below the given bound. */ bool OneModeNetwork::noTwoPaths(int i, int j, int intermediateActorUpperBound) const { this->checkSenderRange(i); this->checkReceiverRange(j); // Iterate the outgoing ties of i and incoming ties of j simultaneously // and check if there are no matching neighbors below the given bound. // We can terminate the loop as soon as one of the iterators reaches // the bound. IncidentTieIterator outIter = this->outTies(i); IncidentTieIterator inIter = this->inTies(j); bool found = false; while (outIter.valid() && inIter.valid() && !found && outIter.actor() < intermediateActorUpperBound && inIter.actor() < intermediateActorUpperBound) { if (outIter.actor() < inIter.actor()) { outIter.next(); } else if (outIter.actor() > inIter.actor()) { inIter.next(); } else { found = true; } } return !found; }
/** * Calculates the statistic corresponding to the given ego. The variable * pSummationTieNetwork is the current network in the case of an evaluation * effect and the network of lost ties in the case of an endowment effect. */ double NetworkEffect::egoStatistic(int ego, const Network * pSummationTieNetwork) { double statistic = 0; for (IncidentTieIterator iter = pSummationTieNetwork->outTies(ego); iter.valid(); iter.next()) { statistic += this->tieStatistic(iter.actor()); } return statistic; }
/** * Indicates if all ties are reciprocated with the same value. */ bool OneModeNetwork::symmetric() const { // The current implementation is linear in the total number of ties. // The time complexity can be reduced to a constant by maintaining // the number of non-symmetric ties. // Assume the network is symmetric until we can disprove it. bool rc = true; // Test the incoming and outgoing ties of each actor in turn. for (int i = 0; i < this->n() && rc; i++) { if (this->outDegree(i) == this->inDegree(i)) { IncidentTieIterator outIter = this->outTies(i); IncidentTieIterator inIter = this->inTies(i); // No need to test both iterators for validity, as the numbers // of incoming and outgoing ties are the same. while (outIter.valid() && rc) { if (outIter.actor() != inIter.actor() || outIter.value() != inIter.value()) { // Found a mismatch. rc = false; } outIter.next(); inIter.next(); } } else { // The numbers of incoming and outgoing ties differ, which // destroys the symmetry immediately. rc = false; } } return rc; }
/** * Calculates the contribution of a tie flip to the given actor. */ double CovariateIndirectTiesEffect::calculateContribution(int alter) const { double change = 0; // If there are enough two-paths from the ego i to the alter j, then // we loose the distance 2 pair (i,j) by introducing the tie between // them. if (this->pTwoPathTable()->get(alter) != 0) { change -= this->value(alter); } // This variable is to simplify the later tests if a two-path through // the given alter makes a difference. int criticalTwoPathCount = 0; if (this->outTieExists(alter)) { criticalTwoPathCount = 1; } // Consider each outgoing tie of the alter j. for (IncidentTieIterator iter = this->pNetwork()->outTies(alter); iter.valid(); iter.next()) { int h = iter.actor(); // If h is not the ego i, there's no tie from i to h, and the // introduction or withdrawal of the tie (i,j) makes a difference // for the pair <i,h> to be a valid distance two pair, // then increment the contribution. if (h != this->ego() && !this->outTieExists(h) && this->pTwoPathTable()->get(h) == criticalTwoPathCount) { change += this->value(h); } } return change; }
/** * Initializes the layer given the reference network is a two mode * network. */ void DistanceTwoLayer::initializeTwoMode(const Network& rNetwork) { // this is a two mode network so we do not need to check for loops // nor do we have to store the reciever two paths. for (int i = 0; i < rNetwork.m(); ++i) { // construct all pairs for (IncidentTieIterator outerIter = rNetwork.inTies(i); outerIter.valid(); outerIter.next()) { int outerActor = outerIter.actor(); // copy the iterator IncidentTieIterator innerIter(outerIter); // move to the next position innerIter.next(); for (; innerIter.valid(); innerIter.next()) { modifyTieValue(outerActor, innerIter.actor(), 1); } } } }