Ejemplo n.º 1
0
 def determine_node_settings(self, graphs):
     graph_node_setting_pairs = []
     for graph in graphs:
         final_state_edges = get_final_state_edges(graph)
         initial_state_edges = get_initial_state_edges(graph)
         node_settings = {}
         for node_id in graph.nodes:
             node_int_types = []
             out_edge_ids = get_edges_outgoing_to_node(graph, node_id)
             in_edge_ids = get_edges_outgoing_to_node(graph, node_id)
             in_edge_props = [
                 graph.edge_props[edge_id] for edge_id in
                 [x for x in in_edge_ids if x in initial_state_edges]
             ]
             out_edge_props = [
                 graph.edge_props[edge_id] for edge_id in
                 [x for x in out_edge_ids if x in final_state_edges]
             ]
             node_props = {}
             if node_id in graph.node_props:
                 node_props = graph.node_props[node_id]
             for int_det in self.interaction_determinators:
                 node_int_types.append(
                     int_det.check(in_edge_props, out_edge_props,
                                   node_props))
             node_int_types = filter_interaction_types(
                 node_int_types, self.allowed_interaction_types)
             logging.debug("using " + str(node_int_types) +
                           " interaction order for node: " + str(node_id))
             node_settings[node_id] = [
                 deepcopy(self.interaction_type_settings[x])
                 for x in node_int_types
             ]
         graph_node_setting_pairs.append((graph, node_settings))
     return graph_node_setting_pairs
Ejemplo n.º 2
0
def determine_attached_final_state(graph, edge_id):
    '''
    Determines all final state particles of a graph, which are attached
    downward (forward in time) for a given edge (resembling the root)

    Args:
        graph (:class:`.StateTransitionGraph`)
        edge_id (int): id of the edge, which is taken as the root
    Returns:
        list of final state edge ids ([int])
    '''
    final_state_edge_ids = []
    all_final_state_edges = get_final_state_edges(graph)
    current_edges = [edge_id]
    while current_edges:
        temp_current_edges = current_edges
        current_edges = []
        for curr_edge in temp_current_edges:
            if curr_edge in all_final_state_edges:
                final_state_edge_ids.append(curr_edge)
            else:
                node_id = graph.edges[curr_edge].ending_node_id
                current_edges.extend(get_edges_outgoing_to_node(
                    graph, node_id))
    return final_state_edge_ids
Ejemplo n.º 3
0
    def initialize_contraints(self):
        """
        Initializes all of the constraints for this graph. For each interaction
        node a set of independent constraints/conservation laws are created.
        For each conservation law a new CSP wrapper is created.
        This wrapper needs all of the qn numbers/variables which
        enter or exit the node and play a role for this conservation law.
        Hence variables are also created within this method.
        """
        for node_id, interaction_settings in self.node_settings.items():
            new_cons_laws = interaction_settings.conservation_laws
            for cons_law in new_cons_laws:
                variable_mapping = {}
                # from cons law and graph determine needed var lists
                qn_names = cons_law.get_required_qn_names()

                # create needed variables for edges state qns
                part_qn_dict = self.prepare_qns(
                    qn_names, interaction_settings.qn_domains,
                    (StateQuantumNumberNames, ParticlePropertyNames))
                in_edges = get_edges_ingoing_to_node(self.graph, node_id)

                in_edge_vars = self.create_edge_variables(
                    in_edges, part_qn_dict)
                variable_mapping["ingoing"] = in_edge_vars[0]
                variable_mapping["ingoing-fixed"] = in_edge_vars[1]
                var_list = [key for key in variable_mapping["ingoing"]]

                out_edges = get_edges_outgoing_to_node(self.graph, node_id)
                out_edge_vars = self.create_edge_variables(
                    out_edges, part_qn_dict)
                variable_mapping["outgoing"] = out_edge_vars[0]
                variable_mapping["outgoing-fixed"] = out_edge_vars[1]
                var_list.extend([key for key in variable_mapping["outgoing"]])

                # now create variables for node/interaction qns
                int_qn_dict = self.prepare_qns(qn_names,
                                               interaction_settings.qn_domains,
                                               InteractionQuantumNumberNames)
                int_node_vars = self.create_node_variables(
                    node_id, int_qn_dict)
                variable_mapping["interaction"] = int_node_vars[0]
                variable_mapping["interaction-fixed"] = int_node_vars[1]
                var_list.extend(
                    [key for key in variable_mapping["interaction"]])

                constraint = ConservationLawConstraintWrapper(
                    cons_law, variable_mapping,
                    self.particle_variable_delimiter)
                constraint.register_graph_node(node_id)
                self.constraints.append(constraint)
                if var_list:
                    self.problem.addConstraint(constraint, var_list)
                else:
                    self.constraints[-1].conditions_never_met = True
