Skip to content

Ensure listening coefficients never drops to 0#800

Open
fernandofcampos wants to merge 2 commits intodevfrom
ENGN-3543
Open

Ensure listening coefficients never drops to 0#800
fernandofcampos wants to merge 2 commits intodevfrom
ENGN-3543

Conversation

@fernandofcampos
Copy link
Contributor

@fernandofcampos fernandofcampos commented Apr 11, 2025

Purpose of Changes and their Description

Link(s) to Ticket(s) or Issue(s) resolved by this PR

Are these changes tested and documented?

  • If tested, please describe how. If not, why tests are not needed.
  • If documented, please describe where. If not, describe why docs are not needed.
  • Added to Unreleased section of CHANGELOG.md?

Still Left Todo

Fill this out if this is a Draft PR so others can help.

@fernandofcampos fernandofcampos force-pushed the ENGN-3543 branch 2 times, most recently from 447c72b to eaf0d4d Compare April 16, 2025 14:23
@fernandofcampos fernandofcampos marked this pull request as ready for review April 16, 2025 14:24
@fernandofcampos fernandofcampos force-pushed the ENGN-3543 branch 3 times, most recently from 5591d37 to 80384a6 Compare April 16, 2025 14:40
Copy link
Contributor

@xmariachi xmariachi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments (a full review on the most complicated parts is pending)

Copy link
Contributor

@amimart amimart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I go some first remarks here, didn't check the whole PR yet

@fernandofcampos fernandofcampos force-pushed the ENGN-3543 branch 3 times, most recently from f50ce77 to 47e408e Compare May 5, 2025 14:13
Comment on lines +13 to +16
const epsilon = "1e-18"

// EpsilonDec represents a small positive value (1e-18), used to prevent division by zero or issues with zero values.
var EpsilonDec = alloraMath.MustNewDecFromString(epsilon)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have this value in emissions params, it's called EpsilonSafeDiv, please reuse it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with using that is that it implies reading from the keeper when we need it. I will see if I can optimize it.

Comment on lines +1004 to +1025
topicId1 := s.setUpTopic(blockHeight2, workerIndexes, reputerIndexes, stake, alphaRegret)

// Add additional stake to each reputer for second topic
for _, index := range reputerIndexes {
s.MintTokensToAddress(s.addrs[index], stake)
_, err := s.msgServer.AddStake(s.ctx, &types.AddStakeRequest{
Sender: s.addrsStr[index],
Amount: stake,
TopicId: topicId1,
})
require.NoError(err)
}

// Fund the second topic with the same significant initial stake
s.MintTokensToAddress(s.addrs[reputerIndexes[0]], initialStake)
fundTopicMessage = types.FundTopicRequest{
Sender: s.addrsStr[reputerIndexes[0]],
TopicId: topicId1,
Amount: initialStake,
}
_, err = s.msgServer.FundTopic(s.ctx, &fundTopicMessage)
require.NoError(err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like you're staking and topic funding both inside and outside the setUpTopic function. Is that intended? If not, please review other cases

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't realize setUpTopic was already doing that. I cleaned up the tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment on lines +177 to +178
// Use a more lenient epsilon value (1% instead of 0.001%)
testutil.InEpsilon2(s.T(), reputerScore.Score, expectedScores[i].String())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these changes compromising reputer scoring accuracy? If yes, has it already been double-checked with the research team to see if it's ok?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, because of the normalization (check at x/emissions/module/rewards/scores.go). I will double check with research.

@fernandofcampos fernandofcampos force-pushed the ENGN-3543 branch 3 times, most recently from fe49dfc to 6e2c27d Compare May 7, 2025 14:28
Copy link

@fstecker fstecker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we discussed today, it would be great if you could wait with this PR until we have some potential problems in the design figured out.

}

// If all stakes are zero, use epsilon values instead to avoid division by zero
if allZeroOrEpsilon {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the whole allZeroOrEpsilon thing redundant? If the only thing that happens in there is also inside the if allZero?

max, err := alloraMath.Max(
coefficientsPlusLearningRateTimesGradient,
alloraMath.ZeroDec(),
EpsilonDec,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This wouldn't allow any of the listening coefficients to go below epsilon? I think that should still be allowed, we only need to check that they don't all become zero (or equivalently, their sum isn't zero). I think we already do this elsewhere, so this shouldn't be necessary?


// Only normalize coefficients when there are multiple reputers
// When there's only one reputer, normalization is unnecessary and would force the value to 1.0
if len(reputerListeningCoefficients) > 1 {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that's necessary. If there's only one reputer, its listening coefficient doesn't matter anyway (the losses will be whatever this reputer says, what else should it be).

return nil, nil, errors.Wrapf(err, "GetAllReputersOutput, error normalizing coefficient %d", j)
}
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm having second thoughts about the normalization, and now think it might be better to normalize so that the max listening coefficient is 1, instead of normalizing so the sum is 1. That would make the listenedStakeFraction as high as possible and the if listenedStakeFraction.Lt(params.MinStakeFraction) branch less likely to be taken. Which might improve convergence. Maybe. I'll think about it some more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants