def __init__(self, n, string_format=None, latex_format=None): if string_format is None: string_format = str(n) Literal.__init__(self, string_format, extra_core_info=[str(n)], theory=__file__) if not isinstance(n, int): raise ValueError("'n' of a Numeral must be an integer") self.n = n
class HexSequence(NumeralSequence): # operator of the BinarySequence operation. _operator_ = Literal(string_format='Hex', theory=__file__) def __init__(self, *bits, styles=None): NumeralSequence.__init__(self, HexSequence._operator_, *bits, styles=styles) for digit in self.digits: if is_irreducible_value(digit) and digit not in HEXDIGITS: raise Exception( 'A HexSequence may only be composed of 0-f hex digits') def as_int(self): if all(digit in HEXDIGITS for digit in self.digits): return eval(self.formatted('string')) raise ValueError("Cannot convert %s to an integer; the hexdigits " "are not all irreducible") def _prefix(self, format_type): if format_type == 'string': return 'x' # prefix to indicate a binary representation elif format_type == 'latex': return r'\textrm{x}' else: raise ValueError("'format_type', %s, not recognized" % format_type)
class Prod(OperationOverInstances): # operator of the Prod operation. _operator_ = Literal(string_format='Prod', latex_format=r'prod', theory=__file__) # def __init__(self, summand-instance_expression, indices-instance_vars, domains): # def __init__(self, instance_vars, instance_expr, conditions = tuple(), domain=EVERYTHING): # def __init__(self, indices, summand, domain, *, condition=None, conditions=None, styles=None): r''' Sum summand over indices over domains. Arguments serve analogous roles to Forall arguments (found in basiclogic.booleanss): indices: instance vars summand: instance_expressions domains: conditions (except no longer optional) ''' OperationOverInstances.__init__(self, Prod._operator_, indices, summand, domain=domain, condition=condition, conditions=conditions, styles=styles)
class Set(Operation): ''' Defines a set with only one item. ''' # operator of the Set operation _operator_ = Literal(stringFormat='Set', context=__file__) def __init__(self, *elems): Operation.__init__(self, Set._operator_, elems) self.elements = self.operands def membershipObject(self, element): from enum_membership import EnumMembership return EnumMembership(element, self) def nonmembershipObject(self, element): from enum_membership import EnumNonmembership return EnumNonmembership(element, self) def string(self, **kwargs): return '{' + self.elements.string(fence=False) + '}' def latex(self, **kwargs): return r'\left\{' + self.elements.latex(fence=False) + r'\right\}'
class Gate(Operation): ''' Represents a gate in a quantum circuit. Updated 1/26/2020 by wdc. ''' # the literal operator of the Gate operation class _operator_ = Literal('GATE', context=__file__) def __init__(self, gate_operation): ''' Create a quantum circuit gate performing the given operation. ''' Operation.__init__(self, Gate._operator_, gate_operation) self.gate_operation = self.operands[0] print("self.gate_operation = {}".format( self.gate_operation)) # for testing; delete later print("type(self.gate_operation) = {}".format(type( self.gate_operation))) # for testing; delete later # look here more carefully later, some changes during the project meeting def formatted(self, formatType, **kwargs): print("Entering Gate.formatted.") # for testing; delete later print(" formatType = {}".format( formatType)) # for testing; delete later formattedGateOperation = (self.gate_operation.formatted(formatType, fence=False)) print(" formattedGateOperation = {}".format( formattedGateOperation)) # for testing; delete later if formatType == 'latex': print(" inside if formatType=latex block" ) # for testing; delete later return r'\gate{' + formattedGateOperation + r'}' else: return Operation._formatted(self, formatType)
class Prod(OperationOverInstances): # operator of the Prod operation. _operator_ = Literal(stringFormat='Prod', latexFormat=r'prod', context=__file__) # def __init__(self, summand-instanceExpression, indices-instanceVars, domains): # def __init__(self, instanceVars, instanceExpr, conditions = tuple(), domain=EVERYTHING): # def __init__(self, indices, summand, domain, conditions=tuple()): r''' Sum summand over indices over domains. Arguments serve analogous roles to Forall arguments (found in basiclogic/booleans): indices: instance vars summand: instanceExpressions domains: conditions (except no longer optional) ''' # nestMultiIvars=True will cause it to treat multiple instance variables as nested Prod operations internally # and only join them together as a style consequence. OperationOverInstances.__init__(self, Prod._operator_, indices, summand, domain=domain, conditions=conditions, nestMultiIvars=True)
class Sqrt(Operation): # operator of the Exp operation. _operator_ = Literal(stringFormat='sqrt', context=__file__) def __init__(self, base): r''' Take the square root of the base. ''' Operation.__init__(self, Sqrt._operator_, base) self.base = base def latex(self, **kwargs): return r'\sqrt{' + self.base.latex() + '}' def distribute(self): ''' Distribute the sqrt over a product. ''' from proveit.number import Mult from theorems import sqrtOfProd if isinstance(self.base, Mult): deduceInRealsPos(self.base.factors) return sqrtOfProd({xEtc: self.base.factors}) def _closureTheorem(self, numberSet): import theorems from proveit.number import two if numberSet == Reals: return theorems.sqrtRealClosure elif numberSet == RealsPos: return theorems.sqrtRealPosClosure elif numberSet == Complexes: return theorems.sqrtComplexClosure
class RegisterBra(Operation): ''' Class to represent a Dirac bra vector that acknowledges the size of the register. Intended params are not quite clear ... ''' # the literal operator of the RegisterBra operation _operator_ = Literal(stringFormat='REGISTER_BRA', context=__file__) def __init__(self, label, size): Operation.__init__(self, RegisterBra._operator_, (label, size)) self.label = self.operands[0] # value self.size = self.operands[1] # size of the register def _config_latex_tool(self, lt): Operation._config_latex_tool(self, lt) # Expression._config_latex_tool(self, lt) if not 'mathtools' in lt.packages: lt.packages.append('mathtools') def _formatted(self, formatType, fence=False): formattedLabel = self.label.formatted(formatType, fence=False) formattedSize = self.size.formatted(formatType, fence=False) if formatType == 'latex': # can't seem to get the \prescript latex to work, so using # a temporary work-around with an 'empty' subscript; much # googling hasn't uncovered explanation for why \prescript # isn't working in the ipynbs # return (r'\prescript{}{' + formattedSize + r'}\langle ' # + formattedLabel + r' \rvert') return (r'{_{' + formattedSize + r'}}\langle ' + formattedLabel + r' \rvert') else: return '{' + formattedSize + '}_' + u'\u2329' + formattedLabel + '|'
class Bra(Function): ''' Class to represent a Dirac bra vector of the form ⟨0| or ⟨1|. ''' # the literal operator of the Bra operation _operator_ = Literal(string_format='BRA', theory=__file__) def __init__(self, label): Function.__init__(self, Bra._operator_, label) self.label = self.operands[0] # might need to change def string(self, **kwargs): return self.formatted('string', **kwargs) def latex(self, **kwargs): return self.formatted('latex', **kwargs) def formatted(self, format_type, **kwargs): if format_type == 'latex': return (r'\langle ' + self.label.formatted(format_type, fence=False) + r' \rvert') else: # using the unicode \u2329 for the left angle bracket return (u'\u2329' + self.label.formatted(format_type, fence=False) + '|')
class Ket(Function): ''' Class to represent a Dirac ket vector of the form |0⟩ or |1⟩. ''' # the literal operator of the Ket operation _operator_ = Literal(string_format='KET', theory=__file__) def __init__(self, label): Function.__init__(self, Ket._operator_, label) self.label = self.operands[0] def string(self, **kwargs): return self.formatted('string', **kwargs) def latex(self, **kwargs): return self.formatted('latex', **kwargs) def formatted(self, format_type, no_lvert=False, **kwargs): left_str = r'\lvert ' if format_type == 'latex' else '|' if no_lvert: left_str = '' if format_type == 'latex': return (left_str + self.label.formatted(format_type, fence=False) + r' \rangle') else: # using the unicode \u232A for the right angle bracket return (left_str + self.label.formatted(format_type, fence=False) + u'\u232A')
class RegisterKet(Function): ''' Class to represent a Dirac ket vector that acknowledges the size of the register on which it is defined. ''' # the literal operator of the RegisterKet operation _operator_ = Literal(string_format='REGISTER_KET', theory=__file__) def __init__(self, label, size): Function.__init__(self, RegisterKet._operator_, (label, size)) self.label = self.operands[0] # value for the ket self.size = self.operands[1] # size of the register def string(self, **kwargs): return self.formatted('string', **kwargs) def latex(self, **kwargs): return self.formatted('latex', **kwargs) def formatted(self, format_type, fence=False, no_lvert=False): formatted_label = self.label.formatted(format_type, fence=False) formatted_size = self.size.formatted(format_type, fence=False) left_str = r'\lvert ' if format_type == 'latex' else '|' if no_lvert: left_str = '' if format_type == 'latex': return (left_str + formatted_label + r' \rangle_{' + formatted_size + '}') else: return (left_str + formatted_label + u'\u232A' + '_{' + formatted_size + '}')
class MatrixExp(Operation): ''' Matrix dot product of any number of operands. ''' _operator_ = Literal(string_format='ExpM', theory=__file__) def __init__(self, base, exponent, *, styles=None): r''' Raise matrix 'base' to exponent power. ''' self.base = base self.exponent = exponent Operation.__init__(self, MatrixExp._operator_, (base, exponent), styles=styles) def string(self, **kwargs): return self.formatted('string', **kwargs) def latex(self, **kwargs): return self.formatted('latex', **kwargs) def formatted(self, format_type, **kwargs): # begin building the inner_str inner_str = self.base.formatted( format_type, fence=True, force_fence=True) inner_str = ( inner_str + r'^{' + self.exponent.formatted(format_type, fence=False) + '}') # only fence if force_fence=True (nested exponents is an # example of when fencing must be forced) kwargs['fence'] = ( kwargs['force_fence'] if 'force_fence' in kwargs else False) return maybe_fenced_string(inner_str, **kwargs)
class Output(QcircuitElement): ''' Represents an output state exiting from the right-hand side of a circuit. ''' # the literal operator of the Output operation class _operator_ = Literal('OUTPUT', theory=__file__) def __init__(self, state, *, part=None, styles=None): ''' Create an OUTPUT operation with the given input state. ''' if part is None: operands = NamedExprs(("state", state)) else: operands = NamedExprs(("state", state), ("part", part)) QcircuitElement.__init__(self, Output._operator_, operands, styles=styles) def circuit_elem_latex(self, *, show_explicitly): ''' Display the LaTeX for this Output circuit element. ''' if show_explicitly and hasattr(self, 'part'): return r'& \qout{%s~\mbox{part}~%s}' % (self.state.latex(), self.part.latex()) return r'& \qout{' + self.state.latex() + r'}' @relation_prover def deduce_equal_or_not(self, rhs, **defaults_config): from . import qcircuit_output_eq, qcircuit_output_neq return self._deduce_equal_or_not(rhs, 'state', qcircuit_output_eq, qcircuit_output_neq)
class Prob(Operation): ''' Updated Sun 1/26/2020 by wdc: updating the __init__ and _formatted methods, import statements. deduceInInterval and deduceInReals methods untouched. ''' # the literal operator of the Prob operation class _operator_ = Literal('PROB', context=__file__) def __init__(self, event, random_variable): Operation.__init__(self, Prob._operator_, (event, random_variable)) self.event = self.operands[0] self.random_variable = self.operands[1] def _formatted(self, formatType, fence=False): formattedEvent = self.event.formatted(formatType, fence=False) formattedVar = self.random_variable.formatted(formatType, fence=False) return 'Pr_{' + formattedVar + '}[' + formattedEvent + ']' def deduceInInterval(self): from axioms import probBetweenZeroAndOne return probBetweenZeroAndOne.specialize({ x: self.random_variable, X: self.event }) def deduceInReals(self): from theorems import probInReals return probInReals.specialize({x: self.random_variable, X: self.event})
class Union(Operation): # operator of the Intersect operation _operator_ = Literal(string_format='union', latex_format=r'\cup', theory=__file__) def __init__(self, *operands, styles=None): ''' Union any number of sets: A union B union C ''' Operation.__init__(self, Union._operator_, operands, styles=styles) def membership_object(self, element): from .union_membership import UnionMembership return UnionMembership(element, self) def nonmembership_object(self, element): from .union_membership import UnionNonmembership return UnionNonmembership(element, self) @relation_prover def deduce_superset_eq_relation(self, superset, **defaults_config): # Check for special case of a union subset # A_1 union ... union ... A_m \subseteq S from . import union_inclusion _A = self.operands _m = _A.num_elements() _S = superset return union_inclusion.instantiate({A: _A, m: _m, S: _S})
class InSet(InClass): ''' Set membership is a special case of class membership, so we'll derive from InClass for code re-use. The operators are distinct (though the formatting is the same). ''' # operator of the InSet operation _operator_ = Literal(string_format='in', latex_format=r'\in', theory=__file__) # map (element, domain) pairs to corresponding InSet expressions inset_expressions = dict() def __init__(self, element, domain, *, styles=None): element = single_or_composite_expression(element) domain = single_or_composite_expression(domain) InSet.inset_expressions[(element, domain)] = self InClass.__init__(self, element, domain, operator=InSet._operator_, styles=styles) def negated(self): ''' Return the negated membership expression, element not in domain. ''' from .not_in_set import NotInSet return NotInSet(self.element, self.domain)
class DividesProper(DividesRelation): ''' DividesProper(x, y) represents the claim that x divides y (i.e. x|y) but x != y. x|y is equivalent to saying that x is a factor of y, y is a multiple of x, or y/x is an integer). This class is still under development, with the class stub located here so that we have a 'strong relation' class version of Divides that can be called from the DividesRelation class, which in turn allows us to use the TransitiveRelation.concude_via_transitivity() method. ''' _operator_ = Literal(string_format='|', latex_format=r'{\rvert_{P}}', theory=__file__) # map left-hand-sides to "Divides" Judgments # (populated in TransitivityRelation.side_effects) known_left_sides = dict() # map right-hand-sides to "Divides" Judgments # (populated in TransitivityRelation.side_effects) known_right_sides = dict() def __init__(self, a, b, *, styles=None): DividesRelation.__init__(self, DividesProper._operator_, a, b, styles=styles)
class Disjoint(Function): ''' The Disjoint operation defines a property for a collection of sets. It evaluates to True iff the sets are mutually/pairwise disjoint; that is, the intersection of any two of the sets is the empty set. We define this property to be True when given zero or one set (there are no pairs of sets, so all pairs are vacuously disjoint). ''' _operator_ = Literal('disjoint', r'\textrm{disjoint}', theory=__file__) def __init__(self, *sets, styles=None): Function.__init__(self, Disjoint._operator_, sets, styles=styles) self.sets = self.operands @prover def conclude(self, **defaults_config): ''' Conclude that sets are Disjoint. One of the sets must have a 'deduce_disjointness' method for this to work. ''' for operand in self.sets: if hasattr(operand, 'deduce_disjointness'): return operand.deduce_disjointness(self) raise NotImplementedError("Cannot conclude %s; non of the sets have a " "'deduce_disjointness' method." % self)
class IntervalCC(RealInterval): # operator of the IntervalCC operation. _operator_ = Literal(string_format='IntervalCC', theory=__file__) def __init__(self, lower_bound, upper_bound, *, styles=None): RealInterval.__init__( self, IntervalCC._operator_, lower_bound, upper_bound, styles=styles) def string(self, **kwargs): return '[' + self.lower_bound.string() + ',' + \ self.upper_bound.string() + ']' def latex(self, **kwargs): return (r'\left[' + self.lower_bound.latex() + ',' + self.upper_bound.latex() + r'\right]') def membership_object(self, element): from .real_interval_membership import IntervalCCMembership return IntervalCCMembership(element, self) def nonmembership_object(self, element): from .real_interval_membership import RealIntervalNonmembership return RealIntervalNonmembership(element, self) @prover def deduce_elem_in_set(self, member, **defaults_config): from . import in_IntervalCC return in_IntervalCC.instantiate( {a: self.lower_bound, b: self.upper_bound, x: member}, auto_simplify=False) @prover def deduce_member_lower_bound(self, member, **defaults_config): from . import interval_cc_lower_bound return interval_cc_lower_bound.instantiate( {a: self.lower_bound, b: self.upper_bound, x: member}, auto_simplify=False) @prover def deduce_member_upper_bound(self, member, **defaults_config): from . import interval_cc_upper_bound return interval_cc_upper_bound.instantiate( {a: self.lower_bound, b: self.upper_bound, x: member}, auto_simplify=False) @prover def deduce_member_in_real(self, member, **defaults_config): from . import all_in_interval_cc__is__real return all_in_interval_cc__is__real.instantiate( {a: self.lower_bound, b: self.upper_bound, x: member}, auto_simplify=False) @prover def deduce_rescaled_membership(self, member, scale_factor, **defaults_config): from . import rescale_interval_cc_membership return rescale_interval_cc_membership.instantiate( {a: self.lower_bound, b: self.upper_bound, c: scale_factor, x: member}) # auto-simplification possible
class MatrixProd(Operation): ''' Matrix dot product of any number of operands. ''' # the literal operator of the MatrixProd operation # perhaps use MATRIX_PROD for string? # latexFormat try using \; in place of a blank space _operator_ = Literal(stringFormat=r'.', latexFormat = r'\thinspace', context=__file__) def __init__(self, *operands): r''' Matrix dot product of any number of operands. ''' Operation.__init__(self, MatrixProd._operator_, operands) def formatted(self, formatType, fence=False, subFence=True): # Temporary hack to get quantum bra and ket products to display properly. # This should eventually be done differently because we shouldn't need to # know anything about the quantum application here. from proveit.physics.quantum import Bra, Ket, RegisterBra, RegisterKet if len(self.operands) == 2 and (isinstance(self.operands[0], Bra) or isinstance(self.operands[0], RegisterBra)) and (isinstance(self.operands[1], Ket) or isinstance(self.operands[1], RegisterKet)): return self.operands[0].formatted(formatType) + self.operands[1].formatted(formatType, no_lvert=True) # return Operation.formatted(self, formatType, fence, subFence) return Operation._formatted(self, formatType=formatType, fence=fence, subFence=subFence)
class Functions(Operation): ''' A set of functions from a domain to a codomain. ''' _operator_ = Literal('Functions', r'\textrm{Functions}', theory=__file__) def __init__(self, domain, codomain, *, styles=None): Operation.__init__(self, Functions._operator_, (domain, codomain), styles=styles) self.domain = domain self.codomain = codomain def membership_object(self, element): from .functions_membership import FunctionsMembership return FunctionsMembership(element, self) def latex(self, **kwargs): domain_str = self.domain.latex(fence=True) codomain_str = self.codomain.latex(fence=True) return (r'\left[' + domain_str + r' \rightarrow ' + codomain_str + r'\right])') def string(self, **kwargs): domain_str = self.domain.string(fence=True) codomain_str = self.codomain.string(fence=True) return (r'[' + domain_str + r' -> ' + codomain_str + r']')
class NotSubsetEq(Operation): # operator of the NotSubsetEq operation _operator_ = Literal(stringFormat='nsubseteq', latexFormat=r'\nsubseteq', context=__file__) def __init__(self, subset, superset): Operation.__init__(self, NotSubsetEq._operator_, (subset, superset)) def deriveSideEffects(self, knownTruth): self.unfold(knownTruth.assumptions) # unfold as an automatic side-effect def conclude(self, assumptions): return self.concludeAsFolded(assumptions) def unfold(self, assumptions=USE_DEFAULTS): ''' From A nsubseteq B, derive and return not(supseteq(A, B)). ''' from ._theorems_ import unfoldNotSubsetEq return unfoldNotSubsetEq.specialize({A:self.operands[0], B:self.operands[1]}, assumptions=assumptions) def concludeAsFolded(self, assumptions=USE_DEFAULTS): ''' Derive this folded version, A nsupset B, from the unfolded version, not(A supset B). ''' from ._theorems_ import foldNotSubsetEq return foldNotSubsetEq.specialize({A:self.operands[0], B:self.operands[1]}, assumptions=assumptions)
class Mod(Operation): # operator of the Mod operation. _operator_ = Literal(stringFormat='mod', latexFormat=r'~\rm{mod}~', context=__file__) def __init__(self, dividend, divisor): Operation.__init__(self, Mod._operator_, (dividend, divisor)) self.dividend = self.operands[0] self.divisor = self.operands[1] def _closureTheorem(self, numberSet): from . import theorems if numberSet == Integers: return theorems.modIntClosure elif numberSet == Reals: return theorems.modRealClosure def deduceInInterval(self, assumptions=frozenset()): from .theorems import modInInterval, modInIntervalCO from numberSets import deduceInIntegers, deduceInReals try: # if the operands are integers, then we can deduce that a mod b is in 0..(b-1) deduceInIntegers(self.operands, assumptions) return modInInterval.specialize({ a: self.dividend, b: self.divisor }).checked(assumptions) except: # if the operands are reals, then we can deduce that a mod b is in [0, b) deduceInReals(self.operands, assumptions) return modInIntervalCO.specialize({ a: self.dividend, b: self.divisor }).checked(assumptions)
class Prob(Operation): ''' Updated Sun 1/26/2020 by wdc: updating the __init__ and _formatted methods, import statements. deduce_in_interval and deduce_in_real methods untouched. ''' # the literal operator of the Prob operation class _operator_ = Literal('PROB', theory=__file__) def __init__(self, event, random_variable): Operation.__init__(self, Prob._operator_, (event, random_variable)) self.event = self.operands[0] self.random_variable = self.operands[1] def _formatted(self, format_type, fence=False): formatted_event = self.event.formatted(format_type, fence=False) formatted_var = self.random_variable.formatted(format_type, fence=False) return 'Pr_{' + formatted_var + '}[' + formatted_event + ']' def deduce_in_interval(self): from axioms import prob_between_zero_and_one return prob_between_zero_and_one.instantiate({ x: self.random_variable, X: self.event }) def deduce_in_real(self): from theorems import prob_in_real return prob_in_real.instantiate({ x: self.random_variable, X: self.event })
class Target(Operation): ''' Represents the target of a control. Updated 1/26/2020 by wdc. ''' # the literal operator of the Target operation class _operator_ = Literal('TARGET', latexFormat=r'\targ', context=__file__) def __init__(self, target_gate): ''' Create a Target operation with the given target_gate as the type of the gate for the target (e.g., X for CNOT and Z for Controlled-Z). ''' Operation.__init__(self, Target._operator_, target_gate) self.target_gate = target_gate print("target_gate = {}".format( self.target_gate)) # for testing; delete later def formatted(self, formatType, fence=False): print("Entering Target.formatted().") # for testing; delete later formattedGateOperation = self.target_gate.formatted(formatType, fence=False) if formatType == 'latex': return r'\gate{' + formattedGateOperation + r'}' else: return Operation._formatted(self, formatType, fence)
class InnerProd(Operation): _operator_ = Literal( string_format=r'InnerProd', latex_format=r'\textrm{InnerProd}', theory=__file__) def __init__(self, a, b, *, styles=None): Operation.__init__(self, InnerProd._operator_, (a, b), styles=styles) def string(self, **kwargs): _a, _b = self.operands return '<' + _a.string() + ', ' + _b.string() + '>' def latex(self, **kwargs): _a, _b = self.operands return (r'\left \langle ' + _a.latex() + ', ' + _b.latex() + r'\right \rangle') @equality_prover('shallow_simplified', 'shallow_simplify') def shallow_simplification(self, *, must_evaluate=False, **defaults_config): ''' Simplify via inner product linearity: <a x, y> = a <x, y> <x, y> = <x, a y> <x + y, z> = <x, z> + <y, z> <x, y + z> = <x, y> + <x, z> ''' from proveit.linear_algebra import VecSpaces, ScalarMult, VecAdd from proveit.linear_algebra.inner_products import ( inner_prod_scalar_mult_left, inner_prod_scalar_mult_right, inner_prod_vec_add_left, inner_prod_vec_add_right) _u, _v = self.operands try: vec_space = VecSpaces.common_known_vec_space((_u, _v)) except UnsatisfiedPrerequisites: # No known common vectors space for the operands, so # we have no specific shallow_simplication we can do here. return Operation.shallow_simplification( self, must_evaluate=must_evaluate) field = VecSpaces.known_field(vec_space) simp = None if isinstance(_u, ScalarMult): simp = inner_prod_scalar_mult_left.instantiate( {K:field, H:vec_space, a:_u.scalar, x:_u.scaled, y:_v}) if isinstance(_v, ScalarMult): simp = inner_prod_scalar_mult_right.instantiate( {K:field, H:vec_space, a:_v.scalar, x:_u, y:_v.scaled}) if isinstance(_u, VecAdd): simp = inner_prod_vec_add_left.instantiate( {K:field, H:vec_space, x:_u.terms[0], y:_u.terms[1], z:_v}) if isinstance(_v, VecAdd): simp = inner_prod_vec_add_right.instantiate( {K:field, H:vec_space, x:_u, y:_v.terms[0], z:_v.terms[1]}) if simp is None: return Operation.shallow_simplification( self, must_evaluate=must_evaluate) if must_evaluate and not is_irreducible_value(simp.rhs): return simp.inner_expr().rhs.evaluate() return simp
class Card(Function): # operator of the Card operation _operator_ = Literal(stringFormat='card', context=__file__) def __init__(self, domain): Function.__init__(self, Card._operator_, domain) self.domain = self.operands[0] def string(self, fence=False): return '|' + self.domain.string(fence=False) + '|' def latex(self, fence=False): return '|' + self.domain.latex(fence=False) + '|' def distinctSubsetExistence(self, elems=None, assumptions=USE_DEFAULTS): ''' Assuming the cardinality of the domain can be proven to be >= 2, proves and returns that there exists distinct elements in that domain. ''' from proveit.number import num from ._theorems_ import distinctSubsetExistence, distinctPairExistence if len(elems)==2: aVar, bVar = elems return distinctPairExistence.specialize({S:self.domain}, relabelMap={a:aVar, b:bVar}, assumptions=assumptions) else: return distinctSubsetExistence.specialize({S:self.domain, N:num(len(elems))}, relabelMap={xMulti:elems}, assumptions=assumptions)
class ModAbs(Operation): # operator of the ModAbs operation. _operator_ = Literal(stringFormat='ModAbs', context=__file__) def __init__(self, value, divisor): Operation.__init__(self, ModAbs._operator_, (value, divisor)) self.value = value self.divisor = divisor def string(self, **kwargs): return '|' + self.value.string( fence=False) + '|_{mod ' + self.divisor.string(fence=False) + '}' def latex(self, **kwargs): # return r'\left|'+self.value.string(fence=False)+r'\right|_{{\rm mod}~' + self.divisor.string(fence=False) + r'\right}' # return ( r'\left|'+self.value.string(fence=False) # + r'\right|_{\textup{mod}\thinspace ' # + self.divisor.string(fence=False) + r'}') return (r'\left|' + self.value.latex(fence=False) + r'\right|_{\textup{mod}\thinspace ' + self.divisor.latex(fence=False) + r'}') def _closureTheorem(self, numberSet): from . import theorems if numberSet == Reals: return theorems.modAbsRealClosure
class Divides(Operation): # context = Context('.') # When I try to include latexFormat, I get an error # 'Implicit operator cannot be changed' _operator_ = Literal(stringFormat='|', latexFormat=r'\rvert', context=__file__) # _operator_ = Literal('|', context=__file__) def __init__(self, a, b): Operation.__init__(self, Divides._operator_, [a, b]) def deduceInBool(self, assumptions=USE_DEFAULTS): ''' Based on similar deduceInBool methods found in various classes in logic.booleans. Attempt to deduce, then return, that this 'Divides' expression is in the set of BOOLEANS. ''' from ._axioms_ import dividesInBool from proveit._common_ import m, n return dividesInBool.specialize( { m: self.operands[0], n: self.operands[1] }, assumptions=assumptions)
class SU(Function): ''' Special unitary groups are Lie groups of square matrices. ''' # the literal operator of the SU operation _operator_ = Literal(string_format='SU', latex_format=r'\textrm{SU}', theory=__file__) def __init__(self, n, *, styles=None): ''' Create some SU(n), the special unitary of degree n. ''' Function.__init__(self, SU._operator_, n, styles=styles) # self.operand = n self.degree = n def including_vec_space(self, field=None): ''' The vector space that includes special unitaries is the matrix space of complex numbers of the appropriate size. ''' from . import special_unitaries_are_matrices if field is not None and field != Complex: raise NotImplementedError( "SU.including_vec_space only implemented for a " "complex field, not %s." % field) subset_of_mat_space = special_unitaries_are_matrices.instantiate( {n: self.degree}) return subset_of_mat_space.superset