Ejemplo n.º 4
0
    def generate_sequential_decay(self, graph, parameter_props):
        class_label = get_xml_label(XMLLabelConstants.Class)
        name_label = get_xml_label(XMLLabelConstants.Name)
        spin_label = StateQuantumNumberNames.Spin
        decay_info_label = get_xml_label(XMLLabelConstants.DecayInfo)
        type_label = get_xml_label(XMLLabelConstants.Type)
        partial_decays = []
        for node_id in graph.nodes:
            # in case a scalar without dynamics decays into daughters with no
            # net helicity, the partial amplitude can be dropped
            # (it is just a constant)
            in_edges = get_edges_ingoing_to_node(graph, node_id)
            out_edges = get_edges_outgoing_to_node(graph, node_id)
            # check mother particle is spin 0
            in_spin = get_particle_property(graph.edge_props[in_edges[0]],
                                            spin_label)
            out_spins = [
                get_particle_property(graph.edge_props[x], spin_label)
                for x in out_edges
            ]
            if (in_spin is not None and None not in out_spins
                    and in_spin.magnitude() == 0):
                if abs(out_spins[0].projection() -
                       out_spins[1].projection()) == 0.0:
                    # check if dynamics is non resonsant (constant)
                    if ('NonResonant' == graph.edge_props[in_edges[0]]
                        [decay_info_label][type_label]):
                        continue

            partial_decays.append(
                self.generate_partial_decay(graph, node_id, parameter_props))

        amp_name = parameter_props['AmplitudeName']
        seq_decay_dict = {
            class_label: "CoefficientAmplitude",
            name_label: amp_name,
            'Amplitude': {
                class_label: "SequentialAmplitude",
                name_label: amp_name,
                'Amplitude': partial_decays
            }
        }
        seq_decay_dict.update(
            self.generate_magnitude_and_phase(parameter_props))
        prefactor = get_prefactor(graph)
        if prefactor != 1.0 and prefactor is not None:
            prefactor_label = get_xml_label(XMLLabelConstants.PreFactor)
            seq_decay_dict[prefactor_label] = {
                '@Magnitude': prefactor,
                '@Phase': 0.0
            }
        return seq_decay_dict
Ejemplo n.º 5
0
        def wrapper(self, graph, node_id, parameter_props):
            spinqn = StateQuantumNumberNames.Spin
            partial_decay_dict = decay_generate_function(
                self, graph, node_id, parameter_props)
            node_props = graph.node_props[node_id]
            L = get_interaction_property(node_props,
                                         InteractionQuantumNumberNames.L)
            S = get_interaction_property(node_props,
                                         InteractionQuantumNumberNames.S)

            in_edge_ids = get_edges_ingoing_to_node(graph, node_id)

            parent_spin = get_particle_property(
                graph.edge_props[in_edge_ids[0]], spinqn)

            daughter_spins = []

            for out_edge_id in get_edges_outgoing_to_node(graph, node_id):
                daughter_spins.append(
                    get_particle_property(graph.edge_props[out_edge_id],
                                          spinqn))

            decay_particle_lambda = (daughter_spins[0].projection() -
                                     daughter_spins[1].projection())
            cg_ls = OrderedDict()
            cg_ls['@Type'] = "LS"
            cg_ls['@j1'] = L.magnitude()
            if L.projection() != 0.0:
                raise ValueError("Projection of L is non-zero!: " +
                                 str(L.projection()))
            cg_ls['@m1'] = L.projection()
            cg_ls['@j2'] = S.magnitude()
            cg_ls['@m2'] = decay_particle_lambda
            cg_ls['@J'] = parent_spin.magnitude()
            cg_ls['@M'] = decay_particle_lambda
            cg_ss = OrderedDict()
            cg_ss['@Type'] = "s2s3"
            cg_ss['@j1'] = daughter_spins[0].magnitude()
            cg_ss['@m1'] = daughter_spins[0].projection()
            cg_ss['@j2'] = daughter_spins[1].magnitude()
            cg_ss['@m2'] = -daughter_spins[1].projection()
            cg_ss['@J'] = S.magnitude()
            cg_ss['@M'] = decay_particle_lambda
            cg_dict = {
                'CanonicalSum': {
                    '@L': L.magnitude(),
                    '@S': S.magnitude(),
                    'ClebschGordan': [cg_ls, cg_ss]
                }
            }
            partial_decay_dict.update(cg_dict)
            return partial_decay_dict
