Exemple #1
0
    def perception(self, tx, perc):
        """
        Patient perception function. Filters based on agent having sufficient energy for edge and end node.

        :param tx: neo4j write transaction
        :param perc: perception recieved from the node

        :return: None
        """
        super(Patient, self).perception(tx, perc)
        if type(self.view) == list:
            edges = self.view
        else:
            edges = [self.view]
        # filter out options requiring too much energy
        valid_edges = []
        self.mobility = intf.getnodevalue(tx, self.id, "mob", "Patient")
        self.energy = intf.getnodevalue(tx, self.id, "energy", "Patient")
        self.current_energy = self.energy
        if len(self.view) > 1:
            for edge in edges:
                if not edge.end_node["name"] in ["Care", "GP", "Hos"]:
                    cost = 0
                    if edge.end_node["energy"]:
                        cost = cost + edge.end_node["energy"]
                    if self.energy > -cost:
                        valid_edges = valid_edges + [edge]
        else:
            valid_edges = self.view
        self.view = valid_edges
Exemple #2
0
def main(rl):
    """
    Runs the monitor snapshot until clock reaches or exceeds run length. Then closes monitor.

    :param rl: run length

    :return: None
    """
    monitor = specification.Monitor()
    clock = 0
    while clock < rl:
        driver = GraphDatabase.driver(specification.database_uri,
                                      auth=specification.Monitor_auth,
                                      max_connection_lifetime=20000)
        with driver.session() as session:
            # modifying and redrawing plot over time and saving plot rather than an animation
            session.write_transaction(monitor.snapshot, clock)
            tx = session.begin_transaction()
            current_time = intf.gettime(tx)
            while clock == current_time:
                current_time = intf.gettime(tx)
            clock = current_time
        driver.close()
    print("Monitor Capture complete")
    driver = GraphDatabase.driver(specification.database_uri,
                                  auth=specification.Monitor_auth,
                                  max_connection_lifetime=2000)
    with driver.session() as session:
        session.write_transaction(monitor.close)
    driver.close()
    print("Monitor closed")
Exemple #3
0
    def generator(self, tx, params):
        """
        Generates Fall Agents and inserts them into the network at the home node.

        :param self: Agent
        :param tx: neo4j database transaction with write permission
        :param params: [mobility, confidence, energy] these are the means for the normal distributions sampled to set parameters

        :return: None
        """
        super(FallAgent, self).generator(tx, params)
        # generate a random set of parameters based on a distribution with mean set by params
        [mobility, confidence, energy] = params
        self.mobility = npr.normal(
            mobility,
            0.05)  # draw from normal distribution centred on given value
        self.energy = npr.normal(energy, 0.05)
        self.confidence = npr.normal(confidence, 0.05)
        self.wellbeing = "'At risk'"
        self.referral = "false"
        # Add agent with params to ind in graph with resources starting at 0
        time = tx.run("MATCH (a:Clock) RETURN a.time").values()[0][0]
        self.log = "(CREATED," + str(time) + ")"
        intf.addagent(tx, {"name": "Home"}, "Agent", {
            "mob": self.mobility,
            "conf": self.confidence,
            "mob_res": 0,
            "conf_res": 0,
            "energy": self.energy,
            "wellbeing": self.wellbeing,
            "log": "'" + self.log + "'",
            "referral": self.referral
        }, "name")
def main(rl, ps):
    """
    Checks population levels meet requirements and adds additional agents if needed until clock reaches or exceeds run
    length

    :param rl: run length
    :param ps: population size

    :return: None
    """
    clock = 0
    agent = specification.Agents(None)
    while clock < rl:
        dri = GraphDatabase.driver(specification.database_uri,
                                   auth=specification.Population_auth,
                                   max_connection_lifetime=2000)
        with dri.session() as ses:
            populationdeficite = specification.Population.check(ses, ps)
            if populationdeficite:
                for i in range(populationdeficite):
                    ses.write_transaction(agent.generator,
                                          specification.Population.params)
            tx = ses.begin_transaction()
            time = intf.gettime(tx)
            while clock == time:
                time = intf.gettime(tx)
            clock = time
        dri.close()
    print("Population closed")
Exemple #5
0
    def logging(self, tx, entry):
        """
        Utility function for adding information to the agents log of its activities

        :param tx: neo4j database write transaction
        :param entry: String to be added to the log

        :return: None
        """
        self.log = intf.getnodevalue(tx, self.id, "log", "Agent")
        self.log = self.log + ", (" + entry + ")"
        intf.updateagent(tx, self.id, "log", str(self.log))
Exemple #6
0
    def look(self, tx):
        """
        If not at home, find co-located agents

        :param tx: neo4j database write transaction

        :return: None
        """
        super(Patient, self).look(tx)
        self.id = self.id[0]
        # If not at home, find co-located agents
        if intf.locateagent(tx, self.id)["name"] != "Home":
            self.colocated = intf.colocated(tx, self.id)
        self.social = intf.getnodevalue(tx, self.id, "social", "Agent")
Exemple #7
0
    def close(self, txc):
        """
        Saves figure, figure data, logs of agents in system at end of run to the output directory given in Specification
        with name tag given in database.

        :param txc: neo4j database write transaction

        :return: None
        """
        super(Monitor, self).close(txc)
        runname = intf.getrunname(txc)
        print(self.clock)
        logs = txc.run("MATCH (a:Agent) RETURN a.log").values()
        pickle_lout = open(
            specification.savedirectory + "logs_" + runname + ".p", "wb")
        pickle.dump(logs, pickle_lout)
        pickle_lout.close()
        pickle_out = open(
            specification.savedirectory + "records_" + runname + ".p", "wb")
        pickle.dump(self.records, pickle_out)
        pickle_out.close()
        pickle_gout = open(
            specification.savedirectory + "graphdata_" + runname + ".p", "wb")
        pickle.dump([
            self.y11, self.y12, self.y13, self.y2, self.y3, self.y41, self.y42,
            self.y43, self.t
        ], pickle_gout)
        pickle_gout.close()
        # dump graph data as strings back into the database
        # save out graph
        plt.savefig("../FallData/figure_" + runname + "")
        if self.show:
            plt.show()
Exemple #8
0
    def choose(self, tx, perc):
        """
        Patients conscious choice from possible edges. This is based on the patients mood exceeds the current threshold
        for that edge. If the agent has the mood for multiple choices the final choice is made as a weighted sampling of
        all possible choices with weights based on the Patients inclination applied to the types of edges.

        :param tx: neo4j database write transaction
        :param perc: perception from node perception function.

        :return: single edge as final choice
        """
        super(Patient, self).choose(tx, perc)
        # filter out options where the agent does not reach the mood threshold
        options = []
        self.mood = intf.getnodevalue(tx, self.id, "mood", "Patient")
        self.inclination = intf.getnodevalue(tx, self.id, "inclination",
                                             "Patient")
        self.log = intf.getnodevalue(tx, self.id, "log", "Patient")
        self.wellbeing = intf.getnodevalue(tx, self.id, "wellbeing", "Patient")
        self.referral = intf.getnodevalue(tx, self.id, "referral", "Patient")
        if len(self.view) < 2:
            if type(self.view) == list and self.view:
                choice = self.view[0]
            else:
                choice = self.view
        else:
            for edge in self.view:
                if edge["mood"] <= self.mood:
                    options = options + [edge]
            # choose based on random sample bias by patients inclination
            if not options:
                return None
            types = [edge["type"] for edge in options]
            edge_types = ["social", "fall", "medical", "inactive"]
            types = [edge_types.index(lable) for lable in types]
            weights = [
                self.positive(self.inclination[label]) for label in types
            ]
            if sum(weights):
                weights = [w / sum(weights) for w in weights]
                sample = npr.choice(range(len(options)), 1, p=weights)
            else:
                sample = npr.choice(range(len(options)), 1)
            choice = options[sample[0]]
        return choice
Exemple #9
0
    def talk(self, tx):
        """
        Determine if agent forms a new social link with random co-located agent based on their social values and
        shortest social path

        :param tx: neo4j write transaction

        :return: None
        """
        super(Patient, self).talk(tx)
        if self.colocated:
            newcontacts = [
                nc for nc in self.colocated if nc not in self.contacts
            ]
            if newcontacts:
                if len(newcontacts) > 1:
                    newfriend = npr.sample(newcontacts)
                else:
                    newfriend = newcontacts
                # Based on relative social values and length of shortest path set probability for forming link with a
                #  randomly sampled co-located unknown agent. social from 2-8 per agent, combined from 4-16. So combined -4
                #  over 24 gives value between 0 and 0.5 plus the if minimum path greater than 6 nothing, else from m=2-6
                #  then 1/(2m-2) gives 0.1-0.5 (m=1 or 0 means itself or already connected).
                prob1 = (newfriend.end_node["social"] + self.social - 4) / 24
                sp = intf.shortestpath(tx, self.id, newfriend.end_node["id"],
                                       'Agent', 'Social')
                if sp < 2:
                    prob2 = 0
                elif sp > 6:
                    prob2 = 0
                else:
                    prob2 = 1 / (2 * sp - 2)
                if npr.random(1) <= (prob1 + prob2):
                    # form friend link
                    intf.createedge(
                        self.id, newfriend.end_node["id"], 'Agent', 'Agent',
                        'SOCIAL:FRIEND', 'created: ' + intf.gettime() +
                        ', usage: ' + intf.gettime() + ', carer: False')
                    self.contacts = newfriend
                else:
                    self.contacts = None
            else:
                self.contacts = None
        else:
            self.contacts = None
Exemple #10
0
    def update(self, tx):
        """
        Check agent contacts compare list with co-located agents and update co-located contacts with new last usage

        :param tx: neo4j database write transaction

        :return: None
        """
        super(Patient, self).update(tx)
        # Update existing com links with latest co-location
        self.contacts = intf.agentcontacts(tx, self.id, "Patient")
        if self.contacts and self.colocated:
            update = [
                contact for contact in self.contacts
                if contact in self.colocated
            ]
            for contact in update:
                intf.updatecontactedge(tx, contact.end_node["id"], self.id,
                                       "last_usage", intf.gettime())
def timesincedischarge(txl):
    """
    Utility function reports the time between any hospital discharge and attending an intervention. Only recorded if
    both events occur.

    :param txl: neo4j database write transaction

    :return: list of times in integer timesteps
    """
    times = []
    agents = intf.getnodeagents(txl, "Intervention", "name")
    for agent in agents:
        log = parselog(agent["log"])
        log.reverse()
        lasthosdis = [entry for entry in log if entry[0] == "Hos discharge"]
        if lasthosdis:
            lasthosdis = lasthosdis[0]
            times = times + [intf.gettime(txl) - lasthosdis[1]]
    return times
Exemple #12
0
    def listen(self, tx):
        """
        If the agent has a new social link check if the new friend has a link to a carer if they do for a random carer
        they form a link with a .5 chance.

        :param tx: neo4j write transaction

        :return: None
        """
        super(Patient, self).listen(tx)
        if self.contacts:
            carers = intf.agentcontacts(tx, self.contacts.end_node["id"],
                                        "Agent", "Carer")
            carers = [carer for carer in carers if carer["carer"]]
            carer = npr.sample(carers)
            if npr.random(1) < 0.5:
                intf.createedge(
                    self.id, carer.end_node["id"], 'Patient', 'Carer',
                    'SOCIAL:FRIEND', 'created: ' + intf.gettime() +
                    ', usage: ' + intf.gettime() + ', carer: True')
Exemple #13
0
    def agentprediction(self, tx, agent):
        """
        Predict how long the agent will stay at the node and its destination once it leaves. This must be implemented by
        the subclass to predict agent behaviour if node has a queue.

        :param tx: neo4j write transaction
        :param agent: agent id

        :return: view of local environment for agent
        """
        view = intf.perception(tx, agent["id"])
        return view
Exemple #14
0
    def generator(self, tx, params):
        """
        Generates Fall Agents and inserts them into the network at the home node.

        :param self: Agent
        :param tx: neo4j database transaction with write permission
        :param params: [mobility, mood, energy, inclination] these are the means for the normal distributions sampled to set parameters

        :return: None
        """
        super(Patient, self).generator(tx, params)
        # generate a random set of parameters based on a distribution with mean set by params
        [mobility, mood, energy, inclination, min_social, max_social] = params
        self.mobility = npr.normal(
            mobility,
            0.05)  # draw from normal distribution centred on given value
        self.energy = npr.normal(energy, 0.05)
        self.mood = npr.normal(mood, 0.05)
        self.inclination = [npr.normal(x) for x in inclination]
        self.inclination = [
            inc / sum(self.inclination) for inc in self.inclination
        ]
        self.wellbeing = "'At risk'"
        self.referral = "false"
        self.social = npr.choice(range(min_social, max_social + 1), 1)[0]
        print(self.social)
        # Add agent with params to ind in graph with resources starting at 0
        time = tx.run("MATCH (a:Clock) RETURN a.time").values()[0][0]
        self.log = "(CREATED," + str(time) + ")"
        intf.addagent(tx, {"name": "Home"}, "Agent:Patient", {
            "mob": self.mobility,
            "mood": self.mood,
            "energy": self.energy,
            "inclination": self.inclination,
            "wellbeing": self.wellbeing,
            "log": "'" + self.log + "'",
            "referral": self.referral,
            "social": self.social
        }, "name")
def main(rl):
    """
    Implements a FlowReaction repeatedly until the clock in the database reaches the run length.

    :param rl: run length

    :return: None
    """
    flowreaction = specification.Balancer.FlowReaction()
    clock = 0
    while clock < rl:
        dri = GraphDatabase.driver(specification.database_uri,
                                   auth=specification.Balancer_auth,
                                   max_connection_lifetime=2000)
        with dri.session() as ses:
            ses.write_transaction(flowreaction.applyrules)
            tx = ses.begin_transaction()
            time = intf.gettime(tx)
            while clock == time:
                time = intf.gettime(tx)
            clock = time
        dri.close()
    print("Balancer closed")
Exemple #16
0
    def agentsready(self, tx):
        """
        Identifies the set of current agents for processing, either the correct set in the queue or all the agents at
        the node. It checks for unqueued agents in nodes with queue and runs the nodes prediction function to add them
        to the queue. It then gathers the agents local environment perception and passes that to the agent when calling
        the move function. We then delete the part of the queue that has been processed to save space. Subclass must
        implement this function for any aspects unique to model.

        :param tx: neo4j write transaction

        :return: None
        """
        agents = intf.getnodeagents(tx, self.name, "name")
        clock = intf.gettime(tx)
        if self.queue or self.queue == {}:
            queueagents = [
                key for time in self.queue.keys()
                for key in self.queue[time].keys()
            ]
            newagents = [ag for ag in agents if ag["id"] not in queueagents]
            # run prediction on each unqueued agent
            for ag in newagents:
                self.agentprediction(tx, ag)
        for ag in agents:
            if self.queue:
                if clock in self.queue.keys():
                    if ag["id"] in self.queue[clock].keys():
                        agper = self.agentperception(
                            tx, ag, self.queue[clock][ag["id"]][0],
                            self.queue[clock][ag["id"]])
                        specification.Agent(ag["id"]).move(tx, agper)
            else:
                agper = self.agentperception(tx, ag)
                specification.Agent(ag["id"]).move(tx, agper)
        if self.queue and clock in self.queue.keys():
            del self.queue[clock]
