Logical Not

In this example, we will generate a small secret shared vector of random bits, then apply Cicada’s logical negation operator to flip them elementwise.

Note that the secret inputs to logical_not() must be the field values \(0\) or \(1\), producing similar outputs. We use the Bits encoding to reveal the output because the default FixedPoint encoding would produce unexpected results.

[1]:
import logging

import numpy

from cicada.additive import AdditiveProtocolSuite
from cicada.communicator import SocketCommunicator
from cicada.encoding import Bits
from cicada.logging import Logger

logging.basicConfig(level=logging.INFO)

def main(communicator):
    log = Logger(logging.getLogger(), communicator)
    protocol = AdditiveProtocolSuite(communicator)
    generator = numpy.random.default_rng(seed=1234)

    bits_share, _ = protocol.random_bitwise_secret(generator=generator, bits=8)
    negated_bits_share = protocol.logical_not(bits_share)

    bits = protocol.reveal(bits_share, encoding=Bits())
    negated_bits = protocol.reveal(negated_bits_share, encoding=Bits())

    log.info(f"Player {communicator.rank} bits: {bits} negated bits: {negated_bits}")

SocketCommunicator.run(world_size=3, fn=main);
INFO:root:Player 0 bits: [1 1 1 0 0 1 0 0] negated bits: [0 0 0 1 1 0 1 1]
INFO:root:Player 1 bits: [1 1 1 0 0 1 0 0] negated bits: [0 0 0 1 1 0 1 1]
INFO:root:Player 2 bits: [1 1 1 0 0 1 0 0] negated bits: [0 0 0 1 1 0 1 1]