Ejemplo n.º 6
0
    def generate_partial_decay(self, graph, node_id, parameter_props):
        class_label = get_xml_label(XMLLabelConstants.Class)
        name_label = get_xml_label(XMLLabelConstants.Name)
        decay_products = []
        for out_edge_id in get_edges_outgoing_to_node(graph, node_id):
            decay_products.append({
                name_label:
                graph.edge_props[out_edge_id][name_label],
                '@FinalState':
                determine_attached_final_state_string(graph, out_edge_id),
                '@Helicity':
                get_helicity_from_edge_props(graph.edge_props[out_edge_id])
            })

        in_edge_ids = get_edges_ingoing_to_node(graph, node_id)
        if len(in_edge_ids) != 1:
            raise ValueError("This node does not represent a two body decay!")
        dec_part = graph.edge_props[in_edge_ids[0]]

        recoil_edge_id = get_recoil_edge(graph, in_edge_ids[0])
        parent_recoil_edge_id = get_parent_recoil_edge(graph, in_edge_ids[0])
        recoil_system_dict = {}
        if recoil_edge_id is not None:
            tempdict = {
                '@RecoilFinalState':
                determine_attached_final_state_string(graph, recoil_edge_id)
            }
            if parent_recoil_edge_id is not None:
                tempdict.update({
                    '@ParentRecoilFinalState':
                    determine_attached_final_state_string(
                        graph, parent_recoil_edge_id)
                })
            recoil_system_dict['RecoilSystem'] = tempdict

        amp_name = parameter_props[node_id]['Name']
        partial_decay_dict = {
            name_label: amp_name,
            class_label: "HelicityDecay",
            'DecayParticle': {
                name_label: dec_part[name_label],
                '@Helicity': get_helicity_from_edge_props(dec_part)
            },
            'DecayProducts': {
                'Particle': decay_products
            }
        }
        # partial_decay_dict.update(self.generate_magnitude_and_phase(amp_name))
        partial_decay_dict.update(recoil_system_dict)

        return partial_decay_dict
Ejemplo n.º 7
0
    def create_variable_containers(self, node_id, cons_law):
        in_edges = get_edges_ingoing_to_node(self.graph, node_id)
        out_edges = get_edges_outgoing_to_node(self.graph, node_id)

        qn_names = cons_law.get_required_qn_names()
        qn_list = self.prepare_qns(
            qn_names, (StateQuantumNumberNames, ParticlePropertyNames))
        in_edges_vars = self.create_edge_variables(in_edges, qn_list)
        out_edges_vars = self.create_edge_variables(out_edges, qn_list)

        node_vars = self.create_node_variables(
            node_id, self.prepare_qns(qn_names, InteractionQuantumNumberNames))

        return (in_edges_vars, out_edges_vars, node_vars)