Exemple #17
0
    def agentperception(self, tx, agent, dest=None, waittime=None):
        """
        The local environment of the node filtered by availability to a particular agent. Subclass must implement this
        function to add node filtering for particular model

        :param tx: neo4j read or write transaction
        :param agent: agent id
        :param dest: passed by nodes with queues if agent destination has already been determined by prediction.
        :param waittime: time the agent has been waiting at the node

        :return: view of local environment for agent as list of relationships
        """
        if dest:
            view = dest
        else:
            view = intf.perception(tx, agent["id"])[1:]
        if type(view) == list:
            for edge in view:
                if "cap" in edge.end_node.keys():
                    if edge.end_node["cap"] <= edge.end_node["load"]:
                        view.remove(edge)
        return view
Exemple #18
0
    def choose(self, tx, perc):
        """
        Agents conscious choice from possible edges. This is based on the effort of the agent calculated from the
        combination of agent and edge values. If the agent has the effort for multiple choices the worth of the edge is
        used as a deciding factor.

        :param tx: neo4j database write transaction
        :param perc: perception from node perception function.

        :return: single edge as final choice
        """
        super(FallAgent, self).choose(tx, perc)
        # filter out options where the agent does not reach the effort threshold
        options = []
        self.confidence = intf.getnodevalue(tx, self.id, "conf", "Agent")
        self.mobility_resources = intf.getnodevalue(tx, self.id, "mob_res",
                                                    "Agent")
        self.confidence_resources = intf.getnodevalue(tx, self.id, "conf_res",
                                                      "Agent")
        self.log = intf.getnodevalue(tx, self.id, "log", "Agent")
        self.wellbeing = intf.getnodevalue(tx, self.id, "wellbeing", "Agent")
        self.referral = intf.getnodevalue(tx, self.id, "referral", "Agent")
        if len(self.view) < 2:
            if type(self.view) == list and self.view:
                choice = self.view[0]
            else:
                choice = self.view
        else:
            for edge in self.view:
                if edge["effort"] <= edge["mobility"] * (self.mobility + self.confidence * self.mobility_resources) + \
                        edge["confidence"] * (self.confidence + self.mobility * self.confidence_resources):
                    options = options + [edge]
            # choose based on current highest worth edge ignores edges with no worth score, these are not choosable
            # edges, they are primarily edges indicating a fall
            if not options:
                return None
            choice = options[0]
            for edge in options:
                if "worth" in edge and "worth" in choice:
                    if edge["worth"] > choice["worth"]:
                        choice = edge
                elif "worth" in edge:
                    choice = edge
        return choice
Exemple #19
0
    def learn(self, tx, choice):
        """
        Agent is changed by node and can change node and edge it arrived by. This can include changes to decision
         making parameters.

        :param tx: neo4j database write transaction
        :param choice: Chosen edge for move

        :return: None
        """
        super(Patient, self).learn(tx, choice)
        # modify mob, conf, res and energy based on new node
        if self.fall and self.fall != "Mild":
            if self.wellbeing != "Fallen":
                self.wellbeing = "Fallen"
                intf.updateagent(tx, self.id, "wellbeing", self.wellbeing)
                clock = tx.run("MATCH (a:Clock) "
                               "RETURN a.time").values()[0][0]
                self.log = self.log + ", (Fallen, " + str(clock) + ")"
        if "modm" in choice.end_node:
            self.mobility = self.positive(
                npr.normal(choice.end_node["modm"], 0.05) + self.mobility)
            intf.updateagent(tx, self.id, "mob", self.mobility)
            # check for updates to wellbeing and log any changes
            if self.mobility == 0:
                if self.wellbeing != "Fallen":
                    self.wellbeing = "Fallen"
                    intf.updateagent(tx, self.id, "wellbeing", self.wellbeing)
                    clock = tx.run("MATCH (a:Clock) "
                                   "RETURN a.time").values()[0][0]
                    self.log = self.log + ", (Fallen, " + str(clock) + ")"
            elif self.mobility > 1:
                if self.wellbeing != "Healthy":
                    self.wellbeing = "Healthy"
                    intf.updateagent(tx, self.id, "wellbeing", self.wellbeing)
                    clock = tx.run("MATCH (a:Clock) "
                                   "RETURN a.time").values()[0][0]
                    self.log = self.log + ", (Healthy, " + str(clock) + ")"
            elif self.mobility <= 1:
                if self.wellbeing == "Healthy":
                    self.wellbeing = "At risk"
                    intf.updateagent(tx, self.id, "wellbeing", self.wellbeing)
                    clock = tx.run("MATCH (a:Clock) "
                                   "RETURN a.time").values()[0][0]
                    self.log = self.log + ", (At risk, " + str(clock) + ")"
        if "modmood" in choice.end_node:
            self.mood = self.positive(
                npr.normal(choice.end_node["modmood"], 0.05) + self.mood)
            intf.updateagent(tx, self.id, "mood", self.mood)
        if "energy" in choice.end_node:
            self.current_energy = npr.normal(choice.end_node["energy"],
                                             0.05) + self.current_energy
            energy_change = self.current_energy - self.energy
            intf.updateagent(tx, self.id, "energy", self.current_energy)
            edge_types = ["social", "fall", "medical", "inactive"]
            for i in range(len(edge_types)):
                if choice["type"] == edge_types[i]:
                    if energy_change < 0:
                        self.inclination[i] = self.inclination[i] + 1
                    elif energy_change > 0:
                        self.inclination[i] = self.positive(
                            self.inclination[i] - 1)
        # change to inclination based on mobility, energy and mood
        if self.current_energy > 0.8:
            self.inclination[0] = self.inclination[0] + 1
        elif self.current_energy < 0.2:
            self.inclination[3] = self.inclination[3] + 1
        if self.mood > 0.8:
            self.inclination[0] = self.inclination[0] - 1
            self.inclination[3] = self.inclination[3] + 1
        elif self.mood < 0.2:
            self.inclination[0] = self.inclination[0] + 1
            self.inclination[3] = self.inclination[3] - 1
        if self.mobility < 0.4:
            self.inclination[2] = self.inclination[2] + 1
            self.inclination[3] = self.inclination[3] + 1
        elif self.mobility > 0.8:
            self.inclination[3] = self.inclination[3] - 1
        intf.updateagent(tx, self.id, "inclination", self.inclination)
        # log going into care
        if choice.end_node["name"] == "Care":
            clock = tx.run("MATCH (a:Clock) " "RETURN a.time").values()[0][0]
            self.log = self.log + ", (Care, " + str(clock) + ")"
        if "cap" in choice.end_node.keys():
            intf.updatenode(tx, choice.end_node["name"], "load",
                            choice.end_node["load"] + 1, "name")
        if self.view[0]["name"] == "Hos" and choice.end_node["name"] != "Hos":
            clock = tx.run("MATCH (a:Clock) " "RETURN a.time").values()[0][0]
            self.log = self.log + ", (Discharged, " + str(clock) + ")"
        intf.updateagent(tx, self.id, "log", str(self.log))
