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 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 #3
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 #4
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 #5
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 #6
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)
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