二维或三维直角坐标中,画出形状不同的含N个格点的链

本文介绍了一种用于三维空间中链路配置的方法,包括如何生成不同的链路路径、剔除重叠路径、实现路径的旋转与镜像变换,最终绘制出链路的三维图像。同时探讨了在二维情况下的简化处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文只讨论单链情况,无分支
总体思路:
1.以第一个节点为原点(0,0,0),依次向外生长,0、1、2、3、4、5分别代表6个生长方向(0:x+1;1:x-1; 2:y+1; 3:y-1; 4:z+1; 5:z-1)。例如列表[0,2,1,1,4],表示x+1,y+1,x-1,x-1,z+1
在这里插入图片描述

2.itertools.product遍历所有情况,然后删去旋转对称的、镜像对称的、节点顺序反向的(二维情况更为简单,无需旋转镜像)
3.再删去有含重叠节点的情况(即自身与自身交叉的情况)
4.把相对位置转换为绝对坐标,画图

定义旋转和镜像(对列表内容进行改变)

import itertools
from matplotlib import pyplot as plt
from matplotlib.pyplot import MultipleLocator
import os
#镜像,分别有三种角度的镜像
def mirror(l1,axis=0):
    l = l1.copy()
    if axis==0:
        for i in range(len(l)):
            if l[i] == 0:
                l[i] = 1
            elif l[i] == 1:
                l[i] = 0
    elif axis==1:
        for i in range(len(l)):
            if l[i] == 2:
                l[i] = 3
            elif l[i] == 3:
                l[i] = 2

    elif axis==2:
        for i in range(len(l)):
            if l[i] == 4:
                l[i] = 5
            elif l[i] == 5:
                l[i] = 4
    return l
#旋转,有三个方向的旋转,可以旋转0~3度,1度代表90°
def rotate(l1,axis=0,degree=1):
    l=l1.copy()
    if degree==0:
        return l
    if axis == 0:
        for i in range(len(l)):
            if degree==1:
                if l[i]==0:
                    l[i]=3
                elif l[i]==1:
                    l[i]=2
                elif l[i] == 2:
                    l[i] = 0
                elif l[i] == 3:
                    l[i] = 1
            elif degree==2:
                if l[i]==0:
                    l[i]=1
                elif l[i]==1:
                    l[i]=0
                elif l[i] == 2:
                    l[i] = 3
                elif l[i] == 3:
                    l[i] = 2
            elif degree==3:
                if l[i]==0:
                    l[i]=2
                elif l[i]==1:
                    l[i]=3
                elif l[i] == 2:
                    l[i] = 1
                elif l[i] == 3:
                    l[i] = 0
    elif axis == 1:
        for i in range(len(l)):
            if degree==1:
                if l[i]==0:
                    l[i]=5
                elif l[i]==1:
                    l[i]=4
                elif l[i] == 4:
                    l[i] = 0
                elif l[i] == 5:
                    l[i] = 1
            elif degree==2:
                if l[i]==0:
                    l[i]=1
                elif l[i]==1:
                    l[i]=0
                elif l[i] == 4:
                    l[i] = 5
                elif l[i] == 5:
                    l[i] = 4
            elif degree==3:
                if l[i]==0:
                    l[i]=4
                elif l[i]==1:
                    l[i]=5
                elif l[i] == 4:
                    l[i] = 1
                elif l[i] == 5:
                    l[i] = 0
    elif axis == 2:
        for i in range(len(l)):
            if degree==1:
                if l[i]==4:
                    l[i]=3
                elif l[i]==5:
                    l[i]=2
                elif l[i] == 2:
                    l[i] = 4
                elif l[i] == 3:
                    l[i] = 5
            elif degree==2:
                if l[i]==4:
                    l[i]=5
                elif l[i]==5:
                    l[i]=4
                elif l[i] == 2:
                    l[i] = 3
                elif l[i] == 3:
                    l[i] = 2
            elif degree==3:
                if l[i]==4:
                    l[i]=2
                elif l[i]==5:
                    l[i]=3
                elif l[i] == 2:
                    l[i] = 5
                elif l[i] == 3:
                    l[i] = 4

    return l