Exemple #20
0
    def payment(self, tx):
        """
        Modifies chosen edge and agent. These include mobility, confidence and energy modifications.

        :param tx: neo4j database write transaction

        :return: None
        """
        super(Patient, self).payment(tx)
        # Deduct energy used on edge
        if "energy" in self.choice.keys():
            if "energy" in self.choice.end_node.keys():
                if self.choice["energy"] + self.choice.end_node[
                        "energy"] > self.current_energy:
                    # Check for carers
                    carers = intf.agentcontacts(tx, self.id, "Agent", "Carer")
                    # Check for sufficient energy
                    for carer in carers:
                        print(carer)
                        if carer.end_node["energy"] >= self.choice["energy"]:
                            intf.updatenode(tx,
                                            carer.end_node["id"],
                                            "energy",
                                            carer.end_node["energy"] -
                                            self.choice["energy"],
                                            label='Carer')
                            self.current_energy = self.current_energy + self.choice[
                                "energy"]
                            intf.updateagent(tx, self.id, "energy",
                                             self.current_energy)
                            intf.updatecontactedge(tx, self.id,
                                                   carer.end_node["id"],
                                                   "usage", intf.gettime(tx),
                                                   "Agent", "Carer")
                            break
                    else:
                        return False
            self.current_energy = npr.normal(self.choice["energy"],
                                             0.05) + self.current_energy
            intf.updateagent(tx, self.id, "energy", self.current_energy)
        # mod variables based on edges
        if "modm" in self.choice:
            self.mobility = self.positive(
                npr.normal(self.choice["modm"], 0.05) + self.mobility)
            intf.updateagent(tx, self.id, "mob", self.mobility)
            if self.mobility == 0:
                if self.wellbeing != "Fallen":
                    self.wellbeing = "Fallen"
                    intf.updateagent(tx, self.id, "wellbeing", self.wellbeing)
                    clock = tx.run("MATCH (a:Clock) "
                                   "RETURN a.time").values()[0][0]
                    self.log = self.log + ", (Fallen, " + str(clock) + ")"
            elif self.mobility > 1:
                if self.wellbeing != "Healthy":
                    self.wellbeing = "Healthy"
                    intf.updateagent(tx, self.id, "wellbeing", self.wellbeing)
                    clock = tx.run("MATCH (a:Clock) "
                                   "RETURN a.time").values()[0][0]
                    self.log = self.log + ", (Healthy, " + str(clock) + ")"
            elif self.mobility <= 1:
                if self.wellbeing == "Healthy":
                    self.wellbeing = "At risk"
                    intf.updateagent(tx, self.id, "wellbeing", self.wellbeing)
                    clock = tx.run("MATCH (a:Clock) "
                                   "RETURN a.time").values()[0][0]
                    self.log = self.log + ", (At risk, " + str(clock) + ")"
        if "modmood" in self.choice:
            self.mood = self.positive(
                npr.normal(self.choice["modmood"], 0.05) + self.mood)
            intf.updateagent(tx, self.id, "mood", self.mood)
        return True
