Power
This section demonstrates raising secret-shared values to a power. As always, this is computed element-wise on arrays of any shape.
Note that for this function, we are raising secret-shared values to a public, unencoded, integer power that is known to all players. The results are secret shared, maintaining the privacy of the inputs.
In this case, we raise a vector of values \([-1, 2, 3.4, -2.3]\) to the power 3, returning \([-1, 8, 39.304, -12.167]\)
[1]:
import logging
import numpy
from cicada.additive import AdditiveProtocolSuite
from cicada.communicator import SocketCommunicator
from cicada.logging import Logger
logging.basicConfig(level=logging.INFO)
def main(communicator):
log = Logger(logging.getLogger(), communicator)
protocol = AdditiveProtocolSuite(communicator)
base = numpy.array([-1, 2, 3.4, -2.3]) if communicator.rank == 0 else None
exponent = numpy.array(3, dtype=int)
log.info(f"Player {communicator.rank} base: {base}", src=0)
log.info(f"Player {communicator.rank} exponent: {exponent}")
base_share = protocol.share(src=0, secret=base, shape=(4,))
power_share = protocol.power(base_share, exponent)
power = protocol.reveal(power_share)
log.info(f"Player {communicator.rank} power: {power}")
SocketCommunicator.run(world_size=3, fn=main);
INFO:root:Player 0 base: [-1. 2. 3.4 -2.3]
INFO:root:Player 0 exponent: 3
INFO:root:Player 1 exponent: 3
INFO:root:Player 2 exponent: 3
INFO:root:Player 0 power: [ -1. 8. 39.30377197 -12.16679382]
INFO:root:Player 1 power: [ -1. 8. 39.30377197 -12.16679382]
INFO:root:Player 2 power: [ -1. 8. 39.30377197 -12.16679382]
Note that the results 39.30381775 and -12.16680908 are slightly off due to the limited precision of our fixed point encoding.