删去重复情况
对每种情况进行三维度的旋转和镜像,每种情况通过旋转、镜像、反序的组合一共可产生4 * 4 * 4 * 2 * 2 * 2 * 2=1024种情况(包括自身),相当于每种情况都有1024种重复情况,但是旋转2度相当于两重镜像,旋转3度相当于旋转一度+镜像,所以不需要考虑旋转2或3度的情况,所以有2 * 2 * 2 * 2 * 2 * 2 * 2=128种情况。每做出一种变换,就在总的集合内删去此变换出来的情况,但要保证不删去自己。

def del_rotate_3D(l1_all):
    l=l1_all.copy()
    l2=l.copy()
    i=0
    while i<len(l):
        for degree1 in range(2):
            for degree2 in range(2):
                for degree3 in range(2):
                    for m1 in range(2):
                        for m2 in range(2):
                            for m3 in range(2):
                                l2[i]=rotate(l[i],0,degree1)
                                l2[i] = rotate(l2[i], 1, degree2)
                                l2[i] = rotate(l2[i], 2, degree3)
                                if m1==1:l2[i]=mirror(l2[i],0)
                                if m2==1:l2[i] = mirror(l2[i], 1)
                                if m3==1:l2[i] = mirror(l2[i], 2)
                                if l2[i]==l[i]:
                                    pass
                                else:
                                    try:l.remove(l2[i])
                                    except:pass
                                l2[i].reverse()
                                if l2[i] == l[i]:
                                    pass
                                else:
                                    try:l.remove(l2[i])
                                    except:pass
        i+=1
    return l

输入每种情况的列表组成的列表,把相对位置转换为绝对坐标,若有重复坐标则删除这种情况

def delete_cross_3D(chosen_conf):
    list4 = []
    for ii in range(len(chosen_conf)):
        xl = [0]
        yl = [0]
        zl=[0]
        for s in chosen_conf[ii]:
            if s == 0:
                xl.append(xl[-1]+1)
                yl.append(yl[-1])
                zl.append(zl[-1])
            elif s == 1:
                xl.append(xl[-1]-1)
                yl.append(yl[-1])
                zl.append(zl[-1])
            elif s == 2:
                xl.append(xl[-1])
                yl.append(yl[-1] + 1)
                zl.append(zl[-1])
            elif s == 3:
                xl.append(xl[-1])
                yl.append(yl[-1]-1)
                zl.append(zl[-1])
            elif s == 4:
                xl.append(xl[-1])
                yl.append(yl[-1])
                zl.append(zl[-1]+1)
            elif s == 5:
                xl.append(xl[-1])
                yl.append(yl[-1])
                zl.append(zl[-1]-1)


        xyz = list(zip(xl, yl,zl))
        if len(set(xyz)) == len(xyz):
            list4.append(chosen_conf[ii])
        else:
            pass
    return list4

输入一个列表,把相对位置转换为绝对坐标,返回x,y,z

def relative2absolute(l1):
    l=l1.copy()
    xl = [0]
    yl = [0]
    zl = [0]
    for s in l:
        if s == 0:
            xl.append(xl[-1] - 1)
            yl.append(yl[-1])
            zl.append(zl[-1])
        elif s == 1:
            xl.append(xl[-1] + 1)
            yl.append(yl[-1])
            zl.append(zl[-1])
        elif s == 2:
            xl.append(xl[-1])
            yl.append(yl[-1] - 1)
            zl.append(zl[-1])
        elif s == 3:
            xl.append(xl[-1])
            yl.append(yl[-1] + 1)
            zl.append(zl[-1])
        elif s == 4:
            xl.append(xl[-1])
            yl.append(yl[-1])
            zl.append(zl[-1] - 1)
        elif s == 5:
            xl.append(xl[-1])
            yl.append(yl[-1])
            zl.append(zl[-1] + 1)

    return xl,yl,zl