Exemple #21
0
    def react(self, tx):
        """
        If the agent now has more social bonds than they can manage we drop new non carer friends then those not used
        recently and finally reduce the carers from most recent.

        :param tx: neo4j write transaction

        :return: None
        """
        super(Patient, self).react(tx)
        self.contacts = intf.agentcontacts(tx, self.id, "Agent")
        carers = self.contacts + intf.agentcontacts(tx, self.id, "Agent",
                                                    "Carer")
        if len(self.contacts) > self.social:
            while len(carers) > self.social:
                carer_drop = None
                latest_time = 0
                for carer in carers:
                    if carer["created"] > latest_time:
                        carer_drop = carer
                        latest_time = carer["created"]
                intf.deletecontact(tx, self.id, carer_drop.end_node["id"],
                                   "Agent", "Carer")
            if len(carers) == self.social:
                for contact in contacts:
                    intf.deletecontact(tx, self.id, contact.end_node["id"],
                                       "Agent", "Agent")
            if len(carers) + len(contacts) > self.social:
                for contact in contacts:
                    if len(carers) + len(contacts) > self.social:
                        if intf.gettime() - contact['created'] < 5:
                            intf.deletecontact(tx, self.id,
                                               contact.end_node["id"], "Agent",
                                               "Agent")
            oldest_usage = 0
            contact_drop = None
            while len(carers) + len(contacts) > self.social:
                for contact in contacts:
                    if intf.gettime() - contact["usage"] > oldest_usage:
                        contact_drop = contact
                        oldest_usage = intf.gettime() - contact["usage"]
                intf.deletecontact(tx, self.id, contact_drop.end_node["id"],
                                   "Agent", "Agent")
def adjustcapasity(txl, history, dynamic=True):
    """
    Rule function that applies the capacity change algorithm in the  case of two intervention node systems. This is uses
    a history variable that is cleared when the capacity is adjusted so that another five timesteps must pass before the
    capacity can be changed again. This only modifies OpenIntervention if dynamic is true else only intervention is
    modified.

    :param txl: neo4j database write transaction
    :param history: List of previous average times since discharge
    :param dynamic: indicates if adjustment to OpenIntervention is needed

    :return: history
    """
    currenttimes = timesincedischarge(txl)
    if not currenttimes and history:
        currentav = history[-1]
    elif not currenttimes:
        currentav = 14
    else:
        currentav = mean(currenttimes)
    history = history + [currentav]
    # If it has been less than 20 time steps since last change do nothing
    if len(history) < 20:
        return history
    else:
        if history[-5] - history[-1] < -1 and history[-1] > 5:
            if dynamic:
                if intf.getnodevalue(
                        txl, "InterventionOpen", "cap",
                        uid="name") > 0 and dynamic:
                    intf.updatenode(
                        txl, "Intervention", "cap",
                        intf.getnodevalue(
                            txl, "Intervention", "cap", uid="name") + 1,
                        "name")
                    intf.updatenode(
                        txl, "InterventionOpen", "cap",
                        intf.getnodevalue(
                            txl, "InterventionOpen", "cap", uid="name") - 1,
                        "name")
            else:
                intf.updatenode(
                    txl, "Intervention", "cap",
                    intf.getnodevalue(txl, "Intervention", "cap", uid="name") +
                    1, "name")
            return []
        elif history[-5] - history[-1] > 0 and history[-1] < 5:
            if intf.getnodevalue(txl, "Intervention", "cap", uid="name") > 0:
                intf.updatenode(
                    txl, "Intervention", "cap",
                    intf.getnodevalue(txl, "Intervention", "cap", uid="name") -
                    1, "name")
                if dynamic:
                    intf.updatenode(
                        txl, "InterventionOpen", "cap",
                        intf.getnodevalue(
                            txl, "InterventionOpen", "cap", uid="name") + 1,
                        "name")

            return []
        else:
            return history
Exemple #23
0
    def learn(self, tx, choice):
        """
        Agent is changed by node and can change node and edge it arrived by. This can include changes to decision
         making parameters.

        :param tx: neo4j database write transaction
        :param choice: Chosen edge for move

        :return: None
        """
        super(FallAgent, self).learn(tx, choice)
        # modify mob, conf, res and energy based on new node
        if self.fall and self.fall != "Mild":
            if self.wellbeing != "Fallen":
                self.wellbeing = "Fallen"
                intf.updateagent(tx, self.id, "wellbeing", self.wellbeing)
                clock = tx.run("MATCH (a:Clock) "
                               "RETURN a.time").values()[0][0]
                self.log = self.log + ", (Fallen, " + str(clock) + ")"
        if "modm" in choice.end_node:
            self.mobility = self.positive(
                npr.normal(choice.end_node["modm"], 0.05) + self.mobility)
            intf.updateagent(tx, self.id, "mob", self.mobility)
            # check for updates to wellbeing and log any changes
            if self.mobility == 0:
                if self.wellbeing != "Fallen":
                    self.wellbeing = "Fallen"
                    intf.updateagent(tx, self.id, "wellbeing", self.wellbeing)
                    clock = tx.run("MATCH (a:Clock) "
                                   "RETURN a.time").values()[0][0]
                    self.log = self.log + ", (Fallen, " + str(clock) + ")"
            elif self.mobility > 1:
                if self.wellbeing != "Healthy":
                    self.wellbeing = "Healthy"
                    intf.updateagent(tx, self.id, "wellbeing", self.wellbeing)
                    clock = tx.run("MATCH (a:Clock) "
                                   "RETURN a.time").values()[0][0]
                    self.log = self.log + ", (Healthy, " + str(clock) + ")"
            elif self.mobility <= 1:
                if self.wellbeing == "Healthy":
                    self.wellbeing = "At risk"
                    intf.updateagent(tx, self.id, "wellbeing", self.wellbeing)
                    clock = tx.run("MATCH (a:Clock) "
                                   "RETURN a.time").values()[0][0]
                    self.log = self.log + ", (At risk, " + str(clock) + ")"
        if "modc" in choice.end_node:
            self.confidence = self.positive(
                npr.normal(choice.end_node["modc"], 0.05) + self.confidence)
            intf.updateagent(tx, self.id, "conf", self.confidence)
        if "modrc" in choice.end_node:
            self.confidence_resources = self.positive(
                npr.normal(choice.end_node["modrc"], 0.05) +
                self.confidence_resources)
            intf.updateagent(tx, self.id, "conf_res",
                             self.confidence_resources)
        if "modrm" in choice.end_node:
            self.mobility_resources = self.positive(
                npr.normal(choice.end_node["modrm"], 0.05) + self.mobility)
            intf.updateagent(tx, self.id, "mob_res", self.mobility_resources)
        if "energy" in choice.end_node:
            self.current_energy = npr.normal(choice.end_node["energy"],
                                             0.05) + self.current_energy
            intf.updateagent(tx, self.id, "energy", self.current_energy)
        # log going into care
        if choice.end_node["name"] == "Care":
            clock = tx.run("MATCH (a:Clock) " "RETURN a.time").values()[0][0]
            self.log = self.log + ", (Care, " + str(clock) + ")"
        if "cap" in choice.end_node.keys():
            intf.updatenode(tx, choice.end_node["name"], "load",
                            choice.end_node["load"] + 1, "name")
        if self.view[0]["name"] == "Hos" and choice.end_node["name"] != "Hos":
            clock = tx.run("MATCH (a:Clock) " "RETURN a.time").values()[0][0]
            self.log = self.log + ", (Discharged, " + str(clock) + ")"
        intf.updateagent(tx, self.id, "log", str(self.log))