Ejemplo n.º 8
0
    def generate(self, graph, node_id):
        '''
        Generates partial amplitude name and fit parameter suffix.
        The fit parameters with the same name are connected and treated as one.
        For these fit parameter suffixes, a name sorted scheme is used.
        On the other hand amplitude names are purely cosmetic!
        '''
        # get ending node of the edge
        # then make name for
        in_edges = get_edges_ingoing_to_node(graph, node_id)
        out_edges = get_edges_outgoing_to_node(graph, node_id)
        name_label = get_xml_label(XMLLabelConstants.Name)
        in_names_hel_dict = {}
        out_names_hel_dict = {}
        for i in in_edges:
            temphel = float(get_helicity_from_edge_props(graph.edge_props[i]))
            # remove .0
            if temphel % 1 == 0:
                temphel = int(temphel)
            in_names_hel_dict[graph.edge_props[i][name_label]] = temphel
        for i in out_edges:
            temphel = float(get_helicity_from_edge_props(graph.edge_props[i]))
            # remove .0
            if temphel % 1 == 0:
                temphel = int(temphel)
            out_names_hel_dict[graph.edge_props[i][name_label]] = temphel

        par_name_suffix = '_to_' + \
            generate_particles_string(out_names_hel_dict)
        name = generate_particles_string(in_names_hel_dict) + par_name_suffix
        par_name_suffix = generate_particles_string(in_names_hel_dict,
                                                    False) + par_name_suffix
        if par_name_suffix not in self.generated_parameter_names:
            append_name = True
            if self.use_parity_conservation:
                # first check if parity partner exists
                pp_par_name_suffix = generate_particles_string(
                    in_names_hel_dict, False) + '_to_' + \
                    generate_particles_string(out_names_hel_dict,
                                              make_parity_partner=True)
                if pp_par_name_suffix in self.generated_parameter_names:
                    par_name_suffix = pp_par_name_suffix
                    append_name = False
            if append_name:
                self.generated_parameter_names.append(par_name_suffix)
        return (name, par_name_suffix)
Ejemplo n.º 9
0
def get_recoil_edge(graph, edge_id):
    '''
    Determines the id of the recoil edge for the specified edge of a graph.

    Args:
        graph (:class:`.StateTransitionGraph`)
        edge_id (int): id of the edge, for which the recoil partner is
            determined
    Returns:
        recoil edge id (int)
    '''
    node_id = graph.edges[edge_id].originating_node_id
    if node_id is None:
        return None
    outgoing_edges = get_edges_outgoing_to_node(graph, node_id)
    outgoing_edges.remove(edge_id)
    if len(outgoing_edges) != 1:
        raise ValueError("The node with id " + str(node_id) +
                         " has more than 2 outgoing edges \n" + str(graph))
    return outgoing_edges[0]
Ejemplo n.º 10
0
    def generate(self, graph, node_id):
        '''
        Method which adds two clebsch gordan coefficients based on
        the translation of helicity amplitudes to canonical ones.
        '''
        # get ending node of the edge
        # then make name for
        in_edges = get_edges_ingoing_to_node(graph, node_id)
        out_edges = get_edges_outgoing_to_node(graph, node_id)
        name_label = get_xml_label(XMLLabelConstants.Name)
        in_names_hel_dict = {}
        out_names_hel_dict = {}
        for i in in_edges:
            temphel = float(get_helicity_from_edge_props(graph.edge_props[i]))
            # remove .0
            if temphel % 1 == 0:
                temphel = int(temphel)
            in_names_hel_dict[graph.edge_props[i][name_label]] = temphel
        for i in out_edges:
            temphel = float(get_helicity_from_edge_props(graph.edge_props[i]))
            # remove .0
            if temphel % 1 == 0:
                temphel = int(temphel)
            out_names_hel_dict[graph.edge_props[i][name_label]] = temphel

        name = generate_particles_string(in_names_hel_dict) + \
            '_to_' + generate_particles_string(out_names_hel_dict)
        par_name_suffix = generate_particles_string(
            in_names_hel_dict, False) + '_to_' +\
            generate_particles_string(out_names_hel_dict, False)

        node_props = graph.node_props[node_id]
        L = get_interaction_property(node_props,
                                     InteractionQuantumNumberNames.L)
        S = get_interaction_property(node_props,
                                     InteractionQuantumNumberNames.S)
        addition_string = '_L_' + str(L.magnitude()) + \
            '_S_' + str(S.magnitude())
        return (name + addition_string, par_name_suffix + addition_string)