Рубрики
Без рубрики

Метакощущение с Python – Направленные идеи карты

Создайте направленные идеи карты с программированием Python и Tkinter, чтобы помочь разработать ваши метакогнитивные навыки.

Автор оригинала: Robin Andrews.

Компьютерные программисты в целом проводят честный момент времени в алгоритмическое мышление Отказ Идея Метакощущение в основном «думает о мышлении», с подразумеваемой повесткой дня улучшения нашего мышления. Тогда это означает, что метакогниствие может быть использовано для программистов, поскольку он дает возможность улучшить наше алгоритмическое мышление.

Однако там не останавливается. Как только мы заинтересованы в размышлениях о том, что открывается целый мир возможностей, а если открыт для возможности того, что наше мышление может быть улучшено, то возможны великие вещи. Программисты, вероятно, лучше размещены, чем многие, чтобы признать необходимость улучшения в нашем мышлении, поскольку мы обычно в привычке изучения новых вещей на очень регулярной основе. В конце концов, мы бы не дойдем до разработчиков, если мы не чувствуем себя комфортно с идеей, что мы еще не знаем все. Это, возможно, менее распространенное отношение за пределами мира программирования.

Было много работы, проделанную в области метакогни. Большая часть основательной работы была сделана Эдвард де Боно Отказ Он создал множество книг и разработал курсы обучения и инструменты, которые распространены в широко распространении во многих учреждениях по всему миру. Мне нравится думать о нем как о том, как «дедушка метакогнита», но, чтобы быть честным, я не знаю достаточно о его влияниях, чтобы знать, является ли это заслуженным титулом.

Общий вопрос с работой De Bono заключается в том, что люди, находящиеся на него, часто не могут признать его значение и власть. Многие из идей настолько просты, что они часто уволяются как тривиальные. Существует также культурная черта интеллектуальных людей, часто не признающих необходимость улучшения их мышления. Если работа De Bono – это то, что вас интересует, вам придется судить о себе для себя. По моему личному мнению, это нечестие революционного, в том, что это самый большой шаг вперед в человеческом рассуждении со времен великих греческих философов, таких как Платон и Аристотель.

Направленные идеи карты с Python

Так что это связано с программированием Python?

Я хочу поделиться с вами метакогнитивным инструментом, написанным в Python для изучения отношений между элементами в ситуации. Это вдохновлено Эдвард де Боно входки Отказ Вы можете получить код из мой аккаунт github Отказ То, как работает инструмент, это то, что он создает Направленный график где . узлы представлять различные аспекты рассматриваемой ситуации.

Как только график создан, он дает нам визуальное представление соединений между элементами. Нет никакой правильной интерпретации результирующего графа, но вместо этого вы заметите определенные функции, такие как петли и Гравитационные колодцы Что может дать вам неожиданное понимание ситуации, которую вы изучите.

Применение:

  • Перечислите элементы, присутствующие в ситуации, которую вы хотите исследовать
  • Для каждого элемента выберите только один элемент, который он течет наиболее естественно, на основании любого определения «потока к» вам нравится.
  • Нажмите отправить и увидеть визуальное представление отношений между элементами
  • Интерпретировать по желанию
  • Вы можете сохранить/загрузить предыдущие сеансы, если требуется.

Приложение может сохранить и загружать предыдущие сеансы в JSON Формат для будущего использования. Обратите внимание, что вы должны создать график, нажав Отправить Прежде чем вы сможете сохранить сеанс. Также обратите внимание, что существуют некоторые правила валидации, которые означают, что вы не сможете представить форму в определенных условиях (например, один узел, протекающий на несколько других узлов).

Код Python для Идея Карты Метакогнитивные инструмент

Я предоставил код Python для этого приложения ниже для справки. Пару вещей, чтобы отметить:

  • Tkinter и Матплотлиб Не играйте красиво вместе. Для этого довольно простого приложения мне не нужно было использовать matplotlib.backends.backend_tkagg Но для всего сложного, вам нужно будет изучить этот подход к работе с обеими библиотеками вместе. Вы можете увидеть Пример здесь Отказ
  • ettewxx Пакет (который вам нужно будет установить, используя PIP ), необходима небольшая модификация для правильной позиции узлов, когда графики не подключены. Это то, что my_reingold.py Файлы для, и он переопределяет оригинал ettewxx версия.
# idea_maps.py

import matplotlib.pyplot as plt
import json
import tkinter as tk
from tkinter import filedialog
import networkx as nx
from my_reingold import my_reingold
nx.drawing.layout._fruchterman_reingold = my_reingold


NUM_ROWS = 13
BOLD_FONT = ("calbri", 12, "bold")
NORMAL_FONT = ("calbri", 12, "normal")


def create_widgets():
    for i in range(NUM_ROWS):
        key = chr(i + 65)
        this_row = widgets[key] = {}
        this_row["label"] = tk.Label(root, text=key, font=BOLD_FONT)
        this_row["label"].grid(row=i, column=0, padx=5, pady=10)
        this_row["factor_field"] = tk.Entry(root, width=60, font=NORMAL_FONT)
        this_row["factor_field"].grid(row=i, column=1, padx=5, pady=10)
        this_row["target_node_field"] = tk.Entry(
            root, width=5, font=NORMAL_FONT)
        this_row["target_node_field"].grid(row=i, column=2, padx=5, pady=10)
        this_row["clear_button"] = tk.Button(root, text="Clear", command=lambda key=key: clear(
            key), font=BOLD_FONT).grid(row=i, column=3, padx=5, pady=10)

    submit_button = tk.Button(root, text="Submit", command=submit,
                              font=BOLD_FONT).grid(row=NUM_ROWS + 1, column=0, padx=5, pady=10)
    save_button = tk.Button(root, text="Save", command=save,
                            font=BOLD_FONT).grid(row=NUM_ROWS + 1, column=1, padx=5, pady=10)
    load_button = tk.Button(root, text="Load", command=load,
                            font=BOLD_FONT).grid(row=NUM_ROWS + 1, column=2, padx=5, pady=10)