Exemple #24
0
    def payment(self, tx):
        """
        Modifies chosen edge and agent. These include mobility, confidence and energy modifications.

        :param tx: neo4j database write transaction
        :param intf: Interface for databse calls

        :return: None
        """
        super(FallAgent, self).payment(tx)
        # Deduct energy used on edge
        if "energy" in self.choice.keys():
            self.current_energy = npr.normal(self.choice["energy"],
                                             0.05) + self.current_energy
            intf.updateagent(tx, self.id, "energy", self.current_energy)
        # mod variables based on edges
        if "modm" in self.choice:
            self.mobility = self.positive(
                npr.normal(self.choice["modm"], 0.05) + self.mobility)
            intf.updateagent(tx, self.id, "mob", self.mobility)
            if self.mobility == 0:
                if self.wellbeing != "Fallen":
                    self.wellbeing = "Fallen"
                    intf.updateagent(tx, self.id, "wellbeing", self.wellbeing)
                    clock = tx.run("MATCH (a:Clock) "
                                   "RETURN a.time").values()[0][0]
                    self.log = self.log + ", (Fallen, " + str(clock) + ")"
            elif self.mobility > 1:
                if self.wellbeing != "Healthy":
                    self.wellbeing = "Healthy"
                    intf.updateagent(tx, self.id, "wellbeing", self.wellbeing)
                    clock = tx.run("MATCH (a:Clock) "
                                   "RETURN a.time").values()[0][0]
                    self.log = self.log + ", (Healthy, " + str(clock) + ")"
            elif self.mobility <= 1:
                if self.wellbeing == "Healthy":
                    self.wellbeing = "At risk"
                    intf.updateagent(tx, self.id, "wellbeing", self.wellbeing)
                    clock = tx.run("MATCH (a:Clock) "
                                   "RETURN a.time").values()[0][0]
                    self.log = self.log + ", (At risk, " + str(clock) + ")"
        if "modc" in self.choice:
            self.confidence = self.positive(
                npr.normal(self.choice["modc"], 0.05) + self.confidence)
            intf.updateagent(tx, self.id, "conf", self.confidence)