画图,ax.plot3D

def draw_figures(xm,ym,zm,seq_num):
    n=len(xm)
    x_major_locator = MultipleLocator(1)
    # 把x轴的刻度间隔设置为1,并存在变量里
    y_major_locator = MultipleLocator(1)
    z_major_locator = MultipleLocator(1)
    # 把y轴的刻度间隔设置为10,并存在变量里
    ax = plt.axes(projection='3d')
    # ax为两条坐标轴的实例
    ax.xaxis.set_major_locator(x_major_locator)
    # 把x轴的主刻度设置为1的倍数
    ax.yaxis.set_major_locator(y_major_locator)
    ax.zaxis.set_major_locator(z_major_locator)

    xmin = min(xm+ym+zm)
    xmax = max(xm+ym+zm)
    xdif=xmax-xmin
    #plt.figure(iii)
    ax.plot3D(xm,ym,zm, 'ro-')

    ax.set_xlim(min(xm), min(xm)+xdif + 0.5)
    ax.set_ylim(min(ym), min(ym)+xdif + 0.5)
    ax.set_zlim(min(zm), min(zm)+xdif + 0.5)
    plt.savefig('n='+str(n)+'_3D/' + str("{:0>5d}".format(seq_num)) + ".png")
    plt.clf()
    #plt.show()
    # plt.close('all')

总体过程

def generate3(n):
    conf=list(itertools.product([0,1,2,3,4,5], repeat=n-1))#生成所有情况
    for i in range(len(conf)):
        conf[i]=list(conf[i])

    a=delete_cross_3D(conf)
    a = del_rotate_3D(a)

    if not os.path.exists('n='+str(n)+'_3D'):
        os.mkdir('n='+str(n)+'_3D')
    seq_num=0
    for con in a:
        seq_num+=1
        xld,yld,zld=relative2absolute(con)
        draw_figures(xld,yld,zld,seq_num)
    print(len(a))
    return a

调用函数,生成所有情况的图片。设有4个节点,n=4

x=generate3(4)

结果有5种情况:
0 0 0
0 0 2
0 2 0
0 2 1
0 2 4
在这里插入图片描述024
在这里插入图片描述002
在这里插入图片描述000
在这里插入图片描述020
021021

如果是二维情况,无需旋转镜像,用此方法即可

import itertools
from itertools import combinations,permutations
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.pyplot import MultipleLocator
import pickle
import os

#在已有数据基础上增加一个格点,头尾各有4种情况,一种情况变为八种
def add_one_residue(front_conf_list):
    conf_add = list(itertools.product([0, 1, 2, 3], repeat=1))
    added_conf_list = []
    for ii in range(len(front_conf_list)):
        for i in range(len(conf_add)):
            added_conf_list.append(front_conf_list[ii] + list(conf_add[i]))
            added_conf_list.append(list(conf_add[i])+front_conf_list[ii])
    return added_conf_list

#相对转绝对坐标
def relative2absolute(conf_l):
    listx = []
    listy=[]
    for ii in range(len(conf_l)):
        xl = [0]
        yl = [0]
        for s in conf_l[ii]:
            if s == 0:
                xl.append(xl[-1]+1)
                yl.append(yl[-1] )
            elif s == 1:
                xl.append(xl[-1] - 1)
                yl.append(yl[-1])
            elif s == 2:
                xl.append(xl[-1])
                yl.append(yl[-1] + 1)
            elif s == 3:
                xl.append(xl[-1] )
                yl.append(yl[-1]- 1)

        listx.append(xl)
        listy.append(yl)

    return listx,listy