def validate_fields():
    legal_targets = list(widgets.keys()) + [""]  # to allow empty fields

    for key, row in widgets.items():
        factor_field_contents = row["factor_field"].get()
        target_node_field_contents = row["target_node_field"].get().upper()

        # Every target must belong to the set of available factors
        if target_node_field_contents not in legal_targets:
            return False

        #  Target factor field must not be empty
        if target_node_field_contents:
            if not widgets[target_node_field_contents]["factor_field"].get():
                return False

        # Every non-empty factor must have a target
        flen0 = len(factor_field_contents) == 0
        tlen0 = len(target_node_field_contents) == 0
        if (flen0 and not tlen0) or (not flen0 and tlen0):
            return False

    return True


def submit():
    plt.close()
    if validate_fields():
        G = nx.DiGraph()
        edges = []
        for key, row in widgets.items():
            factor_field_contents = row["factor_field"].get()
            target_node_field_contents = row["target_node_field"].get().upper()
            if factor_field_contents != "" and target_node_field_contents != "":
                edges.append((key, target_node_field_contents))
                data[key] = {"factor": factor_field_contents,
                             "target_node": target_node_field_contents}
        G.add_edges_from(edges)
        # pos = nx.spring_layout(G, k=1.0, iterations=50)
        pos = nx.spring_layout(G)
        nx.draw_networkx_nodes(G, pos, node_size=500, node_color="green")
        nx.draw_networkx_labels(G, pos, font_color="white")
        nx.draw_networkx_edges(
            G, pos, connectionstyle='arc3, rad = 0.1', width=2, arrows=True)
        plt.show()


def save():
    print("Attempting to save.")
    # print(f"data: {data}")
    if data:
        try:
            filename = filedialog.asksaveasfile(mode='w')
            json_data = json.dumps(data, indent=4)
            filename.write(json_data)
            print("Data saved.")
        except OSError as e:
            print(e)


def load():
    for key, entries in widgets.items():
        entries["factor_field"].delete(0, "end")
        entries["target_node_field"].delete(0, "end")
    try:
        filename = filedialog.askopenfile(mode='r')
        loaded_data = json.loads(filename.read())
        # print(loaded_data)
        for key, entries in loaded_data.items():
            widgets[key]["factor_field"].insert(0, entries["factor"])
            widgets[key]["target_node_field"].insert(0, entries["target_node"])
    except OSError as e:
        print(e)


def clear(key):
    widgets[key]["factor_field"].delete(0, "end")
    widgets[key]["target_node_field"].delete(0, "end")


if __name__ == "__main__":
    data = {}
    widgets = {}
    root = tk.Tk()
    root.title("Directional Idea Map")
    create_widgets()
    root.mainloop()
# my_reingold.py

def my_reingold(
    A, k=None, pos=None, fixed=None, iterations=50, threshold=1e-4, dim=2, seed=None
):
    # Position nodes in adjacency matrix A using Fruchterman-Reingold
    # Entry point for NetworkX graph is fruchterman_reingold_layout()
    import numpy as np

    try:
        nnodes, _ = A.shape
    except AttributeError as e:
        msg = "fruchterman_reingold() takes an adjacency matrix as input"
        raise nx.NetworkXError(msg) from e

    if pos is None:
        # random initial positions
        pos = np.asarray(seed.rand(nnodes, dim), dtype=A.dtype)
    else:
        # make sure positions are of same type as matrix
        pos = pos.astype(A.dtype)

    # optimal distance between nodes
    if k is None:
        k = np.sqrt(1.0 / nnodes)
    # the initial "temperature"  is about .1 of domain area (=1x1)
    # this is the largest step allowed in the dynamics.
    # We need to calculate this in case our fixed positions force our domain
    # to be much bigger than 1x1
    t = max(max(pos.T[0]) - min(pos.T[0]), max(pos.T[1]) - min(pos.T[1])) * 0.1
    # simple cooling scheme.
    # linearly step down by dt on each iteration so last iteration is size dt.
    dt = t / float(iterations + 1)
    delta = np.zeros((pos.shape[0], pos.shape[0], pos.shape[1]), dtype=A.dtype)
    # the inscrutable (but fast) version
    # this is still O(V^2)
    # could use multilevel methods to speed this up significantly
    for iteration in range(iterations):
        # matrix of difference between points
        delta = pos[:, np.newaxis, :] - pos[np.newaxis, :, :]
        # distance between points
        distance = np.linalg.norm(delta, axis=-1)
        # enforce minimum distance of 0.01
        np.clip(distance, 0.01, None, out=distance)
        # displacement "force"
        displacement = np.einsum(
            "ijk,ij->ik", delta, (k * k / distance ** 2 - A * distance / k)
        )
        ### Source code modified by RA
        # Prevent things from flying off into infinity if not connected
        displacement = displacement - pos / ( k * np.sqrt(nnodes))
        ### END of modifications
        # update positions
        length = np.linalg.norm(displacement, axis=-1)
        length = np.where(length < 0.01, 0.1, length)
        delta_pos = np.einsum("ij,i->ij", displacement, t / length)
        if fixed is not None:
            # don't change positions of fixed nodes
            delta_pos[fixed] = 0.0
        pos += delta_pos
        # cool temperature
        t -= dt
        err = np.linalg.norm(delta_pos) / nnodes
        if err < threshold:
            break
    return pos

Я надеюсь, что вы найдете это приложение интересно и полезно.

Счастливые вычисления и кризиты.