Exemple #25
0
    def snapshot(self, txl, ctime):
        """
        Captures the current statistics of the system and updates graph grid, including average system interval,
        intervention interval, average number of falls at end of system interval and proportions of population in each
        population category.

        :param txl: neo4j database write transaction
        :param ctime: current timestep

        :return: None
        """
        look = txl.run("MATCH (n:Node) "
                       "WHERE n.name = {node} "
                       "RETURN n",
                       node="Intervention")
        self.nrecord = look.values()
        if super(Monitor, self).snapshot(txl, ctime):
            # Update plot 1 - Int Cap
            # Update to track average number of each type of fall for people in care.
            [mild, moderate, severe, agents_n] = txl.run(
                "MATCH (n:Node) "
                "WHERE n.name={node} "
                "RETURN n.mild, n.moderate, n.severe, n.agents",
                node="Care").values()[0]
            if agents_n:
                self.y11 = pylab.append(self.y11, mild / agents_n)
                self.p11.set_data(self.t, self.y11)
                self.y12 = pylab.append(self.y12, moderate / agents_n)
                self.p12.set_data(self.t, self.y12)
                self.y13 = pylab.append(self.y13, severe / agents_n)
                self.p13.set_data(self.t, self.y13)
                if max([
                        mild / agents_n, moderate / agents_n, severe / agents_n
                ]) > self.y1:
                    self.y1 = max([
                        mild / agents_n, moderate / agents_n, severe / agents_n
                    ])
                    self.p11.axes.set_ylim(0.0, self.y1 + 1.0)
                    self.p12.axes.set_ylim(0.0, self.y1 + 1.0)
                    self.p13.axes.set_ylim(0.0, self.y1 + 1.0)
            else:
                self.y11 = pylab.append(self.y11, 0)
                self.p11.set_data(self.t, self.y11)
                self.y12 = pylab.append(self.y12, 0)
                self.p12.set_data(self.t, self.y12)
                self.y13 = pylab.append(self.y13, 0)
                self.p13.set_data(self.t, self.y13)
            # Update plot 2 - Hos to Int
            gaps = timesincedischarge(txl)
            if gaps:
                hiint = mean(timesincedischarge(txl))
                self.y3storage = self.y3storage + [hiint]
                if len(self.y3storage) >= 10:
                    self.y3storage = self.y3storage[-10:]
            if self.y3storage:
                self.y2 = pylab.append(self.y2, mean(self.y3storage))
                if self.y < mean(self.y3storage):
                    self.y = mean(self.y3storage)
                self.p2.set_data(self.t, self.y2)
            # Update plot 3 - Start to Care
            careint = intf.getnodevalue(txl, "Care", "interval", uid="name")
            if careint:
                scint = careint
            else:
                scint = 0
            self.y3 = pylab.append(self.y3, scint)
            if self.y < scint:
                self.y = scint
            self.p3.set_data(self.t, self.y3)
            # Update plot 4
            # Update plot showing distribution of well being in the general population.
            wb = txl.run(
                "MATCH (a:Agent)-[r:LOCATED]->(n:Node) "
                "WHERE NOT n.name={node} "
                "RETURN a.wellbeing",
                node="Care").values()
            wb = [val[0] for val in wb]
            healthy = wb.count("Healthy") / len(wb)
            at_risk = wb.count("At risk") / len(wb)
            fallen = wb.count("Fallen") / len(wb)
            self.y41 = pylab.append(self.y41, healthy)
            self.p41.set_data(self.t, self.y41)
            self.y42 = pylab.append(self.y42, at_risk)
            self.p42.set_data(self.t, self.y42)
            self.y43 = pylab.append(self.y43, fallen)
            self.p43.set_data(self.t, self.y43)
            if max([healthy, at_risk, fallen]) / len(wb) > self.y4:
                self.y4 = max([healthy, at_risk, fallen])
                self.p41.axes.set_ylim(0.0, self.y4 + 1.0)
                self.p42.axes.set_ylim(0.0, self.y4 + 1.0)
                self.p43.axes.set_ylim(0.0, self.y4 + 1.0)
            # Update plot axes
            if self.x >= self.xmax - 1.00:
                self.p11.axes.set_xlim(0.0, self.x + 1.0)
                self.p12.axes.set_xlim(0.0, self.x + 1.0)
                self.p13.axes.set_xlim(0.0, self.x + 1.0)
                self.p2.axes.set_xlim(0.0, self.x + 1.0)
                self.p3.axes.set_xlim(0.0, self.x + 1.0)
                self.p41.axes.set_xlim(0.0, self.x + 1.0)
                self.p42.axes.set_xlim(0.0, self.x + 1.0)
                self.p43.axes.set_xlim(0.0, self.x + 1.0)
                self.xmax = self.x
            if self.y > self.ymax1 - 1.0:
                self.p2.axes.set_ylim(0.0, self.y + 1.0)
                self.p3.axes.set_ylim(0.0, self.y + 1.0)
            if self.show:
                plt.pause(0.0005)
Exemple #26
0
    def generate_population(tx, ps):
        """
        Generates the required number of agents and starts them at the Home node.
        Builds social connections between agents.

        :param tx: neo4j database write transaction
        :param ps: population size

        :return: None
        """
        fa = Patient(None)
        for j in range(ps // 4):
            tx.run("CREATE (a:Carer {id:{j_id}, energy:20})", j_id=j)
        for i in range(ps):
            fa.generator(tx, [0.8, 0.9, 1, [2, 0, 1, 2], 2, 8])
            if npr.random(1) < 0.5:
                if npr.random(1) < 0.5:
                    samplesize = 2
                else:
                    samplesize = 1
                newfriends = npr.choice(range(ps // 4),
                                        size=samplesize,
                                        replace=False)
                for nf in newfriends:
                    intf.createedge(
                        tx, i, nf, 'Agent', 'Carer', 'SOCIAL',
                        'created: ' + str(intf.gettime(tx)) + ', usage: ' +
                        str(intf.gettime(tx)) + ', carer: True')
                    intf.createedge(tx, i, nf, 'Agent', 'Carer', 'FRIEND')
        for i in range(ps):
            newfriends = npr.choice(range(ps),
                                    size=npr.choice(range(3)),
                                    replace=False)
            for nf in newfriends:
                if not nf == i:
                    intf.createedge(
                        tx, i, nf, 'Agent', 'Agent', 'SOCIAL',
                        'created: ' + str(intf.gettime(tx)) + ', usage: ' +
                        str(intf.gettime(tx)) + ', carer: False')
                    intf.createedge(tx, i, nf, 'Agent', 'Agent', 'FRIEND')