def draw_figures(axis_list1,axis_list2,n):
    iii = 0
    x_major_locator = MultipleLocator(1)
    # 把x轴的刻度间隔设置为1,并存在变量里
    y_major_locator = MultipleLocator(1)
    # 把y轴的刻度间隔设置为10,并存在变量里
    for i in range(len(axis_list1)):
        ax = plt.gca()
        # ax为两条坐标轴的实例
        ax.xaxis.set_major_locator(x_major_locator)
        # 把x轴的主刻度设置为1的倍数
        ax.yaxis.set_major_locator(y_major_locator)
        xl=axis_list1[i]
        yl=axis_list2[i]
        xmin = min(xl + yl)
        xmax = max(xl + yl)
        xdif=xmax-xmin
        iii += 1
        #plt.figure(iii)
        plt.plot(xl, yl, 'ro-')
        plt.xlim(min(xl) - 0.5, min(xl)+xdif + 0.5)
        plt.ylim(min(yl) - 0.5, min(yl)+xdif + 0.5)
        plt.savefig('n='+str(n)+'_2D/' + str("{:0>5d}".format(iii)) + ".png")
        plt.clf()
        #plt.show()
        # plt.close('all')

#列表中不论什么数字,按出现顺序标为0,1,2,3,例如[3,1,1,2,3,0,0] 变为[0,1,1,2,0,3,3].
# 一个列表不论旋转或镜像,按照此变换后都一样。这种形式称为字母型
def num2letter(l1):
    l=l1.copy()
    o=[]
    re=[]
    for i in range(len(l)):
        if not (l[i] in re):
            re.append(l[i])
    for i in range(len(l)):
        o.append(re.index(l[i]))
    return o

#是否有重叠点
def if_cross(l1):
    l=l1.copy()
    xl = [0]
    yl = [0]
    zl = [0]
    for s in l:
        if s == 0:
            xl.append(xl[-1] - 1)
            yl.append(yl[-1])
            zl.append(zl[-1])
        elif s == 1:
            xl.append(xl[-1] + 1)
            yl.append(yl[-1])
            zl.append(zl[-1])
        elif s == 2:
            xl.append(xl[-1])
            yl.append(yl[-1] - 1)
            zl.append(zl[-1])
        elif s == 3:
            xl.append(xl[-1])
            yl.append(yl[-1] + 1)
            zl.append(zl[-1])
        elif s == 4:
            xl.append(xl[-1])
            yl.append(yl[-1])
            zl.append(zl[-1] - 1)
        elif s == 5:
            xl.append(xl[-1])
            yl.append(yl[-1])
            zl.append(zl[-1] + 1)

    xyz = list(zip(xl, yl, zl))
    if len(set(xyz)) == len(xyz):
        return True
    else:return False

def choose_unrepeat2(l1):
    l=l1.copy()
    l2=l1.copy()
    recl=[]#记录不同字母型
    lout=[]#记录输出
    for i in range(len(l)):
        if if_cross(l[i]) == False: continue
        letter_type=num2letter(l[i]) #转换为字母型
        l2[i].reverse()
        letter_type2 = num2letter(l2[i])#反序后再转换为字母型

        if letter_type in recl  or letter_type2 in recl:
            pass#如果此种字母型已有,代表是重复情况
        else:
            recl.append(letter_type)
            lout.append(l[i])
    return lout

def generate2(n):
    conf=list(itertools.product([0,1,2,3], repeat=2))#从n=3的简单情况开始
    for i in range(len(conf)):
        conf[i]=list(conf[i])#元组转换为列表
    a=conf
    for ii in range(3,n):
        a=add_one_residue(a)#增加一个点
        a=choose_unrepeat2(a)#再筛选

    print(len(a))
    if not os.path.exists('n='+str(n)+'_2D'):
        os.mkdir('n='+str(n)+'_2D')
    print('drawing')
    axx,axy=relative2absolute(a)
    draw_figures(axx,axy,n)
    output = open('n='+str(n)+'_2D_'+'data.pkl', 'wb')  #保存数据
    pickle.dump(a, output)
    return a

x=generate2(4)#简便方法

这些情况之间存在一步转换关系(即两条链只有一个点坐标不同),可画出其邻接矩阵,见下一篇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值